voicemail API callbacks: Extract the sayname API call to its own registerd callback.

* Extract the sayname API call to its own registerd callback.  This allows
the app_directory and app_chanspy applications to say a mailbox owner's
name using an alternate provider when app_voicemail is not available
because you are using res_mwi_external.  app_directory still uses the
voicemail.conf file.

AFS-64 #close
Reported by: Mark Michelson


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@416830 65c4cc65-6c06-0410-ace0-fbb531ad65f3
changes/97/197/1
Richard Mudgett 11 years ago
parent 577632dec9
commit 86e8ab5ed4

@ -864,6 +864,15 @@ static struct ast_autochan *next_channel(struct ast_channel_iterator *iter,
return NULL; return NULL;
} }
static int spy_sayname(struct ast_channel *chan, const char *mailbox, const char *context)
{
char *mailbox_id;
mailbox_id = ast_alloca(strlen(mailbox) + strlen(context) + 2);
sprintf(mailbox_id, "%s@%s", mailbox, context); /* Safe */
return ast_app_sayname(chan, mailbox_id);
}
static int common_exec(struct ast_channel *chan, struct ast_flags *flags, static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
int volfactor, const int fd, struct spy_dtmf_options *user_options, int volfactor, const int fd, struct spy_dtmf_options *user_options,
const char *mygroup, const char *myenforced, const char *spec, const char *exten, const char *mygroup, const char *myenforced, const char *spec, const char *exten,
@ -1078,8 +1087,9 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
if (ast_test_flag(flags, OPTION_NAME)) { if (ast_test_flag(flags, OPTION_NAME)) {
const char *local_context = S_OR(name_context, "default"); const char *local_context = S_OR(name_context, "default");
const char *local_mailbox = S_OR(mailbox, ptr); const char *local_mailbox = S_OR(mailbox, ptr);
if (local_mailbox) { if (local_mailbox) {
res = ast_app_sayname(chan, local_mailbox, local_context); res = spy_sayname(chan, local_mailbox, local_context);
} else { } else {
res = -1; res = -1;
} }

@ -26,7 +26,6 @@
*/ */
/*** MODULEINFO /*** MODULEINFO
<depend>app_voicemail</depend>
<support_level>core</support_level> <support_level>core</support_level>
***/ ***/
#include "asterisk.h" #include "asterisk.h"
@ -290,7 +289,13 @@ static int play_mailbox_owner(struct ast_channel *chan, const char *context,
const char *ext, const char *name, struct ast_flags *flags) const char *ext, const char *name, struct ast_flags *flags)
{ {
int res = 0; int res = 0;
if ((res = ast_app_sayname(chan, ext, context)) >= 0) { char *mailbox_id;
mailbox_id = ast_alloca(strlen(ext) + strlen(context) + 2);
sprintf(mailbox_id, "%s@%s", ext, context); /* Safe */
res = ast_app_sayname(chan, mailbox_id);
if (res >= 0) {
ast_stopstream(chan); ast_stopstream(chan);
/* If Option 'e' was specified, also read the extension number with the name */ /* If Option 'e' was specified, also read the extension number with the name */
if (ast_test_flag(flags, OPT_SAYEXTENSION)) { if (ast_test_flag(flags, OPT_SAYEXTENSION)) {

@ -13669,6 +13669,29 @@ static int sayname(struct ast_channel *chan, const char *mailbox, const char *co
return res; return res;
} }
/*!
* \internal
* \brief Play a recorded user name for the mailbox to the specified channel.
*
* \param chan Where to play the recorded name file.
* \param mailbox_id The mailbox name.
*
* \retval 0 Name played without interruption
* \retval dtmf ASCII value of the DTMF which interrupted playback.
* \retval -1 Unable to locate mailbox or hangup occurred.
*/
static int vm_sayname(struct ast_channel *chan, const char *mailbox_id)
{
char *context;
char *mailbox;
if (ast_strlen_zero(mailbox_id)
|| separate_mailbox(ast_strdupa(mailbox_id), &mailbox, &context)) {
return -1;
}
return sayname(chan, mailbox, context);
}
static void read_password_from_file(const char *secretfn, char *password, int passwordlen) { static void read_password_from_file(const char *secretfn, char *password, int passwordlen) {
struct ast_config *pwconf; struct ast_config *pwconf;
struct ast_flags config_flags = { 0 }; struct ast_flags config_flags = { 0 };
@ -14286,7 +14309,6 @@ static const struct ast_vm_functions vm_table = {
.inboxcount = inboxcount, .inboxcount = inboxcount,
.inboxcount2 = inboxcount2, .inboxcount2 = inboxcount2,
.messagecount = messagecount, .messagecount = messagecount,
.sayname = sayname,
.copy_recording_to_vm = msg_create_from_file, .copy_recording_to_vm = msg_create_from_file,
.index_to_foldername = vm_index_to_foldername, .index_to_foldername = vm_index_to_foldername,
.mailbox_snapshot_create = vm_mailbox_snapshot_create, .mailbox_snapshot_create = vm_mailbox_snapshot_create,
@ -14297,6 +14319,13 @@ static const struct ast_vm_functions vm_table = {
.msg_play = vm_msg_play, .msg_play = vm_msg_play,
}; };
static const struct ast_vm_greeter_functions vm_greeter_table = {
.module_version = VM_GREETER_MODULE_VERSION,
.module_name = AST_MODULE,
.sayname = vm_sayname,
};
static int reload(void) static int reload(void)
{ {
return load_config(1); return load_config(1);
@ -14327,6 +14356,7 @@ static int unload_module(void)
#endif #endif
ast_cli_unregister_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail)); ast_cli_unregister_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
ast_vm_unregister(vm_table.module_name); ast_vm_unregister(vm_table.module_name);
ast_vm_greeter_unregister(vm_greeter_table.module_name);
#ifdef TEST_FRAMEWORK #ifdef TEST_FRAMEWORK
ast_uninstall_vm_test_functions(); ast_uninstall_vm_test_functions();
#endif #endif
@ -14394,8 +14424,10 @@ static int load_module(void)
#endif #endif
res |= ast_vm_register(&vm_table); res |= ast_vm_register(&vm_table);
if (res) res |= ast_vm_greeter_register(&vm_greeter_table);
if (res) {
return res; return res;
}
ast_cli_register_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail)); ast_cli_register_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
ast_data_register_multiple(vm_data_providers, ARRAY_LEN(vm_data_providers)); ast_data_register_multiple(vm_data_providers, ARRAY_LEN(vm_data_providers));

@ -392,17 +392,16 @@ typedef int (ast_inboxcount2_fn)(const char *mailboxes, int *urgentmsgs, int *ne
typedef int (ast_messagecount_fn)(const char *mailbox_id, const char *folder); typedef int (ast_messagecount_fn)(const char *mailbox_id, const char *folder);
/*! /*!
* \brief Play a recorded user name for the mailbox. * \brief Play a recorded user name for the mailbox to the specified channel.
* *
* \param chan Where to play the recorded name file. * \param chan Where to play the recorded name file.
* \param user The user part of user@context. * \param mailbox_id The mailbox name.
* \param context The context part of user@context. Must be explicit.
* *
* \retval 0 Name played without interruption * \retval 0 Name played without interruption
* \retval dtmf ASCII value of the DTMF which interrupted playback * \retval dtmf ASCII value of the DTMF which interrupted playback.
* \retval -1 on failure * \retval -1 Unable to locate mailbox or hangup occurred.
*/ */
typedef int (ast_sayname_fn)(struct ast_channel *chan, const char *user, const char *context); typedef int (ast_sayname_fn)(struct ast_channel *chan, const char *mailbox_id);
/*! /*!
* \brief Creates a voicemail based on a specified file to a mailbox. * \brief Creates a voicemail based on a specified file to a mailbox.
@ -534,7 +533,7 @@ typedef int (ast_vm_msg_forward_fn)(const char *from_mailbox, const char *from_c
typedef int (ast_vm_msg_play_fn)(struct ast_channel *chan, const char *mailbox, typedef int (ast_vm_msg_play_fn)(struct ast_channel *chan, const char *mailbox,
const char *context, const char *folder, const char *msg_num, ast_vm_msg_play_cb *cb); const char *context, const char *folder, const char *msg_num, ast_vm_msg_play_cb *cb);
#define VM_MODULE_VERSION 1 #define VM_MODULE_VERSION 2
/*! \brief Voicemail function table definition. */ /*! \brief Voicemail function table definition. */
struct ast_vm_functions { struct ast_vm_functions {
@ -554,7 +553,6 @@ struct ast_vm_functions {
ast_inboxcount_fn *inboxcount; ast_inboxcount_fn *inboxcount;
ast_inboxcount2_fn *inboxcount2; ast_inboxcount2_fn *inboxcount2;
ast_messagecount_fn *messagecount; ast_messagecount_fn *messagecount;
ast_sayname_fn *sayname;
ast_copy_recording_to_vm_fn *copy_recording_to_vm; ast_copy_recording_to_vm_fn *copy_recording_to_vm;
ast_vm_index_to_foldername_fn *index_to_foldername; ast_vm_index_to_foldername_fn *index_to_foldername;
ast_vm_mailbox_snapshot_create_fn *mailbox_snapshot_create; ast_vm_mailbox_snapshot_create_fn *mailbox_snapshot_create;
@ -569,8 +567,8 @@ struct ast_vm_functions {
* \brief Determine if a voicemail provider is registered. * \brief Determine if a voicemail provider is registered.
* \since 12.0.0 * \since 12.0.0
* *
* \retval 0 if no privider registered. * \retval 0 if no provider registered.
* \retval 1 if a privider is registered. * \retval 1 if a provider is registered.
*/ */
int ast_vm_is_registered(void); int ast_vm_is_registered(void);
@ -597,6 +595,59 @@ int __ast_vm_register(const struct ast_vm_functions *vm_table, struct ast_module
*/ */
void ast_vm_unregister(const char *module_name); void ast_vm_unregister(const char *module_name);
#define VM_GREETER_MODULE_VERSION 1
/*! \brief Voicemail greeter function table definition. */
struct ast_vm_greeter_functions {
/*!
* \brief The version of this function table.
*
* \note If the ABI for this table changes, the module version
* (\ref VM_GREETER_MODULE_VERSION) should be incremented.
*/
unsigned int module_version;
/*! \brief The name of the module that provides the voicemail greeter functionality */
const char *module_name;
/*! \brief The module for the voicemail greeter provider */
struct ast_module *module;
ast_sayname_fn *sayname;
};
/*!
* \brief Determine if a voicemail greeter provider is registered.
* \since 13.0.0
*
* \retval 0 if no provider registered.
* \retval 1 if a provider is registered.
*/
int ast_vm_greeter_is_registered(void);
/*!
* \brief Set voicemail greeter function callbacks
* \since 13.0.0
*
* \param vm_table Voicemail greeter function table to install.
* \param module Pointer to the module implementing the interface
*
* \retval 0 on success.
* \retval -1 on error.
*/
int __ast_vm_greeter_register(const struct ast_vm_greeter_functions *vm_table, struct ast_module *module);
/*! \brief See \ref __ast_vm_greeter_register() */
#define ast_vm_greeter_register(vm_table) __ast_vm_greeter_register(vm_table, ast_module_info ? ast_module_info->self : NULL)
/*!
* \brief Unregister the specified voicemail greeter provider
* \since 13.0.0
*
* \param The module name of the provider to unregister
*
* \return Nothing
*/
void ast_vm_greeter_unregister(const char *module_name);
#ifdef TEST_FRAMEWORK #ifdef TEST_FRAMEWORK
typedef int (ast_vm_test_create_user_fn)(const char *context, const char *user); typedef int (ast_vm_test_create_user_fn)(const char *context, const char *user);
typedef int (ast_vm_test_destroy_user_fn)(const char *context, const char *user); typedef int (ast_vm_test_destroy_user_fn)(const char *context, const char *user);
@ -652,16 +703,16 @@ int ast_app_inboxcount(const char *mailboxes, int *newmsgs, int *oldmsgs);
int ast_app_inboxcount2(const char *mailboxes, int *urgentmsgs, int *newmsgs, int *oldmsgs); int ast_app_inboxcount2(const char *mailboxes, int *urgentmsgs, int *newmsgs, int *oldmsgs);
/*! /*!
* \brief Given a mailbox and context, play that mailbox owner's name to the channel specified * \brief Play a recorded user name for the mailbox to the specified channel.
* \param[in] chan Channel on which to play the name *
* \param[in] mailbox Mailbox number from which to retrieve the recording * \param chan Where to play the recorded name file.
* \param[in] context Mailbox context from which to locate the mailbox number * \param mailbox_id The mailbox name.
*
* \retval 0 Name played without interruption * \retval 0 Name played without interruption
* \retval dtmf ASCII value of the DTMF which interrupted playback. * \retval dtmf ASCII value of the DTMF which interrupted playback.
* \retval -1 Unable to locate mailbox or hangup occurred. * \retval -1 Unable to locate mailbox or hangup occurred.
* \since 1.6.1
*/ */
int ast_app_sayname(struct ast_channel *chan, const char *mailbox, const char *context); int ast_app_sayname(struct ast_channel *chan, const char *mailbox_id);
/*! /*!
* \brief Get the number of messages in a given mailbox folder * \brief Get the number of messages in a given mailbox folder

@ -519,6 +519,66 @@ void ast_vm_unregister(const char *module_name)
ao2_cleanup(table); ao2_cleanup(table);
} }
/*! \brief The container for the voicemail greeter provider */
static AO2_GLOBAL_OBJ_STATIC(vm_greeter_provider);
/*! Voicemail greeter not registered warning */
static int vm_greeter_warnings;
int ast_vm_greeter_is_registered(void)
{
struct ast_vm_greeter_functions *table;
int is_registered;
table = ao2_global_obj_ref(vm_greeter_provider);
is_registered = table ? 1 : 0;
ao2_cleanup(table);
return is_registered;
}
int __ast_vm_greeter_register(const struct ast_vm_greeter_functions *vm_table, struct ast_module *module)
{
RAII_VAR(struct ast_vm_greeter_functions *, table, NULL, ao2_cleanup);
if (!vm_table->module_name) {
ast_log(LOG_ERROR, "Voicemail greeter provider missing required information.\n");
return -1;
}
if (vm_table->module_version != VM_GREETER_MODULE_VERSION) {
ast_log(LOG_ERROR, "Voicemail greeter provider '%s' has incorrect version\n",
vm_table->module_name);
return -1;
}
table = ao2_global_obj_ref(vm_greeter_provider);
if (table) {
ast_log(LOG_WARNING, "Voicemail greeter provider already registered by %s.\n",
table->module_name);
return -1;
}
table = ao2_alloc_options(sizeof(*table), NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
if (!table) {
return -1;
}
*table = *vm_table;
table->module = module;
ao2_global_obj_replace_unref(vm_greeter_provider, table);
return 0;
}
void ast_vm_greeter_unregister(const char *module_name)
{
struct ast_vm_greeter_functions *table;
table = ao2_global_obj_ref(vm_greeter_provider);
if (table && !strcmp(table->module_name, module_name)) {
ao2_global_obj_release(vm_greeter_provider);
}
ao2_cleanup(table);
}
#ifdef TEST_FRAMEWORK #ifdef TEST_FRAMEWORK
static ast_vm_test_create_user_fn *ast_vm_test_create_user_func = NULL; static ast_vm_test_create_user_fn *ast_vm_test_create_user_func = NULL;
static ast_vm_test_destroy_user_fn *ast_vm_test_destroy_user_func = NULL; static ast_vm_test_destroy_user_fn *ast_vm_test_destroy_user_func = NULL;
@ -546,7 +606,8 @@ static void vm_warn_no_provider(void)
#define VM_API_CALL(res, api_call, api_parms) \ #define VM_API_CALL(res, api_call, api_parms) \
do { \ do { \
struct ast_vm_functions *table = ao2_global_obj_ref(vm_provider); \ struct ast_vm_functions *table; \
table = ao2_global_obj_ref(vm_provider); \
if (!table) { \ if (!table) { \
vm_warn_no_provider(); \ vm_warn_no_provider(); \
} else if (table->api_call) { \ } else if (table->api_call) { \
@ -557,6 +618,27 @@ static void vm_warn_no_provider(void)
ao2_cleanup(table); \ ao2_cleanup(table); \
} while (0) } while (0)
static void vm_greeter_warn_no_provider(void)
{
if (vm_greeter_warnings++ % 10 == 0) {
ast_verb(3, "No voicemail greeter provider registered.\n");
}
}
#define VM_GREETER_API_CALL(res, api_call, api_parms) \
do { \
struct ast_vm_greeter_functions *table; \
table = ao2_global_obj_ref(vm_greeter_provider); \
if (!table) { \
vm_greeter_warn_no_provider(); \
} else if (table->api_call) { \
ast_module_ref(table->module); \
(res) = table->api_call api_parms; \
ast_module_unref(table->module); \
} \
ao2_cleanup(table); \
} while (0)
int ast_app_has_voicemail(const char *mailboxes, const char *folder) int ast_app_has_voicemail(const char *mailboxes, const char *folder)
{ {
int res = 0; int res = 0;
@ -612,11 +694,11 @@ int ast_app_inboxcount2(const char *mailboxes, int *urgentmsgs, int *newmsgs, in
return res; return res;
} }
int ast_app_sayname(struct ast_channel *chan, const char *mailbox, const char *context) int ast_app_sayname(struct ast_channel *chan, const char *mailbox_id)
{ {
int res = -1; int res = -1;
VM_API_CALL(res, sayname, (chan, mailbox, context)); VM_GREETER_API_CALL(res, sayname, (chan, mailbox_id));
return res; return res;
} }

Loading…
Cancel
Save