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! */

_______________________________________________
Asterisk-Cvs mailing list
[email protected]
http://lists.digium.com/mailman/listinfo/asterisk-cvs

Reply via email to