@ -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_ fail sound( 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_ fail sound( 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_ fail sound( 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_ fail sound( 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_ fail sound( 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_ fail sound( 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_ fail sound( 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_ fail sound( 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_f ailsou nd( 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_f ailsou nd( 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_f ailsou nd( 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 ;