From 3aad03e5f0dab3f1245eaf069061297248a88de8 Mon Sep 17 00:00:00 2001 From: Mark Michelson <mmichelson@digium.com> Date: Mon, 28 Apr 2008 22:38:07 +0000 Subject: [PATCH] Adding a new option 'n' to app_chanspy. This option allows for the name of the spied-on party to be spoken instead of the channel name or number. This was accomplished by adding a new function pointer to point to a function in app_voicemail which retrieves the name file and plays it. This makes for an easy way that applications may play a user's name should it be necessary. app_directory, in particular, can be simplified greatly by this change. This change comes as a suggestion from Switchvox, which already has this feature. AST-23 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@114813 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- CHANGES | 4 + apps/app_chanspy.c | 189 +++++++++++++++++++++++++++-------------- apps/app_voicemail.c | 19 ++++- include/asterisk/app.h | 6 +- main/app.c | 13 ++- 5 files changed, 163 insertions(+), 68 deletions(-) diff --git a/CHANGES b/CHANGES index 1391f049f6..54a9a9702f 100644 --- a/CHANGES +++ b/CHANGES @@ -36,6 +36,10 @@ Application Changes * Chanspy has a new option, 'B', which can be used to "barge" on a call. This is like the pre-existing whisper mode, except that the spy can also talk to the participant on the bridged channel as well. + * Chanspy has a new option, 'n', which will allow for the spied-on party's name + 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. SIP Changes ----------- diff --git a/apps/app_chanspy.c b/apps/app_chanspy.c index 4ef2f4e4f3..60992a8157 100644 --- a/apps/app_chanspy.c +++ b/apps/app_chanspy.c @@ -69,32 +69,39 @@ static const char *desc_chan = " exit to it. This also disables choosing a channel based on 'chanprefix'\n" " and a digit sequence.\n" " Options:\n" -" b - Only spy on channels involved in a bridged call.\n" -" g(grp) - Match only channels where their SPYGROUP variable is set to\n" -" contain 'grp' in an optional : delimited list.\n" -" q - Don't play a beep when beginning to spy on a channel, or speak the\n" -" selected channel name.\n" -" r[(basename)] - Record the session to the monitor spool directory. An\n" -" optional base for the filename may be specified. The\n" -" default is 'chanspy'.\n" -" s - Skip the playback of the channel type (i.e. SIP, IAX, etc) when\n" -" speaking the selected channel name.\n" -" v([value]) - Adjust the initial volume in the range from -4 to 4. A\n" -" negative value refers to a quieter setting.\n" -" w - Enable 'whisper' mode, so the spying channel can talk to\n" -" the spied-on channel.\n" -" W - Enable 'private whisper' mode, so the spying channel can\n" -" talk to the spied-on channel but cannot listen to that\n" -" channel.\n" -" o - Only listen to audio coming from this channel.\n" -" X - Allow the user to exit ChanSpy to a valid single digit\n" -" numeric extension in the current context or the context\n" -" specified by the SPY_EXIT_CONTEXT channel variable. The\n" -" name of the last channel that was spied on will be stored\n" -" in the SPY_CHANNEL variable.\n" -" e(ext) - Enable 'enforced' mode, so the spying channel can\n" -" only monitor extensions whose name is in the 'ext' : \n" -" delimited list.\n" +" b - Only spy on channels involved in a bridged call.\n" +" g(grp) - Match only channels where their SPYGROUP variable is set to\n" +" contain 'grp' in an optional : delimited list.\n" +" n([mailbox][@context]) - Say the name of the person being spied on if that person has recorded\n" +" his/her name. If a context is specified, then that voicemail context will\n" +" be searched when retrieving the name, otherwise the \"default\" context\n" +" will be searched. If no mailbox is specified, then the channel name will\n" +" be used when searching for the name (i.e. if SIP/1000 is the channel being\n" +" spied on and no mailbox is specified, then \"1000\" will be used when searching\n" +" for the name).\n" +" q - Don't play a beep when beginning to spy on a channel, or speak the\n" +" selected channel name.\n" +" r[(basename)] - Record the session to the monitor spool directory. An\n" +" optional base for the filename may be specified. The\n" +" default is 'chanspy'.\n" +" s - Skip the playback of the channel type (i.e. SIP, IAX, etc) when\n" +" speaking the selected channel name.\n" +" v([value]) - Adjust the initial volume in the range from -4 to 4. A\n" +" negative value refers to a quieter setting.\n" +" w - Enable 'whisper' mode, so the spying channel can talk to\n" +" the spied-on channel.\n" +" W - Enable 'private whisper' mode, so the spying channel can\n" +" talk to the spied-on channel but cannot listen to that\n" +" channel.\n" +" o - Only listen to audio coming from this channel.\n" +" X - Allow the user to exit ChanSpy to a valid single digit\n" +" numeric extension in the current context or the context\n" +" specified by the SPY_EXIT_CONTEXT channel variable. The\n" +" name of the last channel that was spied on will be stored\n" +" in the SPY_CHANNEL variable.\n" +" e(ext) - Enable 'enforced' mode, so the spying channel can\n" +" only monitor extensions whose name is in the 'ext' : \n" +" delimited list.\n" ; static const char *app_ext = "ExtenSpy"; @@ -111,29 +118,36 @@ static const char *desc_ext = " single digit extension exists in the correct context it ChanSpy will\n" " exit to it.\n" " Options:\n" -" b - Only spy on channels involved in a bridged call.\n" -" g(grp) - Match only channels where their ${SPYGROUP} variable is set to\n" -" contain 'grp' in an optional : delimited list.\n" -" q - Don't play a beep when beginning to spy on a channel, or speak the\n" -" selected channel name.\n" -" r[(basename)] - Record the session to the monitor spool directory. An\n" -" optional base for the filename may be specified. The\n" -" default is 'chanspy'.\n" -" s - Skip the playback of the channel type (i.e. SIP, IAX, etc) when\n" -" speaking the selected channel name.\n" -" v([value]) - Adjust the initial volume in the range from -4 to 4. A\n" -" negative value refers to a quieter setting.\n" -" w - Enable 'whisper' mode, so the spying channel can talk to\n" -" the spied-on channel.\n" -" W - Enable 'private whisper' mode, so the spying channel can\n" -" talk to the spied-on channel but cannot listen to that\n" -" channel.\n" -" o - Only listen to audio coming from this channel.\n" -" X - Allow the user to exit ChanSpy to a valid single digit\n" -" numeric extension in the current context or the context\n" -" specified by the SPY_EXIT_CONTEXT channel variable. The\n" -" name of the last channel that was spied on will be stored\n" -" in the SPY_CHANNEL variable.\n" +" b - Only spy on channels involved in a bridged call.\n" +" g(grp) - Match only channels where their ${SPYGROUP} variable is set to\n" +" contain 'grp' in an optional : delimited list.\n" +" n([mailbox][@context]) - Say the name of the person being spied on if that person has recorded\n" +" his/her name. If a context is specified, then that voicemail context will\n" +" be searched when retrieving the name, otherwise the \"default\" context\n" +" will be searched. If no mailbox is specified, then the channel name will\n" +" be used when searching for the name (i.e. if SIP/1000 is the channel being\n" +" spied on and no mailbox is specified, then \"1000\" will be used when searching\n" +" for the name).\n" +" q - Don't play a beep when beginning to spy on a channel, or speak the\n" +" selected channel name.\n" +" r[(basename)] - Record the session to the monitor spool directory. An\n" +" optional base for the filename may be specified. The\n" +" default is 'chanspy'.\n" +" s - Skip the playback of the channel type (i.e. SIP, IAX, etc) when\n" +" speaking the selected channel name.\n" +" v([value]) - Adjust the initial volume in the range from -4 to 4. A\n" +" negative value refers to a quieter setting.\n" +" w - Enable 'whisper' mode, so the spying channel can talk to\n" +" the spied-on channel.\n" +" W - Enable 'private whisper' mode, so the spying channel can\n" +" talk to the spied-on channel but cannot listen to that\n" +" channel.\n" +" o - Only listen to audio coming from this channel.\n" +" X - Allow the user to exit ChanSpy to a valid single digit\n" +" numeric extension in the current context or the context\n" +" specified by the SPY_EXIT_CONTEXT channel variable. The\n" +" name of the last channel that was spied on will be stored\n" +" in the SPY_CHANNEL variable.\n" ; enum { @@ -149,6 +163,7 @@ enum { 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 */ } chanspy_opt_flags; enum { @@ -156,6 +171,7 @@ enum { OPT_ARG_GROUP, OPT_ARG_RECORD, OPT_ARG_ENFORCED, + OPT_ARG_NAME, OPT_ARG_ARRAY_SIZE, } chanspy_opt_args; @@ -172,6 +188,7 @@ AST_APP_OPTIONS(spy_opts, { AST_APP_OPTION('o', OPTION_READONLY), AST_APP_OPTION('X', OPTION_EXIT), AST_APP_OPTION('s', OPTION_NOTECH), + AST_APP_OPTION_ARG('n', OPTION_NAME, OPT_ARG_NAME), }); @@ -554,7 +571,8 @@ redo: static int common_exec(struct ast_channel *chan, const 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 *spec, const char *exten, const char *context, const char *mailbox, + const char *name_context) { char nameprefix[AST_NAME_STRLEN]; char peer_name[AST_NAME_STRLEN + 5]; @@ -727,6 +745,7 @@ static int common_exec(struct ast_channel *chan, const struct ast_flags *flags, strncat(peer_name, peer->name, AST_NAME_STRLEN - 4 - 1); ptr = strchr(peer_name, '/'); *ptr++ = '\0'; + ptr = strsep(&ptr, "-"); for (s = peer_name; s < ptr; s++) *s = tolower(*s); @@ -737,22 +756,29 @@ static int common_exec(struct ast_channel *chan, const struct ast_flags *flags, ast_channel_unlock(peer); if (!ast_test_flag(flags, OPTION_QUIET)) { - if (!ast_test_flag(flags, OPTION_NOTECH)) { - if (ast_fileexists(peer_name, NULL, NULL) != -1) { - res = ast_streamfile(chan, peer_name, chan->language); - if (!res) { - res = ast_waitstream(chan, ""); - } - if (res) { - chanspy_ds_free(peer_chanspy_ds); - break; + if (ast_test_flag(flags, OPTION_NAME)) { + const char *local_context = S_OR(name_context, "default"); + const char *local_mailbox = S_OR(mailbox, ptr); + res = ast_app_sayname(chan, local_mailbox, local_context); + } + if (!ast_test_flag(flags, OPTION_NAME) || res < 0) { + if (!ast_test_flag(flags, OPTION_NOTECH)) { + if (ast_fileexists(peer_name, NULL, NULL) != -1) { + res = ast_streamfile(chan, peer_name, chan->language); + if (!res) { + res = ast_waitstream(chan, ""); + } + if (res) { + chanspy_ds_free(peer_chanspy_ds); + break; + } + } else { + res = ast_say_character_str(chan, peer_name, "", chan->language); } - } else { - res = ast_say_character_str(chan, peer_name, "", chan->language); } + if ((num = atoi(ptr))) + ast_say_digits(chan, atoi(ptr), "", chan->language); } - if ((num = atoi(ptr))) - ast_say_digits(chan, atoi(ptr), "", chan->language); } res = channel_spy(chan, peer_chanspy_ds, &volfactor, fd, flags, exitcontext); @@ -815,6 +841,8 @@ static int chanspy_exec(struct ast_channel *chan, void *data) int oldwf = 0; int volfactor = 0; int res; + char *mailbox = NULL; + char *name_context = NULL; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(spec); AST_APP_ARG(options); @@ -850,6 +878,20 @@ static int chanspy_exec(struct ast_channel *chan, void *data) if (ast_test_flag(&flags, OPTION_ENFORCED)) myenforced = opts[OPT_ARG_ENFORCED]; + + if (ast_test_flag(&flags, OPTION_NAME)) { + if (!ast_strlen_zero(opts[OPT_ARG_NAME])) { + char *delimiter; + if ((delimiter = strchr(opts[OPT_ARG_NAME], '@'))) { + mailbox = opts[OPT_ARG_NAME]; + *delimiter++ = '\0'; + name_context = delimiter; + } else { + mailbox = opts[OPT_ARG_NAME]; + } + } + } + } else ast_clear_flag(&flags, AST_FLAGS_ALL); @@ -870,7 +912,7 @@ static int chanspy_exec(struct ast_channel *chan, void *data) } } - res = common_exec(chan, &flags, volfactor, fd, mygroup, myenforced, args.spec, NULL, NULL); + res = common_exec(chan, &flags, volfactor, fd, mygroup, myenforced, args.spec, NULL, NULL, mailbox, name_context); if (fd) close(fd); @@ -891,6 +933,8 @@ static int extenspy_exec(struct ast_channel *chan, void *data) int oldwf = 0; int volfactor = 0; int res; + char *mailbox = NULL; + char *name_context = NULL; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(context); AST_APP_ARG(options); @@ -930,6 +974,21 @@ static int extenspy_exec(struct ast_channel *chan, void *data) if (ast_test_flag(&flags, OPTION_PRIVATE)) ast_set_flag(&flags, OPTION_WHISPER); + + + if (ast_test_flag(&flags, OPTION_NAME)) { + if (!ast_strlen_zero(opts[OPT_ARG_NAME])) { + char *delimiter; + if ((delimiter = strchr(opts[OPT_ARG_NAME], '@'))) { + mailbox = opts[OPT_ARG_NAME]; + *delimiter++ = '\0'; + name_context = delimiter; + } else { + mailbox = opts[OPT_ARG_NAME]; + } + } + } + } else ast_clear_flag(&flags, AST_FLAGS_ALL); @@ -950,7 +1009,7 @@ static int extenspy_exec(struct ast_channel *chan, void *data) } - res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, NULL, exten, args.context); + res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, NULL, exten, args.context, mailbox, name_context); if (fd) close(fd); diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c index f5c79ba1eb..3f5ddebdb4 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -9528,6 +9528,23 @@ static int load_config(int reload) } } +static int sayname(struct ast_channel *chan, const char *mailbox, const char *context) +{ + int res = -1; + char dir[PATH_MAX]; + snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox); + ast_debug(2, "About to try retrieving name file %s\n", dir); + RETRIEVE(dir, -1, mailbox, context); + if (ast_fileexists(dir, NULL, NULL)) { + res = ast_streamfile(chan, dir, chan->language); + if (!res) { + res = ast_waitstream(chan, ""); + } + } + DISPOSE(dir, -1); + return res; +} + static int reload(void) { return load_config(1); @@ -9575,7 +9592,7 @@ static int load_module(void) ast_cli_register_multiple(cli_voicemail, sizeof(cli_voicemail) / sizeof(struct ast_cli_entry)); - ast_install_vm_functions(has_voicemail, inboxcount, messagecount); + ast_install_vm_functions(has_voicemail, inboxcount, messagecount, sayname); return res; } diff --git a/include/asterisk/app.h b/include/asterisk/app.h index 12d41d7dd7..cc830fe760 100644 --- a/include/asterisk/app.h +++ b/include/asterisk/app.h @@ -105,7 +105,8 @@ int ast_app_getdata_full(struct ast_channel *c, char *prompt, char *s, int maxle void ast_install_vm_functions(int (*has_voicemail_func)(const char *mailbox, const char *folder), int (*inboxcount_func)(const char *mailbox, int *newmsgs, int *oldmsgs), - int (*messagecount_func)(const char *context, const char *mailbox, const char *folder)); + int (*messagecount_func)(const char *context, const char *mailbox, const char *folder), + int (*sayname_func)(struct ast_channel *chan, const char *mailbox, const char *context)); void ast_uninstall_vm_functions(void); @@ -115,6 +116,9 @@ int ast_app_has_voicemail(const char *mailbox, const char *folder); /*! \brief Determine number of new/old messages in a mailbox */ int ast_app_inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs); +/*! Given a mailbox and context, play that mailbox owner's name to the channel specified */ +int ast_app_sayname(struct ast_channel *chan, const char *mailbox, const char *context); + /*! \brief Determine number of messages in a given mailbox and folder */ int ast_app_messagecount(const char *context, const char *mailbox, const char *folder); diff --git a/main/app.c b/main/app.c index 60856ae170..e5c7129480 100644 --- a/main/app.c +++ b/main/app.c @@ -177,15 +177,18 @@ int ast_app_getdata_full(struct ast_channel *c, char *prompt, char *s, int maxle static int (*ast_has_voicemail_func)(const char *mailbox, const char *folder) = NULL; static int (*ast_inboxcount_func)(const char *mailbox, int *newmsgs, int *oldmsgs) = NULL; +static int (*ast_sayname_func)(struct ast_channel *chan, const char *mailbox, const char *context) = NULL; static int (*ast_messagecount_func)(const char *context, const char *mailbox, const char *folder) = NULL; void ast_install_vm_functions(int (*has_voicemail_func)(const char *mailbox, const char *folder), int (*inboxcount_func)(const char *mailbox, int *newmsgs, int *oldmsgs), - int (*messagecount_func)(const char *context, const char *mailbox, const char *folder)) + int (*messagecount_func)(const char *context, const char *mailbox, const char *folder), + int (*sayname_func)(struct ast_channel *chan, const char *mailbox, const char *context)) { ast_has_voicemail_func = has_voicemail_func; ast_inboxcount_func = inboxcount_func; ast_messagecount_func = messagecount_func; + ast_sayname_func = sayname_func; } void ast_uninstall_vm_functions(void) @@ -193,6 +196,7 @@ void ast_uninstall_vm_functions(void) ast_has_voicemail_func = NULL; ast_inboxcount_func = NULL; ast_messagecount_func = NULL; + ast_sayname_func = NULL; } int ast_app_has_voicemail(const char *mailbox, const char *folder) @@ -227,6 +231,13 @@ int ast_app_inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs) return 0; } +int ast_app_sayname(struct ast_channel *chan, const char *mailbox, const char *context) +{ + if (ast_sayname_func) + return ast_sayname_func(chan, mailbox, context); + return -1; +} + int ast_app_messagecount(const char *context, const char *mailbox, const char *folder) { static int warned = 0; -- GitLab