mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-02 11:58:40 +00:00
Merge "bridge_basic: don't cache xferfailsound during an attended transfer"
This commit is contained in:
@@ -101,6 +101,21 @@ struct ast_features_xfer_config {
|
||||
*/
|
||||
struct ast_features_xfer_config *ast_get_chan_features_xfer_config(struct ast_channel *chan);
|
||||
|
||||
/*!
|
||||
* \brief Get the transfer configuration option xferfailsound
|
||||
*
|
||||
* \note The channel should be locked before calling this function.
|
||||
* \note The returned value has to be freed.
|
||||
*
|
||||
* If no channel is provided, then option is pulled from the global
|
||||
* transfer configuration.
|
||||
*
|
||||
* \param chan The channel to get configuration options for
|
||||
* \retval NULL Failed to get configuration
|
||||
* \retval non-NULL The xferfailsound
|
||||
*/
|
||||
char *ast_get_chan_features_xferfailsound(struct ast_channel *chan);
|
||||
|
||||
/*!
|
||||
* \brief Configuration relating to call pickup
|
||||
*/
|
||||
|
||||
@@ -1296,8 +1296,6 @@ struct attended_transfer_properties {
|
||||
AST_STRING_FIELD(exten);
|
||||
/*! Context of transfer target */
|
||||
AST_STRING_FIELD(context);
|
||||
/*! Sound to play on failure */
|
||||
AST_STRING_FIELD(failsound);
|
||||
/*! Sound to play when transfer completes */
|
||||
AST_STRING_FIELD(xfersound);
|
||||
/*! The channel technology of the transferer channel */
|
||||
@@ -1421,12 +1419,21 @@ static struct attended_transfer_properties *attended_transfer_properties_alloc(
|
||||
struct ast_flags *transferer_features;
|
||||
|
||||
props = ao2_alloc(sizeof(*props), attended_transfer_properties_destructor);
|
||||
if (!props || ast_string_field_init(props, 64)) {
|
||||
if (!props) {
|
||||
ast_log(LOG_ERROR, "Unable to create props - channel %s, context %s\n",
|
||||
ast_channel_name(transferer), context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ast_cond_init(&props->cond, NULL);
|
||||
|
||||
if (ast_string_field_init(props, 64)) {
|
||||
ast_log(LOG_ERROR, "Unable to initialize prop fields - channel %s, context %s\n",
|
||||
ast_channel_name(transferer), context);
|
||||
ao2_ref(props, -1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
props->target_framehook_id = -1;
|
||||
props->transferer = ast_channel_ref(transferer);
|
||||
|
||||
@@ -1447,7 +1454,6 @@ static struct attended_transfer_properties *attended_transfer_properties_alloc(
|
||||
props->atxfernoanswertimeout = xfer_cfg->atxfernoanswertimeout;
|
||||
props->atxferloopdelay = xfer_cfg->atxferloopdelay;
|
||||
ast_string_field_set(props, context, get_transfer_context(transferer, context));
|
||||
ast_string_field_set(props, failsound, xfer_cfg->xferfailsound);
|
||||
ast_string_field_set(props, xfersound, xfer_cfg->xfersound);
|
||||
ao2_ref(xfer_cfg, -1);
|
||||
|
||||
@@ -1707,6 +1713,44 @@ static void play_sound(struct ast_channel *chan, const char *sound)
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Helper method to play a fail sound on a channel in a bridge
|
||||
*
|
||||
* \param chan The channel to play the fail sound to
|
||||
*/
|
||||
static void play_failsound(struct ast_channel *chan)
|
||||
{
|
||||
char *sound;
|
||||
|
||||
ast_channel_lock(chan);
|
||||
sound = ast_get_chan_features_xferfailsound(chan);
|
||||
ast_channel_unlock(chan);
|
||||
|
||||
if (sound) {
|
||||
play_sound(chan, sound);
|
||||
ast_free(sound);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Helper method to stream a fail sound on a channel
|
||||
*
|
||||
* \param chan The channel to stream the fail sound to
|
||||
*/
|
||||
static void stream_failsound(struct ast_channel *chan)
|
||||
{
|
||||
char *sound;
|
||||
|
||||
ast_channel_lock(chan);
|
||||
sound = ast_get_chan_features_xferfailsound(chan);
|
||||
ast_channel_unlock(chan);
|
||||
|
||||
if (sound) {
|
||||
ast_stream_and_wait(chan, sound, AST_DIGIT_NONE);
|
||||
ast_free(sound);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Helper method to place a channel in a bridge on hold
|
||||
*/
|
||||
@@ -2049,7 +2093,7 @@ static enum attended_transfer_state calling_target_exit(struct attended_transfer
|
||||
{
|
||||
switch (stimulus) {
|
||||
case STIMULUS_TRANSFEREE_HANGUP:
|
||||
play_sound(props->transferer, props->failsound);
|
||||
play_failsound(props->transferer);
|
||||
publish_transfer_fail(props);
|
||||
return TRANSFER_FAIL;
|
||||
case STIMULUS_DTMF_ATXFER_COMPLETE:
|
||||
@@ -2061,7 +2105,7 @@ static enum attended_transfer_state calling_target_exit(struct attended_transfer
|
||||
case STIMULUS_TRANSFER_TARGET_HANGUP:
|
||||
case STIMULUS_TIMEOUT:
|
||||
case STIMULUS_DTMF_ATXFER_ABORT:
|
||||
play_sound(props->transferer, props->failsound);
|
||||
play_failsound(props->transferer);
|
||||
return TRANSFER_REBRIDGE;
|
||||
case STIMULUS_DTMF_ATXFER_THREEWAY:
|
||||
bridge_unhold(props->transferee_bridge);
|
||||
@@ -2090,7 +2134,7 @@ static enum attended_transfer_state hesitant_exit(struct attended_transfer_prope
|
||||
{
|
||||
switch (stimulus) {
|
||||
case STIMULUS_TRANSFEREE_HANGUP:
|
||||
play_sound(props->transferer, props->failsound);
|
||||
play_failsound(props->transferer);
|
||||
publish_transfer_fail(props);
|
||||
return TRANSFER_FAIL;
|
||||
case STIMULUS_DTMF_ATXFER_COMPLETE:
|
||||
@@ -2101,7 +2145,7 @@ static enum attended_transfer_state hesitant_exit(struct attended_transfer_prope
|
||||
case STIMULUS_TRANSFER_TARGET_HANGUP:
|
||||
case STIMULUS_TIMEOUT:
|
||||
case STIMULUS_DTMF_ATXFER_ABORT:
|
||||
play_sound(props->transferer, props->failsound);
|
||||
play_failsound(props->transferer);
|
||||
return TRANSFER_RESUME;
|
||||
case STIMULUS_DTMF_ATXFER_THREEWAY:
|
||||
return TRANSFER_THREEWAY;
|
||||
@@ -2163,7 +2207,7 @@ static enum attended_transfer_state consulting_exit(struct attended_transfer_pro
|
||||
* a sound to the transferer to indicate the transferee is gone.
|
||||
*/
|
||||
bridge_basic_change_personality(props->target_bridge, BRIDGE_BASIC_PERSONALITY_NORMAL, NULL);
|
||||
play_sound(props->transferer, props->failsound);
|
||||
play_failsound(props->transferer);
|
||||
ast_bridge_merge_inhibit(props->target_bridge, -1);
|
||||
/* These next two lines are here to ensure that our reference to the target bridge
|
||||
* is cleaned up properly and that the target bridge is not destroyed when the
|
||||
@@ -2179,7 +2223,7 @@ static enum attended_transfer_state consulting_exit(struct attended_transfer_pro
|
||||
return TRANSFER_COMPLETE;
|
||||
case STIMULUS_TRANSFER_TARGET_HANGUP:
|
||||
case STIMULUS_DTMF_ATXFER_ABORT:
|
||||
play_sound(props->transferer, props->failsound);
|
||||
play_failsound(props->transferer);
|
||||
return TRANSFER_REBRIDGE;
|
||||
case STIMULUS_DTMF_ATXFER_THREEWAY:
|
||||
bridge_unhold(props->transferee_bridge);
|
||||
@@ -2211,7 +2255,7 @@ static enum attended_transfer_state double_checking_exit(struct attended_transfe
|
||||
{
|
||||
switch (stimulus) {
|
||||
case STIMULUS_TRANSFEREE_HANGUP:
|
||||
play_sound(props->transferer, props->failsound);
|
||||
play_failsound(props->transferer);
|
||||
publish_transfer_fail(props);
|
||||
return TRANSFER_FAIL;
|
||||
case STIMULUS_TRANSFERER_HANGUP:
|
||||
@@ -2221,7 +2265,7 @@ static enum attended_transfer_state double_checking_exit(struct attended_transfe
|
||||
return TRANSFER_COMPLETE;
|
||||
case STIMULUS_TRANSFER_TARGET_HANGUP:
|
||||
case STIMULUS_DTMF_ATXFER_ABORT:
|
||||
play_sound(props->transferer, props->failsound);
|
||||
play_failsound(props->transferer);
|
||||
return TRANSFER_RESUME;
|
||||
case STIMULUS_DTMF_ATXFER_THREEWAY:
|
||||
bridge_unhold(props->target_bridge);
|
||||
@@ -3295,7 +3339,7 @@ static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel,
|
||||
props->transfer_target = dial_transfer(bridge_channel->chan, destination);
|
||||
if (!props->transfer_target) {
|
||||
ast_log(LOG_ERROR, "Unable to request outbound channel for attended transfer target.\n");
|
||||
ast_stream_and_wait(props->transferer, props->failsound, AST_DIGIT_NONE);
|
||||
stream_failsound(props->transferer);
|
||||
ast_bridge_channel_write_unhold(bridge_channel);
|
||||
attended_transfer_properties_shutdown(props);
|
||||
return 0;
|
||||
@@ -3306,7 +3350,7 @@ static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel,
|
||||
props->target_bridge = ast_bridge_basic_new();
|
||||
if (!props->target_bridge) {
|
||||
ast_log(LOG_ERROR, "Unable to create bridge for attended transfer target.\n");
|
||||
ast_stream_and_wait(props->transferer, props->failsound, AST_DIGIT_NONE);
|
||||
stream_failsound(props->transferer);
|
||||
ast_bridge_channel_write_unhold(bridge_channel);
|
||||
ast_hangup(props->transfer_target);
|
||||
props->transfer_target = NULL;
|
||||
@@ -3317,7 +3361,7 @@ static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel,
|
||||
|
||||
if (attach_framehook(props, props->transfer_target)) {
|
||||
ast_log(LOG_ERROR, "Unable to attach framehook to transfer target.\n");
|
||||
ast_stream_and_wait(props->transferer, props->failsound, AST_DIGIT_NONE);
|
||||
stream_failsound(props->transferer);
|
||||
ast_bridge_channel_write_unhold(bridge_channel);
|
||||
ast_hangup(props->transfer_target);
|
||||
props->transfer_target = NULL;
|
||||
@@ -3332,7 +3376,7 @@ static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel,
|
||||
|
||||
if (ast_call(props->transfer_target, destination, 0)) {
|
||||
ast_log(LOG_ERROR, "Unable to place outbound call to transfer target.\n");
|
||||
ast_stream_and_wait(bridge_channel->chan, props->failsound, AST_DIGIT_NONE);
|
||||
stream_failsound(props->transferer);
|
||||
ast_bridge_channel_write_unhold(bridge_channel);
|
||||
ast_hangup(props->transfer_target);
|
||||
props->transfer_target = NULL;
|
||||
@@ -3348,7 +3392,7 @@ static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel,
|
||||
if (ast_bridge_impart(props->target_bridge, props->transfer_target, NULL, NULL,
|
||||
AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
|
||||
ast_log(LOG_ERROR, "Unable to place transfer target into bridge.\n");
|
||||
ast_stream_and_wait(bridge_channel->chan, props->failsound, AST_DIGIT_NONE);
|
||||
stream_failsound(props->transferer);
|
||||
ast_bridge_channel_write_unhold(bridge_channel);
|
||||
ast_hangup(props->transfer_target);
|
||||
props->transfer_target = NULL;
|
||||
@@ -3358,7 +3402,7 @@ static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel,
|
||||
|
||||
if (ast_pthread_create_detached(&thread, NULL, attended_transfer_monitor_thread, props)) {
|
||||
ast_log(LOG_ERROR, "Unable to create monitoring thread for attended transfer.\n");
|
||||
ast_stream_and_wait(bridge_channel->chan, props->failsound, AST_DIGIT_NONE);
|
||||
stream_failsound(props->transferer);
|
||||
ast_bridge_channel_write_unhold(bridge_channel);
|
||||
attended_transfer_properties_shutdown(props);
|
||||
return 0;
|
||||
|
||||
@@ -1158,6 +1158,21 @@ struct ast_features_xfer_config *ast_get_chan_features_xfer_config(struct ast_ch
|
||||
return cfg->global->xfer;
|
||||
}
|
||||
|
||||
char *ast_get_chan_features_xferfailsound(struct ast_channel *chan)
|
||||
{
|
||||
char *res;
|
||||
struct ast_features_xfer_config *cfg = ast_get_chan_features_xfer_config(chan);
|
||||
|
||||
if (!cfg) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res = ast_strdup(cfg->xferfailsound);
|
||||
ao2_ref(cfg, -1);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct ast_features_pickup_config *ast_get_chan_features_pickup_config(struct ast_channel *chan)
|
||||
{
|
||||
RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
|
||||
|
||||
Reference in New Issue
Block a user