Adding a new option to Chanspy(). The 'd' option allows for the spy to
authorMark Michelson <mmichelson@digium.com>
Wed, 14 May 2008 22:15:12 +0000 (22:15 +0000)
committerMark Michelson <mmichelson@digium.com>
Wed, 14 May 2008 22:15:12 +0000 (22:15 +0000)
press DTMF digits to switch between spying modes. Pressing 4 activates spy mode,
pressing 5 activates whisper mode, and pressing 6 activates barge mode. Use of
this feature overrides the normal operation of DTMF numbers.

This feature is courtesy of Switchvox.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@116522 65c4cc65-6c06-0410-ace0-fbb531ad65f3

CHANGES
apps/app_chanspy.c

diff --git a/CHANGES b/CHANGES
index 9526521..728f8bc 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -59,6 +59,11 @@ Application Changes
    to be spoken instead of the channel name or number. For more information on the
    use of this option, issue the command "core show application ChanSpy" from the 
    Asterisk CLI.
+ * Chanspy has a new option, 'd', which allows the spy to use DTMF to swap between
+   spy modes. Use of this feature overrides the typical use of numeric DTMF. In other
+   words, if using the 'd' option, it is not possible to enter a number to append to
+   the first argument to Chanspy(). Pressing 4 will change to spy mode, pressing 5 will
+   change to whisper mode, and pressing 6 will change to barge mode.
 
 SIP Changes
 -----------
index e86f965..75d4851 100644 (file)
@@ -64,7 +64,8 @@ static const char *desc_chan =
 "    - Dialing a series of digits followed by # builds a channel name to append\n"
 "      to 'chanprefix'. For example, executing ChanSpy(Agent) and then dialing\n"
 "      the digits '1234#' while spying will begin spying on the channel\n"
-"      'Agent/1234'.\n"
+"      'Agent/1234'. Note that this feature will be overriden if the 'd' option\n"
+"       is used\n"
 "  Note: The X option supersedes the three features above in that if a valid\n"
 "        single digit extension exists in the correct context ChanSpy will\n"
 "        exit to it. This also disables choosing a channel based on 'chanprefix'\n"
@@ -73,6 +74,11 @@ static const char *desc_chan =
 "    b                      - Only spy on channels involved in a bridged call.\n"
 "    B                      - Instead of whispering on a single channel barge in on both\n"
 "                             channels involved in the call.\n"
+"    d                      - Override the typical numeric DTMF functionality and instead\n"
+"                             use DTMF to switch between spy modes.\n"
+"                                     4 = spy mode\n"
+"                                     5 = whisper mode\n"
+"                                     6 = barge mode\n"
 "    g(grp)                 - Only spy on channels in which one or more of the groups \n"
 "                             listed in 'grp' matches one or more groups from the\n"
 "                             SPYGROUP variable set on the channel to be spied upon.\n"
@@ -126,6 +132,13 @@ static const char *desc_ext =
 "        exit to it.\n"
 "  Options:\n"
 "    b                      - Only spy on channels involved in a bridged call.\n"
+"    B                      - Instead of whispering on a single channel barge in on both\n"
+"                             channels involved in the call.\n"
+"    d                      - Override the typical numeric DTMF functionality and instead\n"
+"                             use DTMF to switch between spy modes.\n"
+"                                     4 = spy mode\n"
+"                                     5 = whisper mode\n"
+"                                     6 = barge mode\n"
 "    g(grp)                 - Only spy on channels in which one or more of the groups \n"
 "                             listed in 'grp' matches one or more groups from the\n"
 "                             SPYGROUP variable set on the channel to be spied upon.\n"
@@ -162,19 +175,20 @@ static const char *desc_ext =
 ;
 
 enum {
-       OPTION_QUIET     = (1 << 0),    /* Quiet, no announcement */
-       OPTION_BRIDGED   = (1 << 1),    /* Only look at bridged calls */
-       OPTION_VOLUME    = (1 << 2),    /* Specify initial volume */
-       OPTION_GROUP     = (1 << 3),    /* Only look at channels in group */
-       OPTION_RECORD    = (1 << 4),
-       OPTION_WHISPER   = (1 << 5),
-       OPTION_PRIVATE   = (1 << 6),    /* Private Whisper mode */
-       OPTION_READONLY  = (1 << 7),    /* Don't mix the two channels */
-       OPTION_EXIT      = (1 << 8),    /* Exit to a valid single digit extension */
-       OPTION_ENFORCED  = (1 << 9),    /* Enforced mode */
-       OPTION_NOTECH    = (1 << 10),   /* Skip technology name playback */
-       OPTION_BARGE     = (1 << 11),   /* Barge mode (whisper to both channels) */
-       OPTION_NAME      = (1 << 12),   /* Say the name of the person on whom we will spy */
+       OPTION_QUIET             = (1 << 0),    /* Quiet, no announcement */
+       OPTION_BRIDGED           = (1 << 1),    /* Only look at bridged calls */
+       OPTION_VOLUME            = (1 << 2),    /* Specify initial volume */
+       OPTION_GROUP             = (1 << 3),    /* Only look at channels in group */
+       OPTION_RECORD            = (1 << 4),
+       OPTION_WHISPER           = (1 << 5),
+       OPTION_PRIVATE           = (1 << 6),    /* Private Whisper mode */
+       OPTION_READONLY          = (1 << 7),    /* Don't mix the two channels */
+       OPTION_EXIT              = (1 << 8),    /* Exit to a valid single digit extension */
+       OPTION_ENFORCED          = (1 << 9),    /* Enforced mode */
+       OPTION_NOTECH            = (1 << 10),   /* Skip technology name playback */
+       OPTION_BARGE             = (1 << 11),   /* Barge mode (whisper to both channels) */
+       OPTION_NAME              = (1 << 12),   /* Say the name of the person on whom we will spy */
+       OPTION_DTMF_SWITCH_MODES = (1 << 13),   /*Allow numeric DTMF to switch between chanspy modes */
 } chanspy_opt_flags;
 
 enum {
@@ -200,6 +214,7 @@ AST_APP_OPTIONS(spy_opts, {
        AST_APP_OPTION('X', OPTION_EXIT),
        AST_APP_OPTION('s', OPTION_NOTECH),
        AST_APP_OPTION_ARG('n', OPTION_NAME, OPT_ARG_NAME),
+       AST_APP_OPTION('d', OPTION_DTMF_SWITCH_MODES),
 });
 
 
@@ -281,8 +296,22 @@ struct chanspy_ds {
        ast_mutex_t lock;
 };
 
+static void change_spy_mode(const char digit, struct ast_flags *flags)
+{
+       if (digit == '4') {
+               ast_clear_flag(flags, OPTION_WHISPER);
+               ast_clear_flag(flags, OPTION_BARGE);
+       } else if (digit == '5') {
+               ast_clear_flag(flags, OPTION_BARGE);
+               ast_set_flag(flags, OPTION_WHISPER);
+       } else if (digit == '6') {
+               ast_clear_flag(flags, OPTION_WHISPER);
+               ast_set_flag(flags, OPTION_BARGE);
+       }
+}
+
 static int channel_spy(struct ast_channel *chan, struct chanspy_ds *spyee_chanspy_ds, 
-       int *volfactor, int fd, const struct ast_flags *flags, char *exitcontext) 
+       int *volfactor, int fd, struct ast_flags *flags, char *exitcontext) 
 {
        struct chanspy_translation_helper csth;
        int running = 0, res, x = 0;
@@ -327,15 +356,14 @@ static int channel_spy(struct ast_channel *chan, struct chanspy_ds *spyee_chansp
                return 0;
        }
 
-       if (ast_test_flag(flags, OPTION_BARGE)) {
-               ast_audiohook_init(&csth.whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "ChanSpy");
-               ast_audiohook_init(&csth.bridge_whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "Chanspy");
-               start_spying(spyee, spyer_name, &csth.whisper_audiohook); /* Unlocks spyee */
-               start_spying(ast_bridged_channel(spyee), spyer_name, &csth.bridge_whisper_audiohook);
-       } else if (ast_test_flag(flags, OPTION_WHISPER)) {
-               ast_audiohook_init(&csth.whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "ChanSpy");
-               start_spying(spyee, spyer_name, &csth.whisper_audiohook); /* Unlocks spyee */
-       }
+       ast_channel_lock(chan);
+       ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
+       ast_channel_unlock(chan);
+
+       ast_audiohook_init(&csth.whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "ChanSpy");
+       ast_audiohook_init(&csth.bridge_whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "Chanspy");
+       start_spying(spyee, spyer_name, &csth.whisper_audiohook); /* Unlocks spyee */
+       start_spying(ast_bridged_channel(spyee), spyer_name, &csth.bridge_whisper_audiohook);
 
        ast_channel_unlock(spyee);
        spyee = NULL;
@@ -417,7 +445,11 @@ static int channel_spy(struct ast_channel *chan, struct chanspy_ds *spyee_chansp
                                ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
                        }
                } else if (res >= '0' && res <= '9') {
-                       inp[x++] = res;
+                       if (ast_test_flag(flags, OPTION_DTMF_SWITCH_MODES)) {
+                               change_spy_mode(res, flags);
+                       } else {
+                               inp[x++] = res;
+                       }
                }
 
                if (res == '*') {
@@ -445,21 +477,18 @@ static int channel_spy(struct ast_channel *chan, struct chanspy_ds *spyee_chansp
        else
                ast_deactivate_generator(chan);
 
-       if (ast_test_flag(flags, OPTION_BARGE)) {
-               ast_audiohook_lock(&csth.whisper_audiohook);
-               ast_audiohook_detach(&csth.whisper_audiohook);
-               ast_audiohook_unlock(&csth.whisper_audiohook);
-               ast_audiohook_destroy(&csth.whisper_audiohook);
-               ast_audiohook_lock(&csth.bridge_whisper_audiohook);
-               ast_audiohook_detach(&csth.bridge_whisper_audiohook);
-               ast_audiohook_unlock(&csth.bridge_whisper_audiohook);
-               ast_audiohook_destroy(&csth.bridge_whisper_audiohook);
-       } else if (ast_test_flag(flags, OPTION_WHISPER)) {
-               ast_audiohook_lock(&csth.whisper_audiohook);
-               ast_audiohook_detach(&csth.whisper_audiohook);
-               ast_audiohook_unlock(&csth.whisper_audiohook);
-               ast_audiohook_destroy(&csth.whisper_audiohook);
-       }
+       ast_channel_lock(chan);
+       ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
+       ast_channel_unlock(chan);
+
+       ast_audiohook_lock(&csth.whisper_audiohook);
+       ast_audiohook_detach(&csth.whisper_audiohook);
+       ast_audiohook_unlock(&csth.whisper_audiohook);
+       ast_audiohook_destroy(&csth.whisper_audiohook);
+       ast_audiohook_lock(&csth.bridge_whisper_audiohook);
+       ast_audiohook_detach(&csth.bridge_whisper_audiohook);
+       ast_audiohook_unlock(&csth.bridge_whisper_audiohook);
+       ast_audiohook_destroy(&csth.bridge_whisper_audiohook);
 
        ast_audiohook_lock(&csth.spy_audiohook);
        ast_audiohook_detach(&csth.spy_audiohook);
@@ -580,7 +609,7 @@ redo:
        return setup_chanspy_ds(next, chanspy_ds);
 }
 
-static int common_exec(struct ast_channel *chan, const struct ast_flags *flags,
+static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
        int volfactor, const int fd, const char *mygroup, const char *myenforced,
        const char *spec, const char *exten, const char *context, const char *mailbox,
        const char *name_context)