Add meetme talk detector (bug #3364)
authorMark Spencer <markster@digium.com>
Sun, 30 Jan 2005 03:07:21 +0000 (03:07 +0000)
committerMark Spencer <markster@digium.com>
Sun, 30 Jan 2005 03:07:21 +0000 (03:07 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4923 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_meetme.c

index 150b365..a5c81b6 100755 (executable)
@@ -19,6 +19,7 @@
 #include <asterisk/module.h>
 #include <asterisk/config.h>
 #include <asterisk/app.h>
+#include <asterisk/dsp.h>
 #include <asterisk/musiconhold.h>
 #include <asterisk/manager.h>
 #include <asterisk/options.h>
@@ -60,6 +61,7 @@ static char *descrip =
 "The option string may contain zero or more of the following characters:\n"
 "      'm' -- set monitor only mode (Listen only, no talking)\n"
 "      't' -- set talk only mode. (Talk only, no listening)\n"
+"      'T' -- set talker detection (sent to manager interface and meetme list)\n"
 "      'i' -- announce user join/leave\n"
 "      'p' -- allow user to exit the conference by pressing '#'\n"
 "      'X' -- allow user to exit the conference by entering a valid single\n"
@@ -135,6 +137,7 @@ struct ast_conf_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 */
@@ -142,7 +145,8 @@ struct ast_conf_user {
 
 #define ADMINFLAG_MUTED (1 << 1)       /* User is muted */
 #define ADMINFLAG_KICKME (1 << 2)      /* User is kicked */
-
+#define MEETME_DELAYDETECTTALK                 300
+#define MEETME_DELAYDETECTENDTALK      1000
 
 AST_MUTEX_DEFINE_STATIC(conflock);
 
@@ -177,6 +181,17 @@ static void *recordthread(void *args);
 #define CONFFLAG_MARKEDUSER (1 << 13)  /* If set, the user will be marked */
 #define CONFFLAG_INTROUSER (1 << 14)   /* If set, user will be ask record name on entry of conference */
 #define CONFFLAG_RECORDCONF (1<< 15)   /* If set, the MeetMe will be recorded */
+#define CONFFLAG_MONITORTALKER (1 << 16) /* If set, the user will be monitored if the user is talking or not */
+
+static char *istalking(int x)
+{
+       if (x > 0)
+               return "(talking)";
+       else if (x < 0)
+               return "(unmonitored)";
+       else 
+               return "(not talking)";
+}
 
 static int careful_write(int fd, unsigned char *data, int len)
 {
@@ -409,7 +424,7 @@ static int conf_cmd(int fd, int argc, char **argv) {
                /* Show all the users */
                user = cnf->firstuser;
                while(user) {
-                       ast_cli(fd, "User #: %i  Channel: %s %s %s %s\n", user->user_no, user->chan->name, (user->userflags & CONFFLAG_ADMIN) ? "(Admin)" : "", (user->userflags & CONFFLAG_MONITOR) ? "(Listen only)" : "", (user->adminflags & ADMINFLAG_MUTED) ? "(Admn Muted)" : "" );
+                       ast_cli(fd, "User #: %i  Channel: %s %s %s %s %s\n", user->user_no, user->chan->name, (user->userflags & CONFFLAG_ADMIN) ? "(Admin)" : "", (user->userflags & CONFFLAG_MONITOR) ? "(Listen only)" : "", (user->adminflags & ADMINFLAG_MUTED) ? "(Admn Muted)" : "", istalking(user->talking));
                        user = user->nextuser;
                }
                return RESULT_SUCCESS;
@@ -537,6 +552,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
        int menu_active = 0;
        int using_pseudo = 0;
        int duration=20;
+       struct ast_dsp *dsp=NULL;
 
        struct ast_app *app;
        char *agifile;
@@ -613,6 +629,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
        user->chan = chan;
        user->userflags = confflags;
        user->adminflags = 0;
+       user->talking = -1;
        ast_mutex_unlock(&conflock);
        origquiet = confflags & CONFFLAG_QUIET;
        if (confflags & CONFFLAG_EXIT_CONTEXT) {
@@ -807,6 +824,10 @@ zapretry:
                        x = 1;
                        ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
                }       
+               if (confflags &  CONFFLAG_MONITORTALKER && !(dsp = ast_dsp_new())) {
+                       ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
+                       res = -1;
+               }
                for(;;) {
                        outfd = -1;
                        ms = -1;
@@ -885,7 +906,33 @@ zapretry:
                                f = ast_read(c);
                                if (!f) 
                                        break;
-                               if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_EXIT_CONTEXT)) {
+                               if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) {
+                                       if (confflags &  CONFFLAG_MONITORTALKER) {
+                                               int totalsilence;
+                                               if (user->talking == -1)
+                                                       user->talking = 0;
+
+                                               res = ast_dsp_silence(dsp, f, &totalsilence);
+                                               if (!user->talking && totalsilence < MEETME_DELAYDETECTTALK) {
+                                                       user->talking = 1;
+                                                       manager_event(EVENT_FLAG_CALL, "MeetmeTalking",
+                                                               "Channel: %s\r\n"
+                                                               "Uniqueid: %s\r\n"
+                                                               "Meetme: %s\r\n"
+                                                               "Usernum: %i\r\n",
+                                                               chan->name, chan->uniqueid, conf->confno, user->user_no);
+                                               }
+                                               if (user->talking && totalsilence > MEETME_DELAYDETECTENDTALK) {
+                                                       user->talking = 0;
+                                                       manager_event(EVENT_FLAG_CALL, "MeetmeStopTalking",
+                                                               "Channel: %s\r\n"
+                                                               "Uniqueid: %s\r\n"
+                                                               "Meetme: %s\r\n"
+                                                               "Usernum: %i\r\n",
+                                                               chan->name, chan->uniqueid, conf->confno, user->user_no);
+                                               }
+                                       }
+                               } else if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_EXIT_CONTEXT)) {
                                        char tmp[2];
                                        tmp[0] = f->subclass;
                                        tmp[1] = '\0';
@@ -1076,6 +1123,9 @@ zapretry:
 
 outrun:
        ast_mutex_lock(&conflock);
+       if (confflags &  CONFFLAG_MONITORTALKER && dsp)
+               ast_dsp_free(dsp);
+       
        if (user->user_no) { /* Only cleanup users who really joined! */
                manager_event(EVENT_FLAG_CALL, "MeetmeLeave", 
                        "Channel: %s\r\n"
@@ -1306,6 +1356,8 @@ static int conf_exec(struct ast_channel *chan, void *data)
        if (inflags) {
                if (strchr(inflags, 'a'))
                        confflags |= CONFFLAG_ADMIN;
+               if (strchr(inflags, 'T'))
+                       confflags |= CONFFLAG_MONITORTALKER;
                if (strchr(inflags, 'i'))
                        confflags |= CONFFLAG_INTROUSER;
                if (strchr(inflags, 'm'))