@ -296,7 +296,7 @@ enum {
/*! \brief Container to hold all conference bridges in progress */
static struct ao2_container * conference_bridges ;
static void leave_conference _bridge ( struct conference_bridge * conference_bridge , struct conference_bridge _user * conference_bridge_ user) ;
static void leave_conference ( struct conference_bridge _user * user) ;
static int play_sound_number ( struct conference_bridge * conference_bridge , int say_number ) ;
static int execute_menu_entry ( struct conference_bridge * conference_bridge ,
struct conference_bridge_user * conference_bridge_user ,
@ -560,9 +560,7 @@ static int start_conf_record_thread(struct conference_bridge *conference_bridge)
{
ao2_ref ( conference_bridge , + 1 ) ; /* give the record thread a ref */
ao2_lock ( conference_bridge ) ;
conf_start_record ( conference_bridge ) ;
ao2_unlock ( conference_bridge ) ;
if ( ast_pthread_create_background ( & conference_bridge - > record_thread , NULL , record_thread , conference_bridge ) ) {
ast_log ( LOG_WARNING , " Failed to create recording channel for conference %s \n " , conference_bridge - > name ) ;
@ -768,8 +766,6 @@ static void destroy_conference_bridge(void *obj)
ast_debug ( 1 , " Destroying conference bridge '%s' \n " , conference_bridge - > name ) ;
ast_mutex_destroy ( & conference_bridge - > playback_lock ) ;
if ( conference_bridge - > playback_chan ) {
struct ast_channel * underlying_channel = conference_bridge - > playback_chan - > tech - > bridged_channel ( conference_bridge - > playback_chan , NULL ) ;
if ( underlying_channel ) {
@ -784,7 +780,11 @@ static void destroy_conference_bridge(void *obj)
ast_bridge_destroy ( conference_bridge - > bridge ) ;
conference_bridge - > bridge = NULL ;
}
conf_bridge_profile_destroy ( & conference_bridge - > b_profile ) ;
ast_cond_destroy ( & conference_bridge - > record_cond ) ;
ast_mutex_destroy ( & conference_bridge - > record_lock ) ;
ast_mutex_destroy ( & conference_bridge - > playback_lock ) ;
}
/*! \brief Call the proper join event handler for the user for the conference bridge's current state
@ -961,7 +961,7 @@ static struct conference_bridge *join_conference_bridge(const char *name, struct
if ( conference_bridge & & ( max_members_reached | | conference_bridge - > locked ) & & ! ast_test_flag ( & conference_bridge_user - > u_profile , USER_OPT_ADMIN ) ) {
ao2_unlock ( conference_bridges ) ;
ao2_ref ( conference_bridge , - 1 ) ;
ast_debug ( 1 , " Conference bridge '%s' is locked and caller is not an admin\n " , name ) ;
ast_debug ( 1 , " Conference '%s' is locked and caller is not an admin\n " , name ) ;
ast_stream_and_wait ( conference_bridge_user - > chan ,
conf_get_sound ( CONF_SOUND_LOCKED , conference_bridge_user - > b_profile . sounds ) ,
" " ) ;
@ -973,10 +973,17 @@ static struct conference_bridge *join_conference_bridge(const char *name, struct
/* Try to allocate memory for a new conference bridge, if we fail... this won't end well. */
if ( ! ( conference_bridge = ao2_alloc ( sizeof ( * conference_bridge ) , destroy_conference_bridge ) ) ) {
ao2_unlock ( conference_bridges ) ;
ast_log ( LOG_ERROR , " Conference bridge '%s' does not exist .\n " , name ) ;
ast_log ( LOG_ERROR , " Conference '%s' could not be created .\n " , name ) ;
return NULL ;
}
/* Setup lock for playback channel */
ast_mutex_init ( & conference_bridge - > playback_lock ) ;
/* Setup lock for the record channel */
ast_mutex_init ( & conference_bridge - > record_lock ) ;
ast_cond_init ( & conference_bridge - > record_cond , NULL ) ;
/* Setup conference bridge parameters */
conference_bridge - > record_thread = AST_PTHREADT_NULL ;
ast_copy_string ( conference_bridge - > name , name , sizeof ( conference_bridge - > name ) ) ;
@ -987,7 +994,7 @@ static struct conference_bridge *join_conference_bridge(const char *name, struct
ao2_ref ( conference_bridge , - 1 ) ;
conference_bridge = NULL ;
ao2_unlock ( conference_bridges ) ;
ast_log ( LOG_ERROR , " Conference bridge '%s' could not be created.\n " , name ) ;
ast_log ( LOG_ERROR , " Conference '%s' mixing bridge could not be created.\n " , name ) ;
return NULL ;
}
@ -1000,15 +1007,15 @@ static struct conference_bridge *join_conference_bridge(const char *name, struct
ast_bridge_set_talker_src_video_mode ( conference_bridge - > bridge ) ;
}
/* Setup lock for playback channel */
ast_mutex_init ( & conference_bridge - > playback_lock ) ;
/* Setup lock for the record channel */
ast_mutex_init ( & conference_bridge - > record_lock ) ;
ast_cond_init ( & conference_bridge - > record_cond , NULL ) ;
/* Link it into the conference bridges container */
ao2_link ( conference_bridges , conference_bridge ) ;
if ( ! ao2_link ( conference_bridges , conference_bridge ) ) {
ao2_ref ( conference_bridge , - 1 ) ;
conference_bridge = NULL ;
ao2_unlock ( conference_bridges ) ;
ast_log ( LOG_ERROR ,
" Conference '%s' could not be added to the conferences list. \n " , name ) ;
return NULL ;
}
/* Set the initial state to EMPTY */
conference_bridge - > state = CONF_STATE_EMPTY ;
@ -1021,7 +1028,7 @@ static struct conference_bridge *join_conference_bridge(const char *name, struct
}
send_conf_start_event ( conference_bridge - > name ) ;
ast_debug ( 1 , " Created conference bridge '%s' and linked to container '%p'\n " , name , conference_bridges ) ;
ast_debug ( 1 , " Created conference '%s' and linked to container.\n " , name ) ;
}
ao2_unlock ( conference_bridges ) ;
@ -1040,7 +1047,7 @@ static struct conference_bridge *join_conference_bridge(const char *name, struct
if ( ast_check_hangup ( conference_bridge_user - > chan ) ) {
ao2_unlock ( conference_bridge ) ;
leave_conference _bridge ( conference_bridge , conference_bridge_user ) ;
leave_conference ( conference_bridge_user ) ;
return NULL ;
}
@ -1049,7 +1056,7 @@ static struct conference_bridge *join_conference_bridge(const char *name, struct
/* Announce number of users if need be */
if ( ast_test_flag ( & conference_bridge_user - > u_profile , USER_OPT_ANNOUNCEUSERCOUNT ) ) {
if ( announce_user_count ( conference_bridge , conference_bridge_user ) ) {
leave_conference _bridge ( conference_bridge , conference_bridge_user ) ;
leave_conference ( conference_bridge_user ) ;
return NULL ;
}
}
@ -1057,7 +1064,7 @@ static struct conference_bridge *join_conference_bridge(const char *name, struct
if ( ast_test_flag ( & conference_bridge_user - > u_profile , USER_OPT_ANNOUNCEUSERCOUNTALL ) & &
( conference_bridge - > activeusers > conference_bridge_user - > u_profile . announce_user_count_all_after ) ) {
if ( announce_user_count ( conference_bridge , NULL ) ) {
leave_conference _bridge ( conference_bridge , conference_bridge_user ) ;
leave_conference ( conference_bridge_user ) ;
return NULL ;
}
}
@ -1072,21 +1079,26 @@ static struct conference_bridge *join_conference_bridge(const char *name, struct
}
/*!
* \ brief Leave a conference bridge
*
* \ param conference_bridge The conference bridge to leave
* \ param conference_bridge_user The conference bridge user structure
* \ brief Leave a conference
*
* \ param user The conference user
*/
static void leave_conference _bridge ( struct conference_bridge * conference_bridge , struct conference_bridge _user * conference_bridge_ user)
static void leave_conference ( struct conference_bridge _user * user)
{
ao2_lock ( conference_bridge ) ;
struct post_join_action * action ;
handle_conf_user_leave ( conference_bridge_user ) ;
ao2_lock ( user - > conference_bridge ) ;
handle_conf_user_leave ( user ) ;
ao2_unlock ( user - > conference_bridge ) ;
/* Done mucking with the conference bridge, huzzah */
ao2_unlock ( conference_bridge ) ;
ao2_ref ( conference_bridge , - 1 ) ;
/* Discard any post-join actions */
while ( ( action = AST_LIST_REMOVE_HEAD ( & user - > post_join_list , list ) ) ) {
ast_free ( action ) ;
}
/* Done mucking with the conference, huzzah */
ao2_ref ( user - > conference_bridge , - 1 ) ;
user - > conference_bridge = NULL ;
}
/*!
@ -1469,7 +1481,7 @@ static int confbridge_exec(struct ast_channel *chan, const char *data)
/* if we're shutting down, don't attempt to do further processing */
if ( ast_shutting_down ( ) ) {
leave_conference _bridge ( conference_bridge , & conference_bridge_user ) ;
leave_conference ( & conference_bridge_user ) ;
conference_bridge = NULL ;
goto confbridge_cleanup ;
}
@ -1495,7 +1507,7 @@ static int confbridge_exec(struct ast_channel *chan, const char *data)
}
/* Easy as pie, depart this channel from the conference bridge */
leave_conference _bridge ( conference_bridge , & conference_bridge_user ) ;
leave_conference ( & conference_bridge_user ) ;
conference_bridge = NULL ;
/* If the user was kicked from the conference play back the audio prompt for it */