[Asterisk-cvs] asterisk/apps app_chanspy.c, 1.19, 1.20 app_meetme.c, 1.103, 1.104

kpfleming kpfleming
Tue Sep 6 21:29:35 CDT 2005


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

Modified Files:
	app_chanspy.c app_meetme.c 
Log Message:
add new channel option (via ast_channel_setoption()) to let channel drivers adjust txgain/rxgain if they are able (only Zap channels at this time)
modify app_chanspy to use new gain option
reformat app_chanspy to match coding guidelines
add user-controlled volume adjustment to app_meetme (issue #4170, heavily modified to actually work on Zap channels)


Index: app_chanspy.c
===================================================================
RCS file: /usr/cvsroot/asterisk/apps/app_chanspy.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- app_chanspy.c	20 Jul 2005 00:53:21 -0000	1.19
+++ app_chanspy.c	7 Sep 2005 01:30:00 -0000	1.20
@@ -39,12 +39,10 @@
 #define AST_NAME_STRLEN 256
 #define ALL_DONE(u, ret) LOCAL_USER_REMOVE(u); return ret;
 #define get_volfactor(x) x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0
-#define minmax(x,y) x ? (x > y) ? y : ((x < (y * -1)) ? (y * -1) : x) : 0
-
 
-static char *synopsis = "Tap into any type of asterisk channel and listen to audio";
-static char *app = "ChanSpy";
-static char *desc = "   Chanspy([<scanspec>][|<options>])\n\n"
+static const char *synopsis = "Tap into any type of asterisk channel and listen to audio";
+static const char *app = "ChanSpy";
+static const char *desc = "   Chanspy([<scanspec>][|<options>])\n\n"
 "Valid Options:\n"
 " - q: quiet, don't announce channels beep, etc.\n"
 " - b: bridged, only spy on channels involved in a bridged call.\n"
@@ -237,104 +235,102 @@
 }
 #endif
 
-
 static int spy_generate(struct ast_channel *chan, void *data, int len, int samples) 
 {
 
-		struct chanspy_translation_helper *csth = data;
-		struct ast_frame frame, *f;
-		int len0 = 0, len1 = 0, samp0 = 0, samp1 = 0, x, vf, maxsamp;
-		short buf0[1280], buf1[1280], buf[1280];
+	struct chanspy_translation_helper *csth = data;
+	struct ast_frame frame, *f;
+	int len0 = 0, len1 = 0, samp0 = 0, samp1 = 0, x, vf, maxsamp;
+	short buf0[1280], buf1[1280], buf[1280];
 		
-		if (csth->spy.status == CHANSPY_DONE) {
-            return -1;
+	if (csth->spy.status == CHANSPY_DONE) {
+		return -1;
         }
 
-		ast_mutex_lock(&csth->spy.lock);
-		while((f = csth->spy.queue[0])) {
-			csth->spy.queue[0] = f->next;
-			ast_slinfactory_feed(&csth->slinfactory[0], f);
-			ast_frfree(f);
-		}
-		ast_mutex_unlock(&csth->spy.lock);
-		ast_mutex_lock(&csth->spy.lock);
-		while((f = csth->spy.queue[1])) {
-			csth->spy.queue[1] = f->next;
-			ast_slinfactory_feed(&csth->slinfactory[1], f);
-			ast_frfree(f);
-		}
-		ast_mutex_unlock(&csth->spy.lock);
+	ast_mutex_lock(&csth->spy.lock);
+	while((f = csth->spy.queue[0])) {
+		csth->spy.queue[0] = f->next;
+		ast_slinfactory_feed(&csth->slinfactory[0], f);
+		ast_frfree(f);
+	}
+	ast_mutex_unlock(&csth->spy.lock);
+	ast_mutex_lock(&csth->spy.lock);
+	while((f = csth->spy.queue[1])) {
+		csth->spy.queue[1] = f->next;
+		ast_slinfactory_feed(&csth->slinfactory[1], f);
+		ast_frfree(f);
+	}
+	ast_mutex_unlock(&csth->spy.lock);
 		
-		if (csth->slinfactory[0].size < len || csth->slinfactory[1].size < len) {
-			return 0;
-		}
+	if (csth->slinfactory[0].size < len || csth->slinfactory[1].size < len) {
+		return 0;
+	}
 		
-		if ((len0 = ast_slinfactory_read(&csth->slinfactory[0], buf0, len))) {
-			samp0 = len0 / 2;
-		} 
-		if((len1 = ast_slinfactory_read(&csth->slinfactory[1], buf1, len))) {
-			samp1 = len1 / 2;
-		}
+	if ((len0 = ast_slinfactory_read(&csth->slinfactory[0], buf0, len))) {
+		samp0 = len0 / 2;
+	} 
+	if ((len1 = ast_slinfactory_read(&csth->slinfactory[1], buf1, len))) {
+		samp1 = len1 / 2;
+	}
 
-		maxsamp = (samp0 > samp1) ? samp0 : samp1;
-		vf = get_volfactor(csth->volfactor);
-        vf = minmax(vf, 16);
+	maxsamp = (samp0 > samp1) ? samp0 : samp1;
+	vf = get_volfactor(csth->volfactor);
 		
-		for(x=0; x < maxsamp; x++) {
-			if (vf < 0) {
-				if (samp0) {
-					buf0[x] /= abs(vf);
-				}
-				if (samp1) {
-					buf1[x] /= abs(vf);
-				}
-			} else if (vf > 0) {
-				if (samp0) {
-					buf0[x] *= vf;
-				}
-				if (samp1) {
-					buf1[x] *= vf;
-				}
+	for(x=0; x < maxsamp; x++) {
+		if (vf < 0) {
+			if (samp0) {
+				buf0[x] /= abs(vf);
 			}
-			if (samp0 && samp1) {
-				if (x < samp0 && x < samp1) {
-					buf[x] = buf0[x] + buf1[x];
-				} else if (x < samp0) {
-					buf[x] = buf0[x];
-				} else if (x < samp1) {
-					buf[x] = buf1[x];
-				}
+			if (samp1) {
+				buf1[x] /= abs(vf);
+			}
+		} else if (vf > 0) {
+			if (samp0) {
+				buf0[x] *= vf;
+			}
+			if (samp1) {
+				buf1[x] *= vf;
+			}
+		}
+		if (samp0 && samp1) {
+			if (x < samp0 && x < samp1) {
+				buf[x] = buf0[x] + buf1[x];
 			} else if (x < samp0) {
 				buf[x] = buf0[x];
 			} else if (x < samp1) {
 				buf[x] = buf1[x];
 			}
+		} else if (x < samp0) {
+			buf[x] = buf0[x];
+		} else if (x < samp1) {
+			buf[x] = buf1[x];
 		}
+	}
 		
-		memset(&frame, 0, sizeof(frame));
-		frame.frametype = AST_FRAME_VOICE;
-		frame.subclass = AST_FORMAT_SLINEAR;
-		frame.data = buf;
-		frame.samples = x;
-		frame.datalen = x * 2;
+	memset(&frame, 0, sizeof(frame));
+	frame.frametype = AST_FRAME_VOICE;
+	frame.subclass = AST_FORMAT_SLINEAR;
+	frame.data = buf;
+	frame.samples = x;
+	frame.datalen = x * 2;
 
-		if (ast_write(chan, &frame)) {
-			csth->spy.status = CHANSPY_DONE;
-			return -1;
-		}
+	if (ast_write(chan, &frame)) {
+		csth->spy.status = CHANSPY_DONE;
+		return -1;
+	}
 
-		if (csth->fd) {
-			write(csth->fd, buf1, len1);
-		}
+	if (csth->fd) {
+		write(csth->fd, buf1, len1);
+	}
 
-		return 0;
+	return 0;
 }
 
 
 static struct ast_generator spygen = {
-    alloc: spy_alloc, 
-    release: spy_release, 
-    generate: spy_generate, 
+	alloc: spy_alloc, 
+	release: spy_release, 
+	generate: spy_generate, 
 };
 
 static void start_spying(struct ast_channel *chan, struct ast_channel *spychan, struct ast_channel_spy *spy) 
@@ -398,6 +394,34 @@
 
 }
 
+/* Map 'volume' levels from -4 through +4 into
+   decibel (dB) settings for channel drivers
+*/
+static signed char volfactor_map[] = {
+	-24,
+	-18,
+	-12,
+	-6,
+	0,
+	6,
+	12,
+	18,
+	24,
+};
+
+/* attempt to set the desired gain adjustment via the channel driver;
+   if successful, clear it out of the csth structure so the
+   generator will not attempt to do the adjustment itself
+*/
+static void set_volume(struct ast_channel *chan, struct chanspy_translation_helper *csth)
+{
+	signed char volume_adjust = volfactor_map[csth->volfactor + 4];
+
+	if (!ast_channel_setoption(chan, AST_OPTION_TXGAIN, &volume_adjust, sizeof(volume_adjust), 0)) {
+		csth->volfactor = 0;
+	}
+}
+
 static int channel_spy(struct ast_channel *chan, struct ast_channel *spyee, int *volfactor, int fd) 
 {
 	struct chanspy_translation_helper csth;
@@ -416,6 +440,7 @@
 		csth.spy.status = CHANSPY_RUNNING;
 		ast_mutex_init(&csth.spy.lock);
 		csth.volfactor = *volfactor;
+		set_volume(chan, &csth);
 		
 		if (fd) {
 			csth.fd = fd;
@@ -423,12 +448,12 @@
 		start_spying(spyee, chan, &csth.spy);
 		ast_activate_generator(chan, &spygen, &csth);
 
-		while(csth.spy.status == CHANSPY_RUNNING && 
-			  chan && !ast_check_hangup(chan) && 
-			  spyee && 
-			  !ast_check_hangup(spyee) 
-			  && running == 1 && 
-			  (res = ast_waitfor(chan, -1) > -1)) {
+		while (csth.spy.status == CHANSPY_RUNNING &&
+		       chan && !ast_check_hangup(chan) &&
+		       spyee &&
+		       !ast_check_hangup(spyee) &&
+		       running == 1 &&
+		       (res = ast_waitfor(chan, -1) > -1)) {
 			if ((f = ast_read(chan))) {
 				res = 0;
 				if (f->frametype == AST_FRAME_DTMF) {
@@ -456,14 +481,15 @@
 					running = x ? atoi(inp) : -1;
 					break;
 				} else {
-					csth.volfactor++;
-					if (csth.volfactor > 4) {
-						csth.volfactor = -4;
+					(*volfactor)++;
+					if (*volfactor > 4) {
+						*volfactor = -4;
 					}
 					if (option_verbose > 2) {
-						ast_verbose(VERBOSE_PREFIX_3"Setting spy volume on %s to %d\n", chan->name, csth.volfactor);
+						ast_verbose(VERBOSE_PREFIX_3 "Setting spy volume on %s to %d\n", chan->name, *volfactor);
 					}
-					*volfactor = csth.volfactor;
+					csth.volfactor = *volfactor;
+					set_volume(chan, &csth);
 				}
 			} else if (res >= 48 && res <= 57) {
 				inp[x++] = res;
@@ -483,8 +509,6 @@
 	return running;
 }
 
-
-
 static int chanspy_exec(struct ast_channel *chan, void *data)
 {
 	struct localuser *u;
@@ -560,12 +584,13 @@
 		silent = ast_test_flag(&flags, OPTION_QUIET);
 		bronly = ast_test_flag(&flags, OPTION_BRIDGED);
 		if (ast_test_flag(&flags, OPTION_VOLUME) && opts[1]) {
-			if (sscanf(opts[0], "%d", &volfactor) != 1)
-				ast_log(LOG_NOTICE, "volfactor must be a number between -4 and 4\n");
-			else {
-				volfactor = minmax(volfactor, 4);
+			int vol;
+
+			if ((sscanf(opts[0], "%d", &vol) != 1) || (vol > 4) || (vol < -4))
+				ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
+			else
+				volfactor = vol;
 			}
-		}
 	}
 
 	if (recbase) {
@@ -614,9 +639,9 @@
 				}
 				
 				if (igrp && (!spec || ((strlen(spec) < strlen(peer->name) &&
-									   !strncasecmp(peer->name, spec, strlen(spec)))))) {
+							!strncasecmp(peer->name, spec, strlen(spec)))))) {
 					if (peer && (!bronly || ast_bridged_channel(peer)) &&
-						!ast_check_hangup(peer) && !ast_test_flag(peer, AST_FLAG_SPYING)) {
+					    !ast_check_hangup(peer) && !ast_test_flag(peer, AST_FLAG_SPYING)) {
 						int x = 0;
 
 						strncpy(peer_name, peer->name, AST_NAME_STRLEN);
@@ -694,7 +719,7 @@
 
 char *description(void)
 {
-	return synopsis;
+	return (char *) synopsis;
 }
 
 int usecount(void)

Index: app_meetme.c
===================================================================
RCS file: /usr/cvsroot/asterisk/apps/app_meetme.c,v
retrieving revision 1.103
retrieving revision 1.104
diff -u -d -r1.103 -r1.104
--- app_meetme.c	8 Aug 2005 02:32:37 -0000	1.103
+++ app_meetme.c	7 Sep 2005 01:30:00 -0000	1.104
@@ -136,16 +136,19 @@
 } *confs;
 
 struct ast_conf_user {
-	int user_no;		     /* User Number */
-	struct ast_conf_user *prevuser;  /* Pointer to the previous user */
-	struct ast_conf_user *nextuser;  /* Pointer to the next user */
-	int userflags;			 /* Flags as set in the conference */
-	int adminflags;			 /* Flags set by the Admin */
-	struct ast_channel *chan; 	 /* Connected channel */
-	int talking;			 /* Is user talking */
-	char usrvalue[50];		 /* Custom User Value */
-	char namerecloc[AST_MAX_EXTENSION]; /* Name Recorded file Location */
-	time_t jointime;		 /* Time the user joined the conference */
+	int user_no;				/* User Number */
+	struct ast_conf_user *prevuser;		/* Pointer to the previous user */
+	struct ast_conf_user *nextuser;		/* Pointer to the next user */
+	int userflags;				/* Flags as set in the conference */
+	int adminflags;				/* Flags set by the Admin */
+	struct ast_channel *chan;		/* Connected channel */
+	int talking;				/* Is user talking */
+	int zapchannel;				/* Is a Zaptel channel */
+	char usrvalue[50];			/* Custom User Value */
+	char namerecloc[AST_MAX_EXTENSION];	/* Name Recorded file Location */
+	time_t jointime;			/* Time the user joined the conference */
+	int desired_volume;			/* Desired volume adjustment */
+	int actual_volume;			/* Actual volume adjustment (for channels that can't adjust) */
 };
 
 #define ADMINFLAG_MUTED (1 << 1)	/* User is muted */
@@ -153,6 +156,11 @@
 #define MEETME_DELAYDETECTTALK 		300
 #define MEETME_DELAYDETECTENDTALK 	1000
 
+enum volume_action {
+	VOL_UP,
+	VOL_DOWN,
+};
+
 AST_MUTEX_DEFINE_STATIC(conflock);
 
 static int admin_exec(struct ast_channel *chan, void *data);
@@ -251,6 +259,94 @@
 	return 0;
 }
 
+/* Map 'volume' levels from -5 through +5 into
+   decibel (dB) settings for channel drivers
+   Note: these are not a straight linear-to-dB
+   conversion... the numbers have been modified
+   to give the user a better level of adjustability
+*/
+static signed char gain_map[] = {
+	-15,
+	-13,
+	-10,
+	-6,
+	0,
+	0,
+	0,
+	6,
+	10,
+	13,
+	15,
+};
+
+static int set_volume(struct ast_conf_user *user, int volume)
+{
+	signed char gain_adjust;
+
+	/* attempt to make the adjustment in the channel driver;
+	   if successful, don't adjust in the frame reading routine
+	*/
+	gain_adjust = gain_map[volume + 5];
+	return ast_channel_setoption(user->chan, AST_OPTION_TXGAIN, &gain_adjust, sizeof(gain_adjust), 0);
+}
+
+static void tweak_volume(struct ast_conf_user *user, enum volume_action action)
+{
+	switch (action) {
+	case VOL_UP:
+		switch (user->desired_volume) {
+		case 5:
+			break;
+		case 0:
+			user->desired_volume = 2;
+			break;
+		case -2:
+			user->desired_volume = 0;
+			break;
+		default:
+			user->desired_volume++;
+			break;
+		}
+		break;
+	case VOL_DOWN:
+		switch (user->desired_volume) {
+		case -5:
+			break;
+		case 2:
+			user->desired_volume = 0;
+			break;
+		case 0:
+			user->desired_volume = -2;
+			break;
+		default:
+			user->desired_volume--;
+			break;
+		}
+	}
+	/* attempt to make the adjustment in the channel driver;
+	   if successful, don't adjust in the frame reading routine
+	*/
+	if (!set_volume(user, user->desired_volume))
+		user->actual_volume = 0;
+	else
+		user->actual_volume = user->desired_volume;
+}
+
+static void adjust_volume(struct ast_frame *f, int vol)
+{
+	int count;
+	short *fdata = f->data;
+
+	for (count = 0; count < f->datalen; count++) {
+		if (vol > 0) {
+			fdata[count] *= abs(vol);
+		} else if (vol < 0) {
+			fdata[count] /= abs(vol);
+		}
+	}
+}
+
+
 static void conf_play(struct ast_channel *chan, struct ast_conference *conf, int sound)
 {
 	unsigned char *data;
@@ -789,6 +885,7 @@
 	}
 	ast_indicate(chan, -1);
 	retryzap = strcasecmp(chan->type, "Zap");
+	user->zapchannel = retryzap;
 zapretry:
 	origfd = chan->fds[0];
 	if (retryzap) {
@@ -903,7 +1000,7 @@
 		if (!agifile)
 			agifile = agifiledefault;
 
-		if (!strcasecmp(chan->type,"Zap")) {
+		if (user->zapchannel) {
 			/*  Set CONFMUTE mode on Zap channel to mute DTMF tones */
 			x = 1;
 			ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
@@ -916,13 +1013,13 @@
 			ast_log(LOG_WARNING, "Could not find application (agi)\n");
 			ret = -2;
 		}
-		if (!strcasecmp(chan->type,"Zap")) {
+		if (user->zapchannel) {
 			/*  Remove CONFMUTE mode on Zap channel */
 			x = 0;
 			ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
 		}
 	} else {
-		if (!strcasecmp(chan->type,"Zap") && (confflags & CONFFLAG_STARMENU)) {
+		if (user->zapchannel && (confflags & CONFFLAG_STARMENU)) {
 			/*  Set CONFMUTE mode on Zap channel to mute DTMF tones when the menu is enabled */
 			x = 1;
 			ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
@@ -932,8 +1029,19 @@
 			res = -1;
 		}
 		for(;;) {
+			int menu_was_active = 0;
+
 			outfd = -1;
 			ms = -1;
+			
+			/* if we have just exited from the menu, and the user had a channel-driver
+			   volume adjustment, restore it
+			*/
+			if (!menu_active && menu_was_active && user->desired_volume && !user->actual_volume)
+				set_volume(user, user->desired_volume);
+
+			menu_was_active = menu_active;
+
 			currentmarked = conf->markedusers;
 			if (!(confflags & CONFFLAG_QUIET) && (confflags & CONFFLAG_MARKEDUSER) && (confflags & CONFFLAG_WAITMARKED) && lastmarked == 0) {
 				if (currentmarked == 1 && conf->users > 1) {
@@ -1079,6 +1187,9 @@
 				if (!f)
 					break;
 				if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) {
+					if (user->actual_volume) {
+						adjust_volume(f, user->actual_volume);
+					}
 					if (confflags &  CONFFLAG_MONITORTALKER) {
 						int totalsilence;
 						if (user->talking == -1)
@@ -1129,6 +1240,13 @@
 						ast_mutex_unlock(&conflock);
 						goto outrun;
 					}
+
+					/* if we are entering the menu, and the user has a channel-driver
+					   volume adjustment, clear it
+					*/
+					if (!menu_active && user->desired_volume && !user->actual_volume)
+						set_volume(user, 0);
+
 					if (musiconhold) {
 			   			ast_moh_stop(chan);
 					}
@@ -1189,6 +1307,19 @@
 										usr->adminflags |= ADMINFLAG_KICKME;
 									ast_stopstream(chan);
 									break;	
+
+								case '9':
+									tweak_volume(user, VOL_UP);
+									break;
+
+								case '8':
+									menu_active = 0;
+									break;
+
+								case '7':
+									tweak_volume(user, VOL_DOWN);
+									break;
+
 								default:
 									menu_active = 0;
 									/* Play an error message! */
@@ -1232,6 +1363,18 @@
 											ast_waitstream(chan, "");
 									}
 									break;
+							case '9':
+								tweak_volume(user, VOL_UP);
+								break;
+
+							case '8':
+								menu_active = 0;
+								break;
+
+							case '7':
+								tweak_volume(user, VOL_DOWN);
+								break;
+
 								default:
 									menu_active = 0;
 									/* Play an error message! */




More information about the svn-commits mailing list