[Asterisk-cvs] asterisk channel.c,1.101,1.102

anthm at lists.digium.com anthm at lists.digium.com
Mon Apr 26 19:16:28 CDT 2004


Update of /usr/cvsroot/asterisk
In directory mongoose.digium.com:/tmp/cvs-serv31609

Modified Files:
	channel.c 
Log Message:
applied final release of bug 1353 per Mark's permission


Index: channel.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channel.c,v
retrieving revision 1.101
retrieving revision 1.102
diff -u -d -r1.101 -r1.102
--- channel.c	26 Apr 2004 03:02:49 -0000	1.101
+++ channel.c	26 Apr 2004 23:22:33 -0000	1.102
@@ -28,6 +28,7 @@
 #include <asterisk/channel.h>
 #include <asterisk/channel_pvt.h>
 #include <asterisk/logger.h>
+#include <asterisk/say.h>
 #include <asterisk/file.h>
 #include <asterisk/translate.h>
 #include <asterisk/manager.h>
@@ -40,7 +41,7 @@
 #include <sys/ioctl.h>
 #include <linux/zaptel.h>
 #ifndef ZT_TIMERPING
-#error "You need newer zaptel!  Please cvs update zaptel"
+#error "You need newer zaptel!	Please cvs update zaptel"
 #endif
 #endif
 
@@ -140,17 +141,19 @@
 time_t	myt;
 
 	time(&myt);
-        if (offset)
+		if (offset)
 	  chan->whentohangup = myt + offset;
-        else
-          chan->whentohangup = 0;
+		else
+		  chan->whentohangup = 0;
 	return;
 }
 
+
+
 int ast_channel_register(char *type, char *description, int capabilities,
 		struct ast_channel *(*requester)(char *type, int format, void *data))
 {
-    return ast_channel_register_ex(type, description, capabilities, requester, NULL);
+	return ast_channel_register_ex(type, description, capabilities, requester, NULL);
 }
 
 int ast_channel_register_ex(char *type, char *description, int capabilities,
@@ -271,8 +274,8 @@
 	struct ast_channel_pvt *pvt;
 	int x;
 	int flags;
-	struct varshead *headp;        
-	        
+	struct varshead *headp;		   
+			
 	
 	/* If shutting down, don't allocate any new channels */
 	if (shutting_down)
@@ -333,7 +336,7 @@
 					snprintf(tmp->uniqueid, sizeof(tmp->uniqueid), "%li.%d", (long)time(NULL), uniqueint++);
 					headp=&tmp->varshead;
 					ast_mutex_init(&tmp->lock);
-				        AST_LIST_HEAD_INIT(headp);
+						AST_LIST_HEAD_INIT(headp);
 					tmp->vars=ast_var_assign("tempvar","tempval");
 					AST_LIST_INSERT_HEAD(headp,tmp->vars,entries);
 					strncpy(tmp->context, "default", sizeof(tmp->context)-1);
@@ -461,7 +464,7 @@
 	
 }
 
-int ast_safe_sleep_conditional(	struct ast_channel *chan, int ms,
+int ast_safe_sleep_conditional( struct ast_channel *chan, int ms,
 								int (*cond)(void*), void *data )
 {
 	struct ast_frame *f;
@@ -569,13 +572,13 @@
 	/* loop over the variables list, freeing all data and deleting list items */
 	/* no need to lock the list, as the channel is already locked */
 	
-	while (!AST_LIST_EMPTY(headp)) {           /* List Deletion. */
-	            vardata = AST_LIST_FIRST(headp);
-	            AST_LIST_REMOVE_HEAD(headp, entries);
-//	            printf("deleting var %s=%s\n",ast_var_name(vardata),ast_var_value(vardata));
-	            ast_var_delete(vardata);
+	while (!AST_LIST_EMPTY(headp)) {		   /* List Deletion. */
+				vardata = AST_LIST_FIRST(headp);
+				AST_LIST_REMOVE_HEAD(headp, entries);
+//				printf("deleting var %s=%s\n",ast_var_name(vardata),ast_var_value(vardata));
+				ast_var_delete(vardata);
 	}
-	                                                 
+													 
 
 	free(chan->pvt);
 	chan->pvt = NULL;
@@ -665,7 +668,7 @@
 	}
 	if (chan->blocking) {
 		ast_log(LOG_WARNING, "Hard hangup called by thread %ld on %s, while fd "
-					"is blocked by thread %ld in procedure %s!  Expect a failure\n",
+					"is blocked by thread %ld in procedure %s!	Expect a failure\n",
 					(long)pthread_self(), chan->name, (long)chan->blocker, chan->blockproc);
 		CRASH;
 	}
@@ -681,9 +684,9 @@
 	ast_mutex_unlock(&chan->lock);
 	manager_event(EVENT_FLAG_CALL, "Hangup", 
 			"Channel: %s\r\n"
-                        "Uniqueid: %s\r\n"
-                        "Cause: %i\r\n",
-                        chan->name, chan->uniqueid, chan->hangupcause);
+						"Uniqueid: %s\r\n"
+						"Cause: %i\r\n",
+						chan->name, chan->uniqueid, chan->hangupcause);
 	ast_channel_free(chan);
 	return res;
 }
@@ -1114,7 +1117,7 @@
 			ast_log(LOG_WARNING, "Failed to perform masquerade\n");
 			f = NULL;
 		} else
-			f =  &null_frame;
+			f =	 &null_frame;
 		ast_mutex_unlock(&chan->lock);
 		return f;
 	}
@@ -1128,7 +1131,7 @@
 	}
 
 	if (!chan->deferdtmf && strlen(chan->dtmfq)) {
-		/* We have DTMF that has been deferred.  Return it now */
+		/* We have DTMF that has been deferred.	 Return it now */
 		chan->dtmff.frametype = AST_FRAME_DTMF;
 		chan->dtmff.subclass = chan->dtmfq[0];
 		/* Drop first digit */
@@ -1181,7 +1184,7 @@
 				chan->timingdata = NULL;
 				ast_mutex_unlock(&chan->lock);
 			}
-			f =  &null_frame;
+			f =	 &null_frame;
 			return f;
 		} else
 			ast_log(LOG_NOTICE, "No/unknown event '%d' on timer for '%s'?\n", blah, chan->name);
@@ -1361,10 +1364,10 @@
 		f = ast_read(chan);
 		if (f == NULL) return -1; /* if hangup */
 		if ((f->frametype == AST_FRAME_CONTROL) &&
-		    (f->subclass == AST_CONTROL_HANGUP)) return -1; /* if hangup */
-		if (f->frametype == AST_FRAME_TEXT)  /* if a text frame */
+			(f->subclass == AST_CONTROL_HANGUP)) return -1; /* if hangup */
+		if (f->frametype == AST_FRAME_TEXT)	 /* if a text frame */
 		   {
-			c = *((char *)f->data);  /* get the data */
+			c = *((char *)f->data);	 /* get the data */
 			ast_frfree(f);
 			return(c);
 		   }
@@ -1397,21 +1400,21 @@
 		 * it by doing our own generation. (PM2002)
 		 */
 		static const char* dtmf_tones[] = {
-			"!941+1336/100,!0/100",	/* 0 */
-			"!697+1209/100,!0/100",	/* 1 */
-			"!697+1336/100,!0/100",	/* 2 */
-			"!697+1477/100,!0/100",	/* 3 */
-			"!770+1209/100,!0/100",	/* 4 */
-			"!770+1336/100,!0/100",	/* 5 */
-			"!770+1477/100,!0/100",	/* 6 */
-			"!852+1209/100,!0/100",	/* 7 */
-			"!852+1336/100,!0/100",	/* 8 */
-			"!852+1477/100,!0/100",	/* 9 */
-			"!697+1633/100,!0/100",	/* A */
-			"!770+1633/100,!0/100",	/* B */
-			"!852+1633/100,!0/100",	/* C */
-			"!941+1633/100,!0/100",	/* D */
-			"!941+1209/100,!0/100",	/* * */
+			"!941+1336/100,!0/100", /* 0 */
+			"!697+1209/100,!0/100", /* 1 */
+			"!697+1336/100,!0/100", /* 2 */
+			"!697+1477/100,!0/100", /* 3 */
+			"!770+1209/100,!0/100", /* 4 */
+			"!770+1336/100,!0/100", /* 5 */
+			"!770+1477/100,!0/100", /* 6 */
+			"!852+1209/100,!0/100", /* 7 */
+			"!852+1336/100,!0/100", /* 8 */
+			"!852+1477/100,!0/100", /* 9 */
+			"!697+1633/100,!0/100", /* A */
+			"!770+1633/100,!0/100", /* B */
+			"!852+1633/100,!0/100", /* C */
+			"!941+1633/100,!0/100", /* D */
+			"!941+1209/100,!0/100", /* * */
 			"!941+1477/100,!0/100" };	/* # */
 		if (digit >= '0' && digit <='9')
 			ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
@@ -1462,7 +1465,7 @@
 	struct ast_frame *f = NULL;
 	/* Stop if we're a zombie or need a soft hangup */
 	ast_mutex_lock(&chan->lock);
-	if (chan->zombie || ast_check_hangup(chan))  {
+	if (chan->zombie || ast_check_hangup(chan))	 {
 		ast_mutex_unlock(&chan->lock);
 		return -1;
 	}
@@ -1582,7 +1585,7 @@
 		return -1;
 	}
 	
-	/* Now we have a good choice for both.  We'll write using our native format. */
+	/* Now we have a good choice for both.	We'll write using our native format. */
 	chan->pvt->rawwriteformat = native;
 	/* User perspective is fmt */
 	chan->writeformat = fmt;
@@ -1615,7 +1618,7 @@
 		return -1;
 	}
 	
-	/* Now we have a good choice for both.  We'll write using our native format. */
+	/* Now we have a good choice for both.	We'll write using our native format. */
 	chan->pvt->rawreadformat = native;
 	/* User perspective is fmt */
 	chan->readformat = fmt;
@@ -1643,7 +1646,7 @@
 			char *tmp, *var;
 			/* JDG chanvar */
 			tmp = oh->variable;
-			/* FIXME replace this call with strsep  NOT*/
+			/* FIXME replace this call with strsep	NOT*/
 			while( (var = strtok_r(NULL, "|", &tmp)) ) {
 				pbx_builtin_setvar( chan, var );
 			} /* /JDG */
@@ -1795,9 +1798,9 @@
 		strncpy(name, chan->name, sizeof(name)-1);
 		cut = strchr(name,'-');
 		if (cut)
-		        *cut = 0;
+				*cut = 0;
 		if (!strcmp(name, device))
-		        return AST_DEVICE_INUSE;
+				return AST_DEVICE_INUSE;
 		chan = ast_channel_walk(chan);
 	}
 	return AST_DEVICE_UNKNOWN;
@@ -1813,7 +1816,7 @@
 	strncpy(tech, device, sizeof(tech)-1);
 	number = strchr(tech, '/');
 	if (!number) {
-	    return AST_DEVICE_INVALID;
+		return AST_DEVICE_INVALID;
 	}
 	*number = 0;
 	number++;
@@ -2090,8 +2093,8 @@
 		clone->name, clone->_state, original->name, original->_state);
 #endif
 	/* XXX This is a seriously wacked out operation.  We're essentially putting the guts of
-	   the clone channel into the original channel.  Start by killing off the original
-	   channel's backend.   I'm not sure we're going to keep this function, because 
+	   the clone channel into the original channel.	 Start by killing off the original
+	   channel's backend.	I'm not sure we're going to keep this function, because 
 	   while the features are nice, the cost is very high in terms of pure nastiness. XXX */
 
 	/* We need the clone's lock, too */
@@ -2126,7 +2129,7 @@
 	manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\n", newn, masqn);
 	manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\n", orig, newn);
 
-	/* Swap the guts */	
+	/* Swap the guts */ 
 	p = original->pvt;
 	original->pvt = clone->pvt;
 	clone->pvt = p;
@@ -2175,7 +2178,7 @@
 	strncpy(clone->name, zombn, sizeof(clone->name) - 1);
 	manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\n", masqn, zombn);
 
-	/* Keep the same language.  */
+	/* Keep the same language.	*/
 	/* Update the type. */
 	original->type = clone->type;
 	/* Copy the FD's */
@@ -2183,7 +2186,7 @@
 		original->fds[x] = clone->fds[x];
 	}
 	/* Append variables from clone channel into original channel */
-	/* XXX Is this always correct?  We have to in order to keep MACROS working XXX */
+	/* XXX Is this always correct?	We have to in order to keep MACROS working XXX */
 	varptr = original->varshead.first;
 	if (varptr) {
 		while(varptr->entries.next) {
@@ -2200,12 +2203,12 @@
 	/* CDR fields remain the same */
 	/* XXX What about blocking, softhangup, blocker, and lock and blockproc? XXX */
 	/* Application and data remain the same */
-	/* Clone exception  becomes real one, as with fdno */
+	/* Clone exception	becomes real one, as with fdno */
 	original->exception = clone->exception;
 	original->fdno = clone->fdno;
 	/* Schedule context remains the same */
 	/* Stream stuff stays the same */
-	/* Keep the original state.  The fixup code will need to work with it most likely */
+	/* Keep the original state.	 The fixup code will need to work with it most likely */
 
 	/* dnid and callerid change to become the new, HOWEVER, we also link the original's
 	   fields back into the defunct 'clone' so that they will be freed when
@@ -2229,7 +2232,7 @@
 	   these separate */
 	original->_state = clone->_state;
 	
-	/* Context, extension, priority, app data, jump table,  remain the same */
+	/* Context, extension, priority, app data, jump table,	remain the same */
 	/* pvt switches.  pbx stays the same, as does next */
 	
 	/* Set the write format */
@@ -2327,16 +2330,73 @@
 	return 0;
 }
 
-int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
-{
-	/* Copy voice back and forth between the two channels.  Give the peer
+
+static long tvdiff(struct timeval *now,struct timeval *then) {
+	return (((now->tv_sec * 1000) + now->tv_usec / 1000) - ((then->tv_sec * 1000) + then->tv_usec / 1000));
+}
+
+static void	 bridge_playfile(struct ast_channel *chan,char *sound,int remain) {
+	int res=0,min=0,sec=0;
+	
+	if(remain > 0) {
+		if(remain / 60 > 1) {
+			min = remain / 60;
+			sec = remain % 60;
+		}
+		else {
+			sec = remain;
+		}
+	}
+	
+	if(!strcmp(sound,"timeleft")) {
+		res=ast_streamfile(chan,"vm-youhave",chan->language);
+		res = ast_waitstream(chan, "");
+		if(min) {
+			res = ast_say_number(chan,min, AST_DIGIT_ANY, chan->language);
+			res=ast_streamfile(chan,"minutes",chan->language);
+			res = ast_waitstream(chan, "");
+		}
+		if(sec) {
+			res = ast_say_number(chan,sec, AST_DIGIT_ANY, chan->language);
+			res=ast_streamfile(chan,"seconds",chan->language);
+			res = ast_waitstream(chan, "");
+		}
+	}
+	else {
+		res=ast_streamfile(chan,sound,chan->language);
+		res = ast_waitstream(chan, "");
+	}
+}
+
+int ast_channel_bridge(struct ast_channel *c0,struct ast_channel *c1,struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc) {
+	/* Copy voice back and forth between the two channels.	Give the peer
 	   the ability to transfer calls with '#<extension' syntax. */
+	int flags;
 	struct ast_channel *cs[3];
 	int to = -1;
 	struct ast_frame *f;
 	struct ast_channel *who = NULL;
-	int res;
+	int res=0;
 	int nativefailed=0;
+	struct timeval start_time,precise_now;
+	long elapsed_ms=0,time_left_ms=0;
+	int playit=0,playitagain=1,first_time=1;
+	
+
+	flags = (config->allowdisconnect||config->allowredirect_out ? AST_BRIDGE_DTMF_CHANNEL_0 : 0) + (config->allowredirect_in ? AST_BRIDGE_DTMF_CHANNEL_1 : 0);
+
+	/* timestamp */
+	gettimeofday(&start_time,NULL);
+	time_left_ms = config->timelimit;
+
+	if(config->play_to_caller && config->start_sound){
+		bridge_playfile(c0,config->start_sound,time_left_ms / 1000);
+	}
+	if(config->play_to_callee && config->start_sound){
+		bridge_playfile(c1,config->start_sound,time_left_ms / 1000);
+	}
+
+
 
 	/* Stop if we're a zombie or need a soft hangup */
 	if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) 
@@ -2366,6 +2426,57 @@
 			c0->name, c1->name, c0->uniqueid, c1->uniqueid);
 
 	for (/* ever */;;) {
+
+		/* timestamp */
+		if(config->timelimit) {
+			gettimeofday(&precise_now,NULL);
+			elapsed_ms = tvdiff(&precise_now,&start_time);
+			time_left_ms = config->timelimit - elapsed_ms;
+
+			if(playitagain && (config->play_to_caller || config->play_to_callee) && (config->play_warning && time_left_ms <= config->play_warning)) { 
+				/* narrowing down to the end */
+				if(config->warning_freq == 0) {
+					playit = 1;
+					first_time=0;
+					playitagain=0;
+				}
+				else if(first_time) {
+					playit = 1;
+					first_time=0;
+				}
+				else {
+					if((time_left_ms % config->warning_freq) <= 50) {
+						playit = 1;
+					}
+				}
+			}
+
+			if(time_left_ms <= 0) {
+				if(config->play_to_caller && config->end_sound){
+					bridge_playfile(c0,config->end_sound,0);
+				}
+
+				if(config->play_to_callee && config->end_sound){
+					bridge_playfile(c1,config->end_sound,0);
+                }
+				break;
+			}
+
+			if(time_left_ms >= 5000 && playit) {
+				if(config->play_to_caller && config->warning_sound && config->play_warning){
+					bridge_playfile(c0,config->warning_sound,time_left_ms / 1000);
+				}
+
+				if(config->play_to_callee && config->warning_sound && config->play_warning){
+					bridge_playfile(c1,config->warning_sound,time_left_ms / 1000);
+				}
+				playit = 0;
+			}
+			
+		}
+
+
+
 		/* Stop if we're a zombie or need a soft hangup */
 		if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) {
 			*fo = NULL;
@@ -2374,7 +2485,7 @@
 			ast_log(LOG_DEBUG, "Bridge stops because we're zombie or need a soft hangup: c0=%s, c1=%s, flags: %s,%s,%s,%s\n",c0->name,c1->name,c0->zombie?"Yes":"No",ast_check_hangup(c0)?"Yes":"No",c1->zombie?"Yes":"No",ast_check_hangup(c1)?"Yes":"No");
 			break;
 		}
-		if (c0->pvt->bridge && 
+		if (c0->pvt->bridge && config->timelimit==0 &&
 			(c0->pvt->bridge == c1->pvt->bridge) && !nativefailed && !c0->monitor && !c1->monitor) {
 				/* Looks like they share a bridge code */
 			if (option_verbose > 2) 




More information about the svn-commits mailing list