[asterisk-commits] branch group/new_loader_completion r24836 - in /team/group/new_loader_complet...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Mon May 8 04:10:44 MST 2006


Author: kpfleming
Date: Fri May  5 09:44:46 2006
New Revision: 24836

URL: http://svn.digium.com/view/asterisk?rev=24836&view=rev
Log:
update to trunk, re-enable automerge (still does not build)

Added:
    team/group/new_loader_completion/funcs/func_realtime.c
      - copied unchanged from r24805, trunk/funcs/func_realtime.c
Modified:
    team/group/new_loader_completion/   (props changed)
    team/group/new_loader_completion/UPGRADE.txt
    team/group/new_loader_completion/app.c
    team/group/new_loader_completion/apps/app_chanspy.c
    team/group/new_loader_completion/apps/app_dial.c
    team/group/new_loader_completion/apps/app_page.c
    team/group/new_loader_completion/apps/app_queue.c
    team/group/new_loader_completion/apps/app_realtime.c
    team/group/new_loader_completion/apps/app_senddtmf.c
    team/group/new_loader_completion/apps/app_verbose.c
    team/group/new_loader_completion/apps/app_voicemail.c
    team/group/new_loader_completion/channel.c
    team/group/new_loader_completion/channels/chan_iax2.c
    team/group/new_loader_completion/channels/chan_sip.c
    team/group/new_loader_completion/channels/chan_zap.c
    team/group/new_loader_completion/configs/queues.conf.sample
    team/group/new_loader_completion/doc/channelvariables.txt
    team/group/new_loader_completion/doc/manager.txt
    team/group/new_loader_completion/doc/queuelog.txt
    team/group/new_loader_completion/funcs/func_channel.c
    team/group/new_loader_completion/include/asterisk/cdr.h
    team/group/new_loader_completion/pbx/ael/ael.tab.c
    team/group/new_loader_completion/pbx/ael/ael.y
    team/group/new_loader_completion/redhat/asterisk.spec
    team/group/new_loader_completion/res/res_features.c
    team/group/new_loader_completion/say.c

Propchange: team/group/new_loader_completion/
------------------------------------------------------------------------------
    automerge = *

Propchange: team/group/new_loader_completion/
------------------------------------------------------------------------------
Binary property 'branch-1.2-merged' - no diff available.

Propchange: team/group/new_loader_completion/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Fri May  5 09:44:46 2006
@@ -1,1 +1,1 @@
-/trunk:1-24346
+/trunk:1-24835

Modified: team/group/new_loader_completion/UPGRADE.txt
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/UPGRADE.txt?rev=24836&r1=24835&r2=24836&view=diff
==============================================================================
--- team/group/new_loader_completion/UPGRADE.txt (original)
+++ team/group/new_loader_completion/UPGRADE.txt Fri May  5 09:44:46 2006
@@ -73,6 +73,26 @@
   queue member channel that is taking the call. This is useful when trying 
   to link recording filenames back to a particular call from the queue.  
 
+* The old/current behavior of app_queue has a serial type behavior
+  in that the queue will make all waiting callers wait in the queue
+  even if there is more than one available member ready to take
+  calls until the head caller is connected with the member they
+  were trying to get to. The next waiting caller in line then
+  becomes the head caller, and they are then connected with the
+  next available member and all available members and waiting callers
+  waits while this happens. This cycle continues until there are
+  no more available members or waiting callers, whichever comes first.
+  The new behavior, enabled by setting autofill=yes in queues.conf
+  either at the [general] level to default for all queues or 
+  to set on a per-queue level, makes sure that when the waiting 
+  callers are connecting with available members in a parallel fashion 
+  until there are no more available members or no more waiting callers,
+  whichever comes first. This is probably more along the lines of how
+  one would expect a queue should work and in most cases, you will want 
+  to enable this new behavior. If you do not specify or comment out this 
+  option, it will default to "no" to keep backward compatability with the old 
+  behavior.
+
 Manager:
 
 * After executing the 'status' manager action, the "Status" manager events
@@ -115,6 +135,11 @@
 * The ENUMLOOKUP() function with the 'c' option (for counting the number of records),
   but the lookup fails to match any records, the returned value will now be "0" instead of blank.
 
+* The REALTIME() function is now available in version 1.4 and app_realtime has
+  been deprecated in favor of the new function. app_realtime will be removed
+  completely with the version 1.6 release so please take the time between
+  releases to make any necessary changes
+
 The IAX2 channel:
 
 * The "mailboxdetail" option has been deprecated.  Previously, if this option

Modified: team/group/new_loader_completion/app.c
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/app.c?rev=24836&r1=24835&r2=24836&view=diff
==============================================================================
--- team/group/new_loader_completion/app.c (original)
+++ team/group/new_loader_completion/app.c Fri May  5 09:44:46 2006
@@ -535,22 +535,21 @@
 static int global_silence_threshold = 128;
 static int global_maxsilence = 0;
 
-int ast_play_and_record(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int silencethreshold, int maxsilence, const char *path)
-{
-	int d;
+static int __ast_play_and_record(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int beep, int silencethreshold, int maxsilence, const char *path, int prepend)
+{
+	int d = 0;
 	char *fmts;
 	char comment[256];
-	int x, fmtcnt=1, res=-1,outmsg=0;
-	struct ast_frame *f;
+	int x, fmtcnt = 1, res = -1, outmsg = 0;
 	struct ast_filestream *others[MAX_OTHER_FORMATS];
 	char *sfmt[MAX_OTHER_FORMATS];
-	char *stringp=NULL;
+	char *stringp = NULL;
 	time_t start, end;
-	struct ast_dsp *sildet=NULL;   	/* silence detector dsp */
+	struct ast_dsp *sildet = NULL;   /* silence detector dsp */
 	int totalsilence = 0;
-	int dspsilence = 0;
-	int rfmt=0;
+	int rfmt = 0;
 	struct ast_silence_generator *silgen = NULL;
+	char prependfile[80];
 
 	if (silencethreshold < 0)
 		silencethreshold = global_silence_threshold;
@@ -565,19 +564,25 @@
 	}
 
 	ast_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 = ast_play_and_wait(chan, playfile);
+	snprintf(comment, sizeof(comment), "Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name);
+
+	if (playfile || beep) {
+		if (!beep)
+			d = ast_play_and_wait(chan, playfile);
 		if (d > -1)
 			d = ast_stream_and_wait(chan, "beep", chan->language, "");
 		if (d < 0)
 			return -1;
 	}
 
+	if (prepend) {
+		ast_copy_string(prependfile, recordfile, sizeof(prependfile));	
+		strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1);
+	}
+
 	fmts = ast_strdupa(fmt);
 
-	stringp=fmts;
+	stringp = fmts;
 	strsep(&stringp, "|");
 	ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts);
 	sfmt[0] = ast_strdupa(fmts);
@@ -591,10 +596,11 @@
 	}
 
 	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] = ast_writefile(recordfile, sfmt[x], comment, O_TRUNC, 0, 0700);
-		ast_verbose( VERBOSE_PREFIX_3 "x=%d, open writing:  %s format: %s, %p\n", x, recordfile, sfmt[x], others[x]);
+	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] = ast_writefile(prepend ? prependfile : recordfile, sfmt[x], comment, O_TRUNC, 0, 0700);
+		if (option_verbose > 2)
+			ast_verbose(VERBOSE_PREFIX_3 "x=%d, open writing:  %s format: %s, %p\n", x, prepend ? prependfile : recordfile, sfmt[x], others[x]);
 
 		if (!others[x]) {
 			break;
@@ -620,17 +626,19 @@
 		}
 	}
 
-	/* Request a video update */
-	ast_indicate(chan, AST_CONTROL_VIDUPDATE);
-
-	if (ast_opt_transmit_silence)
-		silgen = ast_channel_start_silence_generator(chan);
+	if (!prepend) {
+		/* Request a video update */
+		ast_indicate(chan, AST_CONTROL_VIDUPDATE);
+
+		if (ast_opt_transmit_silence)
+			silgen = ast_channel_start_silence_generator(chan);
+	}
 
 	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(;;) {
+		/* Loop forever, writing the packets we read to the writer(s), until
+		   we read a digit or get a hangup */
+		struct ast_frame *f;
+		for (;;) {
 		 	res = ast_waitfor(chan, 2000);
 			if (!res) {
 				ast_log(LOG_DEBUG, "One waitfor failed, trying another\n");
@@ -651,13 +659,15 @@
 				break;
 			if (f->frametype == AST_FRAME_VOICE) {
 				/* write each format */
-				for (x=0;x<fmtcnt;x++) {
+				for (x = 0; x < fmtcnt; x++) {
+					if (prepend && !others[x])
+						break;
 					res = ast_writestream(others[x], f);
 				}
 
 				/* Silence Detection */
 				if (maxsilence > 0) {
-					dspsilence = 0;
+					int dspsilence = 0;
 					ast_dsp_silence(sildet, f, &dspsilence);
 					if (dspsilence)
 						totalsilence = dspsilence;
@@ -668,28 +678,33 @@
 						/* Ended happily with silence */
 						if (option_verbose > 2)
 							ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000);
-						ast_frfree(f);
 						res = 'S';
-						outmsg=2;
+						outmsg = 2;
 						break;
 					}
 				}
 				/* Exit on any error */
 				if (res) {
 					ast_log(LOG_WARNING, "Error writing frame\n");
-					ast_frfree(f);
 					break;
 				}
 			} else if (f->frametype == AST_FRAME_VIDEO) {
 				/* Write only once */
 				ast_writestream(others[0], f);
 			} else if (f->frametype == AST_FRAME_DTMF) {
+				if (prepend) {
+				/* stop recording with any digit */
+					if (option_verbose > 2) 
+						ast_verbose(VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
+					res = 't';
+					outmsg = 2;
+					break;
+				}
 				if (f->subclass == '#') {
 					if (option_verbose > 2)
-						ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
+						ast_verbose(VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
 					res = '#';
 					outmsg = 2;
-					ast_frfree(f);
 					break;
 				}
 				if (f->subclass == '0') {
@@ -698,7 +713,6 @@
 						ast_verbose(VERBOSE_PREFIX_3 "User cancelled by pressing %c\n", f->subclass);
 					res = '0';
 					outmsg = 0;
-					ast_frfree(f);
 					break;
 				}
 			}
@@ -706,276 +720,87 @@
 				time(&end);
 				if (maxtime < (end - start)) {
 					if (option_verbose > 2)
-						ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n");
+						ast_verbose(VERBOSE_PREFIX_3 "Took too long, cutting it short...\n");
+					res = 't';
 					outmsg = 2;
-					res = 't';
-					ast_frfree(f);
 					break;
 				}
 			}
 			ast_frfree(f);
 		}
-		if (end == start) time(&end);
 		if (!f) {
 			if (option_verbose > 2)
-				ast_verbose( VERBOSE_PREFIX_3 "User hung up\n");
+				ast_verbose(VERBOSE_PREFIX_3 "User hung up\n");
 			res = -1;
-			outmsg=1;
-		}
+			outmsg = 1;
+		} else {
+			ast_frfree(f);
+		}
+		if (end == start) time(&end);
 	} else {
 		ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]);
 	}
 
-	if (silgen)
-		ast_channel_stop_silence_generator(chan, silgen);
-
+	if (!prepend) {
+		if (silgen)
+			ast_channel_stop_silence_generator(chan, silgen);
+	}
 	*duration = end - start;
 
-	for (x=0;x<fmtcnt;x++) {
-		if (!others[x])
-			break;
-		if (res > 0)
-			ast_stream_rewind(others[x], totalsilence ? totalsilence-200 : 200);
-		ast_truncstream(others[x]);
-		ast_closestream(others[x]);
-	}
-	if (rfmt && ast_set_read_format(chan, rfmt)) {
-		ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
-	}
-	if (outmsg > 1) {
-		/* Let them know recording is stopped */
-		ast_stream_and_wait(chan, "auth-thankyou", chan->language, "");
-	}
-	if (sildet)
-		ast_dsp_free(sildet);
-	return res;
-}
-
-int ast_play_and_prepend(struct ast_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 ast_frame *f;
-	struct ast_filestream *others[MAX_OTHER_FORMATS];
-	struct ast_filestream *realfiles[MAX_OTHER_FORMATS];
-	char *sfmt[MAX_OTHER_FORMATS];
-	char *stringp=NULL;
-	time_t start, end;
-	struct ast_dsp *sildet;   	/* silence detector dsp */
-	int totalsilence = 0;
-	int dspsilence = 0;
-	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) {
-		ast_log(LOG_WARNING, "Error play_and_prepend called without duration pointer\n");
-		return -1;
-	}
-
-	ast_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 = ast_play_and_wait(chan, playfile);
-		if (d > -1)
-			d = ast_stream_and_wait(chan, "beep",chan->language, "");
-		if (d < 0)
-			return -1;
-	}
-	ast_copy_string(prependfile, recordfile, sizeof(prependfile));	
-	strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1);
-			
-	fmts = ast_strdupa(fmt);
-	
-	stringp=fmts;
-	strsep(&stringp, "|");
-	ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts);	
-	sfmt[0] = ast_strdupa(fmts);
-	
-	while((fmt = strsep(&stringp, "|"))) {
-		if (fmtcnt > MAX_OTHER_FORMATS - 1) {
-			ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app.c\n");
-			break;
-		}
-		sfmt[fmtcnt++] = ast_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] = ast_writefile(prependfile, sfmt[x], comment, O_TRUNC, 0, 0700);
-		ast_verbose( VERBOSE_PREFIX_3 "x=%d, open writing:  %s format: %s, %p\n", x, prependfile, sfmt[x], others[x]);
-		if (!others[x]) {
-			break;
-		}
-	}
-	
-	sildet = ast_dsp_new(); /* Create the silence detector */
-	if (!sildet) {
-		ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
-		return -1;
-	}
-	ast_dsp_set_threshold(sildet, silencethreshold);
-
-	if (maxsilence > 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");
-			ast_dsp_free(sildet);
-			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 = ast_waitfor(chan, 2000);
-			if (!res) {
-				ast_log(LOG_DEBUG, "One waitfor failed, trying another\n");
-				/* Try one more time in case of masq */
-			 	res = ast_waitfor(chan, 2000);
-				if (!res) {
-					ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
-					res = -1;
-				}
-			}
-			
-			if (res < 0) {
-				f = NULL;
+	if (!prepend) {
+		for (x = 0; x < fmtcnt; x++) {
+			if (!others[x])
 				break;
-			}
-			f = ast_read(chan);
-			if (!f)
-				break;
-			if (f->frametype == AST_FRAME_VOICE) {
-				/* write each format */
-				for (x=0;x<fmtcnt;x++) {
-					if (!others[x])
-						break;
-					res = ast_writestream(others[x], f);
-				}
-				
-				/* Silence Detection */
-				if (maxsilence > 0) {
-					dspsilence = 0;
-					ast_dsp_silence(sildet, f, &dspsilence);
-					if (dspsilence)
-						totalsilence = dspsilence;
-					else
-						totalsilence = 0;
-					
-					if (totalsilence > maxsilence) {
-					/* Ended happily with silence */
-					if (option_verbose > 2) 
-						ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000);
-					ast_frfree(f);
-					res = 'S';
-					outmsg=2;
-					break;
-					}
-				}
-				/* Exit on any error */
-				if (res) {
-					ast_log(LOG_WARNING, "Error writing frame\n");
-					ast_frfree(f);
-					break;
-				}
-			} else if (f->frametype == AST_FRAME_VIDEO) {
-				/* Write only once */
-				ast_writestream(others[0], f);
-			} else if (f->frametype == AST_FRAME_DTMF) {
-				/* stop recording with any digit */
-				if (option_verbose > 2) 
-					ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
-				res = 't';
-				outmsg = 2;
-				ast_frfree(f);
-				break;
-			}
-			if (maxtime) {
-				time(&end);
-				if (maxtime < (end - start)) {
-					if (option_verbose > 2)
-						ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n");
-					res = 't';
-					outmsg=2;
-					ast_frfree(f);
-					break;
-				}
-			}
-			ast_frfree(f);
-		}
-		if (end == start) time(&end);
-		if (!f) {
-			if (option_verbose > 2) 
-				ast_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;
-				ast_closestream(others[x]);
-				ast_filedelete(prependfile, sfmt[x]);
-			}
-#endif
-		}
-	} else {
-		ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", prependfile, sfmt[x]); 
-	}
-	ast_dsp_free(sildet);
-	*duration = end - start;
-#if 0
-	if (outmsg > 1) {
-#else
-	if (outmsg) {
-#endif
+			if (res > 0)
+				ast_stream_rewind(others[x], totalsilence ? totalsilence-200 : 200);
+			ast_truncstream(others[x]);
+			ast_closestream(others[x]);
+		}
+	}
+
+	if (prepend && outmsg) {
+		struct ast_filestream *realfiles[MAX_OTHER_FORMATS];
 		struct ast_frame *fr;
-		for (x=0;x<fmtcnt;x++) {
+
+		for (x = 0; x < fmtcnt; x++) {
 			snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]);
 			realfiles[x] = ast_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0);
 			if (!others[x] || !realfiles[x])
 				break;
-			if (totalsilence)
-				ast_stream_rewind(others[x], totalsilence-200);
-			else
-				ast_stream_rewind(others[x], 200);
+			ast_stream_rewind(others[x], totalsilence ? totalsilence-200 : 200);
 			ast_truncstream(others[x]);
 			/* add the original file too */
 			while ((fr = ast_readframe(realfiles[x]))) {
-				ast_writestream(others[x],fr);
+				ast_writestream(others[x], fr);
+				ast_frfree(fr);
 			}
 			ast_closestream(others[x]);
 			ast_closestream(realfiles[x]);
 			ast_filerename(prependfile, recordfile, sfmt[x]);
-#if 0
-			ast_verbose("Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x],prependfile,recordfile);
-#endif
+			if (option_verbose > 3)
+				ast_verbose(VERBOSE_PREFIX_4 "Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x], prependfile, recordfile);
 			ast_filedelete(prependfile, sfmt[x]);
 		}
 	}
 	if (rfmt && ast_set_read_format(chan, rfmt)) {
 		ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
 	}
-	if (outmsg > 1) {
-		/* Let them know it worked */
+	if (outmsg == 2) {
 		ast_stream_and_wait(chan, "auth-thankyou", chan->language, "");
-	}	
+	}
+	if (sildet)
+		ast_dsp_free(sildet);
 	return res;
+}
+
+int ast_play_and_record(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int silencethreshold, int maxsilence, const char *path)
+{
+	return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, 0, silencethreshold, maxsilence, path, 0);
+}
+
+int ast_play_and_prepend(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int *duration, int beep, int silencethreshold, int maxsilence)
+{
+	return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, beep, silencethreshold, maxsilence, NULL, 1);
 }
 
 /* Channel group core functions */

Modified: team/group/new_loader_completion/apps/app_chanspy.c
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/apps/app_chanspy.c?rev=24836&r1=24835&r2=24836&view=diff
==============================================================================
--- team/group/new_loader_completion/apps/app_chanspy.c (original)
+++ team/group/new_loader_completion/apps/app_chanspy.c Fri May  5 09:44:46 2006
@@ -73,7 +73,7 @@
 "  Options:\n"
 "    b - Only spy on channels involved in a bridged call.\n"
 "    g(grp) - Match only channels where their ${SPYGROUP} variable is set to\n"
-"             'grp'.\n"
+"             contain 'grp' in an optional : delimited list.\n"
 "    q - Don't play a beep when beginning to spy on a channel.\n"
 "    r[(basename)] - Record the session to the monitor spool directory. An\n"
 "                    optional base for the filename may be specified. The\n"
@@ -413,7 +413,7 @@
 			spec = NULL;
 		}
 	}
-	
+
 	if (options) {
 		char *opts[OPT_ARG_ARRAY_SIZE];
 		ast_app_parse_options(chanspy_opts, &flags, opts, options);
@@ -470,18 +470,34 @@
 			if (peer != chan) {
 				const char *group = NULL;
 				int igrp = 1;
-
+				char *groups[25] = {0};
+				int num_groups = 0;
+				char *dup_group;
+				
 				if (peer == prev && !chosen) {
 					break;
 				}
 				chosen = 0;
-				group = pbx_builtin_getvar_helper(peer, "SPYGROUP");
+
 				if (mygroup) {
-					if (!group || strcmp(mygroup, group)) {
-						igrp = 0;
+					int x;
+
+					if ((group = pbx_builtin_getvar_helper(peer, "SPYGROUP"))) {
+						dup_group = ast_strdupa(group);
+						num_groups = ast_app_separate_args(dup_group, ':', groups, sizeof(groups) / sizeof(groups[0]));
 					}
+
+					igrp = 0;
+					if (num_groups) {
+						for (x = 0; x < num_groups; x++) {
+							if (!strcmp(mygroup, groups[x])) {
+								igrp = 1;
+								break;
+							}
+						}
+					} 
 				}
-				
+
 				if (igrp && (!spec || ((strlen(spec) <= strlen(peer->name) &&
 							!strncasecmp(peer->name, spec, strlen(spec)))))) {
 					if (peer && (!bronly || ast_bridged_channel(peer)) &&

Modified: team/group/new_loader_completion/apps/app_dial.c
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/apps/app_dial.c?rev=24836&r1=24835&r2=24836&view=diff
==============================================================================
--- team/group/new_loader_completion/apps/app_dial.c (original)
+++ team/group/new_loader_completion/apps/app_dial.c Fri May  5 09:44:46 2006
@@ -113,7 +113,8 @@
 "    G(context^exten^pri) - If the call is answered, transfer the calling party to\n"
 "           the specified priority and the called party to the specified priority+1.\n"
 "           Optionally, an extension, or extension and context may be specified. \n"
-"           Otherwise, the current extension is used.\n"
+"           Otherwise, the current extension is used. You cannot use any additional\n"
+"           action post answer options in conjunction with this option.\n" 
 "    h    - Allow the called party to hang up by sending the '*' DTMF digit.\n"
 "    H    - Allow the calling party to hang up by hitting the '*' DTMF digit.\n"
 "    j    - Jump to priority n+101 if all of the requested channels were busy.\n"
@@ -146,6 +147,8 @@
 "           * GOTO:<context>^<exten>^<priority> - Transfer the call to the\n"
 "                          specified priority. Optionally, an extension, or\n"
 "                          extension and priority can be specified.\n"
+"           You cannot use any additional action post answer options in conjunction\n"
+"           with this option.\n"
 "    n    - This option is a modifier for the screen/privacy mode. It specifies\n"
 "           that no introductions are to be saved in the priv-callerintros\n"
 "           directory.\n"

Modified: team/group/new_loader_completion/apps/app_page.c
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/apps/app_page.c?rev=24836&r1=24835&r2=24836&view=diff
==============================================================================
--- team/group/new_loader_completion/apps/app_page.c (original)
+++ team/group/new_loader_completion/apps/app_page.c Fri May  5 09:44:46 2006
@@ -60,17 +60,20 @@
 "caller is dumped into the conference as a speaker and the room is\n"
 "destroyed when the original caller leaves.  Valid options are:\n"
 "        d - full duplex audio\n"
-"	 q - quiet, do not play beep to caller\n";
+"	 q - quiet, do not play beep to caller\n"
+"        r - record the page into a file (see 'r' for app_meetme)\n";
 
 
 enum {
 	PAGE_DUPLEX = (1 << 0),
 	PAGE_QUIET = (1 << 1),
+	PAGE_RECORD = (1 << 2),
 } page_opt_flags;
 
 AST_APP_OPTIONS(page_opts, {
 	AST_APP_OPTION('d', PAGE_DUPLEX),
 	AST_APP_OPTION('q', PAGE_QUIET),
+	AST_APP_OPTION('r', PAGE_RECORD),
 });
 
 struct calloutdata {
@@ -176,7 +179,8 @@
 	if (options)
 		ast_app_parse_options(page_opts, &flags, NULL, options);
 
-	snprintf(meetmeopts, sizeof(meetmeopts), "%ud|%sqxdw", confid, ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "m");
+	snprintf(meetmeopts, sizeof(meetmeopts), "%ud|%s%sqxdw", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "m"),
+		(ast_test_flag(&flags, PAGE_RECORD) ? "r" : "") );
 
 	while ((tech = strsep(&tmp, "&"))) {
 		/* don't call the originating device */
@@ -197,7 +201,8 @@
 			res = ast_waitstream(chan, "");
 	}
 	if (!res) {
-		snprintf(meetmeopts, sizeof(meetmeopts), "%ud|A%sqxd", confid, ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "t");
+		snprintf(meetmeopts, sizeof(meetmeopts), "%ud|A%s%sqxd", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "t"), 
+			(ast_test_flag(&flags, PAGE_RECORD) ? "r" : "") );
 		pbx_exec(chan, app, meetmeopts);
 	}
 

Modified: team/group/new_loader_completion/apps/app_queue.c
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/apps/app_queue.c?rev=24836&r1=24835&r2=24836&view=diff
==============================================================================
--- team/group/new_loader_completion/apps/app_queue.c (original)
+++ team/group/new_loader_completion/apps/app_queue.c Fri May  5 09:44:46 2006
@@ -234,6 +234,9 @@
 /*! \brief queues.conf per-queue weight option */
 static int use_weight = 0;
 
+/*! \brief queues.conf [general] option */
+static int autofill_default = 0;
+
 enum queue_result {
 	QUEUE_UNKNOWN = 0,
 	QUEUE_TIMEOUT = 1,
@@ -302,7 +305,8 @@
 	int status;			/*!< Status of queue member */
 	int paused;			/*!< Are we paused (not accepting calls)? */
 	time_t lastcall;		/*!< When last successful call was hungup */
-	int dead;			/*!< Used to detect members deleted in realtime */
+	unsigned int dead:1;			/*!< Used to detect members deleted in realtime */
+	unsigned int delme:1;		/*!< Flag to delete entry on reload */
 	struct member *next;		/*!< Next member */
 };
 
@@ -574,6 +578,7 @@
 	q->roundingseconds = 0; /* Default - don't announce seconds */
 	q->servicelevel = 0;
 	q->ringinuse = 1;
+	q->autofill = autofill_default;
 	q->moh[0] = '\0';
 	q->announce[0] = '\0';
 	q->context[0] = '\0';
@@ -1846,6 +1851,7 @@
 		if (!*to) {
 			if (option_verbose > 2)
 				ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
+			ast_queue_log(qe->parent->name, qe->chan->uniqueid, on, "RINGNOANSWER", "%d", orig);
 			if (qe->parent->autopause) {
 				if (!set_member_paused(qe->parent->name, on, 1)) {
 					if (option_verbose > 2)
@@ -1859,25 +1865,75 @@
 	}
 
 	return peer;
+	
 }
 
 static int is_our_turn(struct queue_ent *qe)
 {
 	struct queue_ent *ch;
+	struct member *cur;
+	int avl = 0;
+	int idx = 0;
 	int res;
 
-	/* Atomically read the parent head -- does not need a lock */
-	ch = qe->parent->head;
-	/* If we are now at the top of the head, break out */
-	if ((ch == qe) || (qe->parent->autofill)) {
+	if (!qe->parent->autofill) {
+
+		/* Atomically read the parent head -- does not need a lock */
+		ch = qe->parent->head;
+		/* If we are now at the top of the head, break out */
+		if ((ch == qe) || (qe->parent->autofill)) {
+			if (option_debug)
+				ast_log(LOG_DEBUG, "It's our turn (%s).\n", qe->chan->name);
+			res = 1;
+		} else {
+			if (option_debug)
+				ast_log(LOG_DEBUG, "It's not our turn (%s).\n", qe->chan->name);
+			res = 0;
+		}	
+
+	} else {
+
+		/* This needs a lock. How many members are available to be served? */
+	
+		ast_mutex_lock(&qe->parent->lock);
+			
+		ch = qe->parent->head;
+		cur = qe->parent->members;
+	
+		while (cur) {
+			if (cur->status == 1) 
+				avl++;
+			cur = cur->next;
+		}
+
 		if (option_debug)
-			ast_log(LOG_DEBUG, "It's our turn (%s).\n", qe->chan->name);
-		res = 1;
-	} else {
-		if (option_debug)
-			ast_log(LOG_DEBUG, "It's not our turn (%s).\n", qe->chan->name);
-		res = 0;
-	}
+			ast_log(LOG_DEBUG, "There are %d available members.\n", avl);
+	
+		if (qe->parent->strategy == 1) {
+			if (option_debug)
+				ast_log(LOG_DEBUG, "Even though there are %d available members, the strategy is ringall so only the head call is allowed in!\n", avl);
+			avl = 1;
+		}
+	
+		while ((idx < avl) && (ch) && (ch != qe)) {
+			idx++;
+			ch = ch->next;			
+		}
+	
+		/* If the queue entry is within avl [the number of available members] calls from the top ... */
+		if (ch && idx < avl) {
+			if (option_debug)
+				ast_log(LOG_DEBUG, "It's our turn (%s).\n", qe->chan->name);
+			res = 1;
+		} else {
+			if (option_debug)
+				ast_log(LOG_DEBUG, "It's not our turn (%s).\n", qe->chan->name);
+			res = 0;
+		}
+		
+		ast_mutex_unlock(&qe->parent->lock);
+	}
+
 	return res;
 }
 
@@ -1904,6 +1960,7 @@
 		/* leave the queue if no agents, if enabled */
 		if (qe->parent->leavewhenempty && (stat == QUEUE_NO_MEMBERS)) {
 			*reason = QUEUE_LEAVEEMPTY;
+			ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long)time(NULL) - qe->start);
 			leave_queue(qe);
 			break;
 		}
@@ -1911,6 +1968,7 @@
 		/* leave the queue if no reachable agents, if enabled */
 		if ((qe->parent->leavewhenempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) {
 			*reason = QUEUE_LEAVEUNAVAIL;
+			ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long)time(NULL) - qe->start);
 			leave_queue(qe);
 			break;
 		}
@@ -2258,7 +2316,8 @@
 		bridge = ast_bridge_call(qe->chan,peer, &bridge_config);
 
 		if (strcasecmp(oldcontext, qe->chan->context) || strcasecmp(oldexten, qe->chan->exten)) {
-			ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "TRANSFER", "%s|%s", qe->chan->exten, qe->chan->context);
+			ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "TRANSFER", "%s|%s|%ld|%ld", 
+					  qe->chan->exten, qe->chan->context, (long)(callstart - qe->start), (long)(time(NULL) - callstart));
 		} else if (qe->chan->_softhangup) {
 			ast_queue_log(queuename, qe->chan->uniqueid, peer->name, "COMPLETECALLER", "%ld|%ld",
 				      (long)(callstart - qe->start), (long)(time(NULL) - callstart));
@@ -2942,7 +3001,7 @@
 			if (res < 0) {
 				/* Record this abandoned call */
 				record_abandoned(&qe);
-				 ast_queue_log(args.queuename, chan->uniqueid, "NONE", "ABANDON", "%d|%d|%ld", qe.pos, qe.opos, (long)time(NULL) - qe.start);
+				ast_queue_log(args.queuename, chan->uniqueid, "NONE", "ABANDON", "%d|%d|%ld", qe.pos, qe.opos, (long)time(NULL) - qe.start);
 				if (option_verbose > 2) {
 					ast_verbose(VERBOSE_PREFIX_3 "User disconnected from queue %s while waiting their turn\n", args.queuename);
 				}
@@ -3275,7 +3334,7 @@
 	struct ast_config *cfg;
 	char *cat, *tmp;
 	struct ast_variable *var;
-	struct member *prev, *cur;
+	struct member *prev, *cur, *newm;
 	int new;
 	char *general_val = NULL;
 	char interface[80];
@@ -3301,6 +3360,9 @@
 			queue_persistent_members = 0;
 			if ((general_val = ast_variable_retrieve(cfg, "general", "persistentmembers")))
 				queue_persistent_members = ast_true(general_val);
+			autofill_default = 0;
+			if ((general_val = ast_variable_retrieve(cfg, "general", "autofill")))
+				autofill_default = ast_true(general_val);
 		} else {	/* Define queue */
 			/* Look for an existing one */
 			AST_LIST_TRAVERSE(&queues, q, list) {
@@ -3321,12 +3383,10 @@
 				/* Re-initialize the queue, and clear statistics */
 				init_queue(q);
 				clear_queue(q);
-				free_members(q, 0);
-				prev = q->members;
-				if (prev) {
-					/* find the end of any dynamic members */
-					while(prev->next)
-						prev = prev->next;
+				for (cur = q->members; cur; cur = cur->next) {
+					if (!cur->dynamic) {
+						cur->delme = 1;
+					}
 				}
 				for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
 					if (!strcasecmp(var->name, "member")) {
@@ -3341,18 +3401,52 @@
 							}
 						} else
 							penalty = 0;
-						cur = create_queue_member(interface, penalty, 0);
+
+						/* Find the old position in the list */
+						for (prev = NULL, cur = q->members; cur; prev = cur, cur = cur->next) {
+							if (!strcmp(cur->interface, interface)) {
+								break;
+							}
+						}
+
+						newm = create_queue_member(interface, penalty, cur ? cur->paused : 0);
+
 						if (cur) {
-							if (prev)
-								prev->next = cur;
-							else
-								q->members = cur;
-							prev = cur;
+							/* Delete it now */
+							newm->next = cur->next;
+							if (prev) {
+								prev->next = newm;
+							} else {
+								q->members = newm;
+							}
+							free(cur);
+						} else {
+							newm->next = q->members;
+							q->members = newm;
 						}
 					} else {
 						queue_set_param(q, var->name, var->value, var->lineno, 1);
 					}
 				}
+
+				/* Free remaining members marked as delme */
+				for (prev = NULL, newm = NULL, cur = q->members; cur; prev = cur, cur = cur->next) {
+					if (newm) {
+						free(newm);
+						newm = NULL;
+					}
+
+					if (cur->delme) {
+						if (prev) {
+							prev->next = cur->next;
+							newm = cur;
+						} else {
+							q->members = cur->next;
+							newm = cur;
+						}
+					}
+				}
+
 				if (new) {
 					AST_LIST_INSERT_HEAD(&queues, q, list);
 				} else

Modified: team/group/new_loader_completion/apps/app_realtime.c
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/apps/app_realtime.c?rev=24836&r1=24835&r2=24836&view=diff
==============================================================================
--- team/group/new_loader_completion/apps/app_realtime.c (original)
+++ team/group/new_loader_completion/apps/app_realtime.c Fri May  5 09:44:46 2006
@@ -139,6 +139,8 @@
 	int res = 0, count = 0;
 	char countc[13];
 
+        ast_log(LOG_WARNING, "The RealTimeUpdate application has been deprecated in favor of the REALTIME dialplan function.\n");
+
 	if (ast_strlen_zero(data)) {
 		ast_log(LOG_ERROR,"Invalid input: usage %s\n",UUSAGE);
 		return -1;
@@ -184,6 +186,8 @@
 	char countc[13];
 	size_t len;
 		
+        ast_log(LOG_WARNING, "The RealTime application has been deprecated in favor of the REALTIME dialplan function.\n");
+
 	if (ast_strlen_zero(data)) {
 		ast_log(LOG_ERROR,"Invalid input: usage %s\n",USAGE);
 		return -1;

Modified: team/group/new_loader_completion/apps/app_senddtmf.c
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/apps/app_senddtmf.c?rev=24836&r1=24835&r2=24836&view=diff
==============================================================================
--- team/group/new_loader_completion/apps/app_senddtmf.c (original)
+++ team/group/new_loader_completion/apps/app_senddtmf.c Fri May  5 09:44:46 2006
@@ -43,6 +43,7 @@
 #include "asterisk/options.h"
 #include "asterisk/utils.h"
 #include "asterisk/app.h"
+#include "asterisk/manager.h"
 
 static char *tdesc = "Send DTMF digits Application";
 
@@ -82,7 +83,7 @@
 		timeout = atoi(to);
 	}
 		
-	if(timeout <= 0)
+	if (timeout <= 0)
 		timeout = 250;
 
 	res = ast_dtmf_stream(chan,NULL,digits,timeout);
@@ -92,11 +93,43 @@
 	return res;
 }
 
+static char mandescr_playdtmf[] =
+"Description: Plays a dtmf digit on the specified channel.\n"
+"Variables: (all are required)\n"
+"	Channel: Channel name to send digit to\n"
+"	Digit: The dtmf digit to play\n";
+
+static int manager_play_dtmf(struct mansession *s, struct message *m)
+{
+	char *channel = astman_get_header(m, "Channel");
+	char *digit = astman_get_header(m, "Digit");
+	struct ast_channel *chan = ast_get_channel_by_name_locked(channel);
+	
+	if (!chan) {
+		astman_send_error(s, m, "Channel not specified");
+		ast_mutex_unlock(&chan->lock);
+		return 0;
+	}
+	if (!digit) {
+		astman_send_error(s, m, "No digit specified");
+		ast_mutex_unlock(&chan->lock);
+		return 0;
+	}
+
+	ast_senddigit(chan, *digit);
+
+	ast_mutex_unlock(&chan->lock);
+	astman_send_ack(s, m, "DTMF successfully queued");
+	
+	return 0;
+}
+
 static int unload_module(void)
 {
 	int res;
 
 	res = ast_unregister_application(app);
+	res |= ast_manager_unregister("PlayDTMF");
 
 	ast_module_user_hangup_all();
 
@@ -105,7 +138,12 @@
 
 static int load_module(void)
 {
-	return ast_register_application(app, senddtmf_exec, synopsis, descrip);
+	int res;
+
+	res = ast_manager_register2( "PlayDTMF", EVENT_FLAG_CALL, manager_play_dtmf, "Play DTMF signal on a specific channel.", mandescr_playdtmf );
+	res |= ast_register_application(app, senddtmf_exec, synopsis, descrip);
+
+	return res;
 }
 
 static const char *description(void)

Modified: team/group/new_loader_completion/apps/app_verbose.c
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/apps/app_verbose.c?rev=24836&r1=24835&r2=24836&view=diff
==============================================================================
--- team/group/new_loader_completion/apps/app_verbose.c (original)
+++ team/group/new_loader_completion/apps/app_verbose.c Fri May  5 09:44:46 2006
@@ -65,7 +65,7 @@
 
 	if (data) {
 		if ((vtext = ast_strdupa(data))) {
-			char *tmp = strsep(&vtext, "|,");
+			char *tmp = strsep(&vtext, "|");
 			if (vtext) {
 				if (sscanf(tmp, "%d", &vsize) != 1) {
 					vsize = 0;

Modified: team/group/new_loader_completion/apps/app_voicemail.c
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/apps/app_voicemail.c?rev=24836&r1=24835&r2=24836&view=diff
==============================================================================
--- team/group/new_loader_completion/apps/app_voicemail.c (original)
+++ team/group/new_loader_completion/apps/app_voicemail.c Fri May  5 09:44:46 2006
@@ -854,8 +854,8 @@
 	char full_fn[256];
 	char msgnums[80];
 	
-	odbc_obj *obj;
-	obj = fetch_odbc_obj(odbc_database, 0);
+	struct odbc_obj *obj;
+	obj = odbc_request_obj(odbc_database, 0);
 	if (obj) {
 		ast_copy_string(fmt, vmfmts, sizeof(fmt));
 		c = strchr(fmt, '|');
@@ -874,6 +874,7 @@
 		res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
 		if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 			ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
+			odbc_release_obj(obj);
 			goto yuck;
 		}
 		snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE dir=? AND msgnum=?",odbc_table);
@@ -881,6 +882,7 @@
 		if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 			ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
 			SQLFreeHandle (SQL_HANDLE_STMT, stmt);
+			odbc_release_obj(obj);
 			goto yuck;
 		}
 		SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(dir), 0, (void *)dir, 0, NULL);
@@ -889,28 +891,33 @@
 		if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 			ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
 			SQLFreeHandle (SQL_HANDLE_STMT, stmt);

[... 4552 lines stripped ...]


More information about the asterisk-commits mailing list