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
This commit is contained in:
Mark Michelson
2008-04-28 22:38:07 +00:00
parent eff8f552b6
commit 3aad03e5f0
5 changed files with 165 additions and 70 deletions

View File

@@ -36,6 +36,10 @@ Application Changes
* Chanspy has a new option, 'B', which can be used to "barge" on a call. This is * 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 like the pre-existing whisper mode, except that the spy can also talk to the
participant on the bridged channel as well. 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 SIP Changes
----------- -----------

View File

@@ -69,32 +69,39 @@ static const char *desc_chan =
" exit to it. This also disables choosing a channel based on 'chanprefix'\n" " exit to it. This also disables choosing a channel based on 'chanprefix'\n"
" and a digit sequence.\n" " and a digit sequence.\n"
" Options:\n" " Options:\n"
" b - Only spy on channels involved in a bridged call.\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" " g(grp) - Match only channels where their SPYGROUP variable is set to\n"
" contain 'grp' in an optional : delimited list.\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" " n([mailbox][@context]) - Say the name of the person being spied on if that person has recorded\n"
" selected channel name.\n" " his/her name. If a context is specified, then that voicemail context will\n"
" r[(basename)] - Record the session to the monitor spool directory. An\n" " be searched when retrieving the name, otherwise the \"default\" context\n"
" optional base for the filename may be specified. The\n" " will be searched. If no mailbox is specified, then the channel name will\n"
" default is 'chanspy'.\n" " be used when searching for the name (i.e. if SIP/1000 is the channel being\n"
" s - Skip the playback of the channel type (i.e. SIP, IAX, etc) when\n" " spied on and no mailbox is specified, then \"1000\" will be used when searching\n"
" speaking the selected channel name.\n" " for the name).\n"
" v([value]) - Adjust the initial volume in the range from -4 to 4. A\n" " q - Don't play a beep when beginning to spy on a channel, or speak the\n"
" negative value refers to a quieter setting.\n" " selected channel name.\n"
" w - Enable 'whisper' mode, so the spying channel can talk to\n" " r[(basename)] - Record the session to the monitor spool directory. An\n"
" the spied-on channel.\n" " optional base for the filename may be specified. The\n"
" W - Enable 'private whisper' mode, so the spying channel can\n" " default is 'chanspy'.\n"
" talk to the spied-on channel but cannot listen to that\n" " s - Skip the playback of the channel type (i.e. SIP, IAX, etc) when\n"
" channel.\n" " speaking the selected channel name.\n"
" o - Only listen to audio coming from this channel.\n" " v([value]) - Adjust the initial volume in the range from -4 to 4. A\n"
" X - Allow the user to exit ChanSpy to a valid single digit\n" " negative value refers to a quieter setting.\n"
" numeric extension in the current context or the context\n" " w - Enable 'whisper' mode, so the spying channel can talk to\n"
" specified by the SPY_EXIT_CONTEXT channel variable. The\n" " the spied-on channel.\n"
" name of the last channel that was spied on will be stored\n" " W - Enable 'private whisper' mode, so the spying channel can\n"
" in the SPY_CHANNEL variable.\n" " talk to the spied-on channel but cannot listen to that\n"
" e(ext) - Enable 'enforced' mode, so the spying channel can\n" " channel.\n"
" only monitor extensions whose name is in the 'ext' : \n" " o - Only listen to audio coming from this channel.\n"
" delimited list.\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"; 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" " single digit extension exists in the correct context it ChanSpy will\n"
" exit to it.\n" " exit to it.\n"
" Options:\n" " Options:\n"
" b - Only spy on channels involved in a bridged call.\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" " g(grp) - Match only channels where their ${SPYGROUP} variable is set to\n"
" contain 'grp' in an optional : delimited list.\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" " n([mailbox][@context]) - Say the name of the person being spied on if that person has recorded\n"
" selected channel name.\n" " his/her name. If a context is specified, then that voicemail context will\n"
" r[(basename)] - Record the session to the monitor spool directory. An\n" " be searched when retrieving the name, otherwise the \"default\" context\n"
" optional base for the filename may be specified. The\n" " will be searched. If no mailbox is specified, then the channel name will\n"
" default is 'chanspy'.\n" " be used when searching for the name (i.e. if SIP/1000 is the channel being\n"
" s - Skip the playback of the channel type (i.e. SIP, IAX, etc) when\n" " spied on and no mailbox is specified, then \"1000\" will be used when searching\n"
" speaking the selected channel name.\n" " for the name).\n"
" v([value]) - Adjust the initial volume in the range from -4 to 4. A\n" " q - Don't play a beep when beginning to spy on a channel, or speak the\n"
" negative value refers to a quieter setting.\n" " selected channel name.\n"
" w - Enable 'whisper' mode, so the spying channel can talk to\n" " r[(basename)] - Record the session to the monitor spool directory. An\n"
" the spied-on channel.\n" " optional base for the filename may be specified. The\n"
" W - Enable 'private whisper' mode, so the spying channel can\n" " default is 'chanspy'.\n"
" talk to the spied-on channel but cannot listen to that\n" " s - Skip the playback of the channel type (i.e. SIP, IAX, etc) when\n"
" channel.\n" " speaking the selected channel name.\n"
" o - Only listen to audio coming from this channel.\n" " v([value]) - Adjust the initial volume in the range from -4 to 4. A\n"
" X - Allow the user to exit ChanSpy to a valid single digit\n" " negative value refers to a quieter setting.\n"
" numeric extension in the current context or the context\n" " w - Enable 'whisper' mode, so the spying channel can talk to\n"
" specified by the SPY_EXIT_CONTEXT channel variable. The\n" " the spied-on channel.\n"
" name of the last channel that was spied on will be stored\n" " W - Enable 'private whisper' mode, so the spying channel can\n"
" in the SPY_CHANNEL variable.\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 { enum {
@@ -149,6 +163,7 @@ enum {
OPTION_ENFORCED = (1 << 9), /* Enforced mode */ OPTION_ENFORCED = (1 << 9), /* Enforced mode */
OPTION_NOTECH = (1 << 10), /* Skip technology name playback */ OPTION_NOTECH = (1 << 10), /* Skip technology name playback */
OPTION_BARGE = (1 << 11), /* Barge mode (whisper to both channels) */ 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; } chanspy_opt_flags;
enum { enum {
@@ -156,6 +171,7 @@ enum {
OPT_ARG_GROUP, OPT_ARG_GROUP,
OPT_ARG_RECORD, OPT_ARG_RECORD,
OPT_ARG_ENFORCED, OPT_ARG_ENFORCED,
OPT_ARG_NAME,
OPT_ARG_ARRAY_SIZE, OPT_ARG_ARRAY_SIZE,
} chanspy_opt_args; } chanspy_opt_args;
@@ -172,6 +188,7 @@ AST_APP_OPTIONS(spy_opts, {
AST_APP_OPTION('o', OPTION_READONLY), AST_APP_OPTION('o', OPTION_READONLY),
AST_APP_OPTION('X', OPTION_EXIT), AST_APP_OPTION('X', OPTION_EXIT),
AST_APP_OPTION('s', OPTION_NOTECH), 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, static int common_exec(struct ast_channel *chan, const struct ast_flags *flags,
int volfactor, const int fd, const char *mygroup, const char *myenforced, 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 nameprefix[AST_NAME_STRLEN];
char peer_name[AST_NAME_STRLEN + 5]; 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); strncat(peer_name, peer->name, AST_NAME_STRLEN - 4 - 1);
ptr = strchr(peer_name, '/'); ptr = strchr(peer_name, '/');
*ptr++ = '\0'; *ptr++ = '\0';
ptr = strsep(&ptr, "-");
for (s = peer_name; s < ptr; s++) for (s = peer_name; s < ptr; s++)
*s = tolower(*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); ast_channel_unlock(peer);
if (!ast_test_flag(flags, OPTION_QUIET)) { if (!ast_test_flag(flags, OPTION_QUIET)) {
if (!ast_test_flag(flags, OPTION_NOTECH)) { if (ast_test_flag(flags, OPTION_NAME)) {
if (ast_fileexists(peer_name, NULL, NULL) != -1) { const char *local_context = S_OR(name_context, "default");
res = ast_streamfile(chan, peer_name, chan->language); const char *local_mailbox = S_OR(mailbox, ptr);
if (!res) { res = ast_app_sayname(chan, local_mailbox, local_context);
res = ast_waitstream(chan, ""); }
} if (!ast_test_flag(flags, OPTION_NAME) || res < 0) {
if (res) { if (!ast_test_flag(flags, OPTION_NOTECH)) {
chanspy_ds_free(peer_chanspy_ds); if (ast_fileexists(peer_name, NULL, NULL) != -1) {
break; res = ast_streamfile(chan, peer_name, chan->language);
} if (!res) {
} else { res = ast_waitstream(chan, "");
res = ast_say_character_str(chan, peer_name, "", chan->language); }
} if (res) {
chanspy_ds_free(peer_chanspy_ds);
break;
}
} 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); 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 oldwf = 0;
int volfactor = 0; int volfactor = 0;
int res; int res;
char *mailbox = NULL;
char *name_context = NULL;
AST_DECLARE_APP_ARGS(args, AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(spec); AST_APP_ARG(spec);
AST_APP_ARG(options); 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)) if (ast_test_flag(&flags, OPTION_ENFORCED))
myenforced = opts[OPT_ARG_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 } else
ast_clear_flag(&flags, AST_FLAGS_ALL); 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) if (fd)
close(fd); close(fd);
@@ -891,6 +933,8 @@ static int extenspy_exec(struct ast_channel *chan, void *data)
int oldwf = 0; int oldwf = 0;
int volfactor = 0; int volfactor = 0;
int res; int res;
char *mailbox = NULL;
char *name_context = NULL;
AST_DECLARE_APP_ARGS(args, AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(context); AST_APP_ARG(context);
AST_APP_ARG(options); 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)) if (ast_test_flag(&flags, OPTION_PRIVATE))
ast_set_flag(&flags, OPTION_WHISPER); 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 } else
ast_clear_flag(&flags, AST_FLAGS_ALL); 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) if (fd)
close(fd); close(fd);

View File

@@ -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) static int reload(void)
{ {
return load_config(1); 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_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; return res;
} }

View File

@@ -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), 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 (*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); 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 */ /*! \brief Determine number of new/old messages in a mailbox */
int ast_app_inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs); 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 */ /*! \brief Determine number of messages in a given mailbox and folder */
int ast_app_messagecount(const char *context, const char *mailbox, const char *folder); int ast_app_messagecount(const char *context, const char *mailbox, const char *folder);

View File

@@ -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_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_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; 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), 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 (*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_has_voicemail_func = has_voicemail_func;
ast_inboxcount_func = inboxcount_func; ast_inboxcount_func = inboxcount_func;
ast_messagecount_func = messagecount_func; ast_messagecount_func = messagecount_func;
ast_sayname_func = sayname_func;
} }
void ast_uninstall_vm_functions(void) void ast_uninstall_vm_functions(void)
@@ -193,6 +196,7 @@ void ast_uninstall_vm_functions(void)
ast_has_voicemail_func = NULL; ast_has_voicemail_func = NULL;
ast_inboxcount_func = NULL; ast_inboxcount_func = NULL;
ast_messagecount_func = NULL; ast_messagecount_func = NULL;
ast_sayname_func = NULL;
} }
int ast_app_has_voicemail(const char *mailbox, const char *folder) 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; 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) int ast_app_messagecount(const char *context, const char *mailbox, const char *folder)
{ {
static int warned = 0; static int warned = 0;