@ -211,6 +211,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
< parameter name = " Conference " required = " true " / >
< parameter name = " Channel " required = " true " >
< para > If this parameter is not a complete channel name , the first channel with this prefix will be used . < / para >
< para > If this parameter is " all " , all channels will be muted . < / para >
< para > If this parameter is " participants " , all non - admin channels will be muted . < / para >
< / parameter >
< / syntax >
< description >
@ -225,6 +227,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
< parameter name = " Conference " required = " true " / >
< parameter name = " Channel " required = " true " >
< para > If this parameter is not a complete channel name , the first channel with this prefix will be used . < / para >
< para > If this parameter is " all " , all channels will be unmuted . < / para >
< para > If this parameter is " participants " , all non - admin channels will be unmuted . < / para >
< / parameter >
< / syntax >
< description >
@ -238,8 +242,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
< xi : include xpointer = " xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID']) " / >
< parameter name = " Conference " required = " true " / >
< parameter name = " Channel " required = " true " >
< para > If this parameter is not a complete channel name , the first channel with this prefix will be used . < / para >
< para > If this parameter is " all " , all channels will be kicked from the conference . < / para >
< para > If this parameter is " participants " , all non - admin channels will be kicked from the conference . < / para >
< / parameter >
< / syntax >
< description >
@ -2189,37 +2193,47 @@ int conf_handle_dtmf(struct ast_bridge_channel *bridge_channel,
return 0 ;
}
static int kick_conference_participant ( struct confbridge_conference * conference , const char * channel )
static int kick_conference_participant ( struct confbridge_conference * conference ,
const char * channel )
{
int res = - 1 ;
int match ;
struct confbridge_user * user = NULL ;
int all = ! strcasecmp ( " all " , channel ) ;
int participants = ! strcasecmp ( " participants " , channel ) ;
SCOPED_AO2LOCK ( bridge_lock , conference ) ;
AST_LIST_TRAVERSE ( & conference - > active_list , user , list ) {
if ( ! strcasecmp ( ast_channel_name ( user - > chan ) , channel ) & & ! user - > kicked ) {
user - > kicked = 1 ;
pbx_builtin_setvar_helper ( user - > chan , " CONFBRIDGE_RESULT " , " KICKED " ) ;
ast_bridge_remove ( conference - > bridge , user - > chan ) ;
return 0 ;
} else if ( ! strcasecmp ( " all " , channel ) ) {
if ( user - > kicked ) {
continue ;
}
match = ! strcasecmp ( channel , ast_channel_name ( user - > chan ) ) ;
if ( match | | all
| | ( participants & & ! ast_test_flag ( & user - > u_profile , USER_OPT_ADMIN ) ) ) {
user - > kicked = 1 ;
pbx_builtin_setvar_helper ( user - > chan , " CONFBRIDGE_RESULT " , " KICKED " ) ;
ast_bridge_remove ( conference - > bridge , user - > chan ) ;
res = 0 ;
if ( match ) {
return res ;
}
}
}
AST_LIST_TRAVERSE ( & conference - > waiting_list , user , list ) {
if ( ! strcasecmp ( ast_channel_name ( user - > chan ) , channel ) & & ! user - > kicked ) {
user - > kicked = 1 ;
pbx_builtin_setvar_helper ( user - > chan , " CONFBRIDGE_RESULT " , " KICKED " ) ;
ast_bridge_remove ( conference - > bridge , user - > chan ) ;
return 0 ;
} else if ( ! strcasecmp ( " all " , channel ) ) {
if ( user - > kicked ) {
continue ;
}
match = ! strcasecmp ( channel , ast_channel_name ( user - > chan ) ) ;
if ( match | | all
| | ( participants & & ! ast_test_flag ( & user - > u_profile , USER_OPT_ADMIN ) ) ) {
user - > kicked = 1 ;
pbx_builtin_setvar_helper ( user - > chan , " CONFBRIDGE_RESULT " , " KICKED " ) ;
ast_bridge_remove ( conference - > bridge , user - > chan ) ;
res = 0 ;
if ( match ) {
return res ;
}
}
}
@ -2261,10 +2275,13 @@ static char *complete_confbridge_participant(const char *conference_name, const
return NULL ;
}
if ( ! state ) {
if ( ! strncasecmp ( " all " , word , wordlen ) & & + + which > state ) {
return ast_strdup ( " all " ) ;
}
state - - ;
if ( ! strncasecmp ( " participants " , word , wordlen ) & & + + which > state ) {
return ast_strdup ( " participants " ) ;
}
{
SCOPED_AO2LOCK ( bridge_lock , conference ) ;
@ -2295,7 +2312,8 @@ static char *handle_cli_confbridge_kick(struct ast_cli_entry *e, int cmd, struct
e - > command = " confbridge kick " ;
e - > usage =
" Usage: confbridge kick <conference> <channel> \n "
" Kicks a channel out of the conference bridge (all to kick everyone). \n " ;
" Kicks a channel out of the conference bridge. \n "
" (all to kick everyone, participants to kick non-admins). \n " ;
return NULL ;
case CLI_GENERATE :
if ( a - > pos = = 2 ) {
@ -2319,10 +2337,14 @@ static char *handle_cli_confbridge_kick(struct ast_cli_entry *e, int cmd, struct
not_found = kick_conference_participant ( conference , a - > argv [ 3 ] ) ;
ao2_ref ( conference , - 1 ) ;
if ( not_found ) {
ast_cli ( a - > fd , " No participant named '%s' found! \n " , a - > argv [ 3 ] ) ;
if ( ! strcasecmp ( " all " , a - > argv [ 3 ] ) | | ! strcasecmp ( " participants " , a - > argv [ 3 ] ) ) {
ast_cli ( a - > fd , " No participants found! \n " ) ;
} else {
ast_cli ( a - > fd , " No participant named '%s' found! \n " , a - > argv [ 3 ] ) ;
}
return CLI_SUCCESS ;
}
ast_cli ( a - > fd , " Participant '%s' kicked out of conference '%s' \n " , a - > argv [ 3 ] , a - > argv [ 2 ] ) ;
ast_cli ( a - > fd , " Kicked '%s' out of conference '%s'\n " , a - > argv [ 3 ] , a - > argv [ 2 ] ) ;
return CLI_SUCCESS ;
}
@ -2454,6 +2476,30 @@ static int generic_lock_unlock_helper(int lock, const char *conference_name)
return res ;
}
/* \internal
* \ brief Mute / unmute a single user .
*/
static void generic_mute_unmute_user ( struct confbridge_conference * conference , struct confbridge_user * user , int mute )
{
/* Set user level mute request. */
user - > muted = mute ? 1 : 0 ;
conf_update_user_mute ( user ) ;
ast_test_suite_event_notify ( " CONF_MUTE " ,
" Message: participant %s %s \r \n "
" Conference: %s \r \n "
" Channel: %s " ,
ast_channel_name ( user - > chan ) ,
mute ? " muted " : " unmuted " ,
conference - > b_profile . name ,
ast_channel_name ( user - > chan ) ) ;
if ( mute ) {
send_mute_event ( user - > chan , conference ) ;
} else {
send_unmute_event ( user - > chan , conference ) ;
}
}
/* \internal
* \ brief finds a conference user by channel name and mutes / unmutes them .
*
@ -2461,53 +2507,48 @@ static int generic_lock_unlock_helper(int lock, const char *conference_name)
* \ retval - 1 conference not found
* \ retval - 2 user not found
*/
static int generic_mute_unmute_helper ( int mute , const char * conference_name , const char * chan_name )
static int generic_mute_unmute_helper ( int mute , const char * conference_name ,
const char * chan_name )
{
struct confbridge_conference * conference ;
RAII_VAR ( struct confbridge_conference * , conference , NULL , ao2_cleanup ) ;
struct confbridge_user * user ;
int res = 0 ;
int all = ! strcasecmp ( " all " , chan_name ) ;
int participants = ! strcasecmp ( " participants " , chan_name ) ;
int res = - 2 ;
conference = ao2_find ( conference_bridges , conference_name , OBJ_KEY ) ;
if ( ! conference ) {
return - 1 ;
}
ao2_lock ( conference ) ;
AST_LIST_TRAVERSE ( & conference - > active_list , user , list ) {
if ( ! strncmp ( chan_name , ast_channel_name ( user - > chan ) , strlen ( chan_name ) ) ) {
break ;
{
SCOPED_AO2LOCK ( bridge_lock , conference ) ;
AST_LIST_TRAVERSE ( & conference - > active_list , user , list ) {
int match = ! strncasecmp ( chan_name , ast_channel_name ( user - > chan ) ,
strlen ( chan_name ) ) ;
if ( match | | all
| | ( participants & & ! ast_test_flag ( & user - > u_profile , USER_OPT_ADMIN ) ) ) {
generic_mute_unmute_user ( conference , user , mute ) ;
res = 0 ;
if ( match ) {
return res ;
}
}
}
}
if ( ! user ) {
/* user is not in the active list so check the waiting list as well */
AST_LIST_TRAVERSE ( & conference - > waiting_list , user , list ) {
if ( ! strncmp ( chan_name , ast_channel_name ( user - > chan ) , strlen ( chan_name ) ) ) {
break ;
int match = ! strncasecmp ( chan_name , ast_channel_name ( user - > chan ) ,
strlen ( chan_name ) ) ;
if ( match | | all
| | ( participants & & ! ast_test_flag ( & user - > u_profile , USER_OPT_ADMIN ) ) ) {
generic_mute_unmute_user ( conference , user , mute ) ;
res = 0 ;
if ( match ) {
return res ;
}
}
}
}
if ( user ) {
/* Set user level mute request. */
user - > muted = mute ? 1 : 0 ;
conf_update_user_mute ( user ) ;
ast_test_suite_event_notify ( " CONF_MUTE " ,
" Message: participant %s %s \r \n "
" Conference: %s \r \n "
" Channel: %s " ,
ast_channel_name ( user - > chan ) ,
mute ? " muted " : " unmuted " ,
conference - > b_profile . name ,
ast_channel_name ( user - > chan ) ) ;
if ( mute ) {
send_mute_event ( user - > chan , conference ) ;
} else {
send_unmute_event ( user - > chan , conference ) ;
}
} else {
res = - 2 ; ;
}
ao2_unlock ( conference ) ;
ao2_ref ( conference , - 1 ) ;
return res ;
}
@ -2520,7 +2561,11 @@ static int cli_mute_unmute_helper(int mute, struct ast_cli_args *a)
ast_cli ( a - > fd , " No conference bridge named '%s' found! \n " , a - > argv [ 2 ] ) ;
return - 1 ;
} else if ( res = = - 2 ) {
ast_cli ( a - > fd , " No channel named '%s' found in conference %s \n " , a - > argv [ 3 ] , a - > argv [ 2 ] ) ;
if ( ! strcasecmp ( " all " , a - > argv [ 3 ] ) | | ! strcasecmp ( " participants " , a - > argv [ 3 ] ) ) {
ast_cli ( a - > fd , " No participants found in conference %s \n " , a - > argv [ 2 ] ) ;
} else {
ast_cli ( a - > fd , " No channel named '%s' found in conference %s \n " , a - > argv [ 3 ] , a - > argv [ 2 ] ) ;
}
return - 1 ;
}
ast_cli ( a - > fd , " %s %s from confbridge %s \n " , mute ? " Muting " : " Unmuting " , a - > argv [ 3 ] , a - > argv [ 2 ] ) ;
@ -2535,6 +2580,7 @@ static char *handle_cli_confbridge_mute(struct ast_cli_entry *e, int cmd, struct
e - > usage =
" Usage: confbridge mute <conference> <channel> \n "
" Mute a channel in a conference. \n "
" (all to mute everyone, participants to mute non-admins) \n "
" If the specified channel is a prefix, \n "
" the action will be taken on the first \n "
" matching channel. \n " ;
@ -2565,6 +2611,7 @@ static char *handle_cli_confbridge_unmute(struct ast_cli_entry *e, int cmd, stru
e - > usage =
" Usage: confbridge unmute <conference> <channel> \n "
" Unmute a channel in a conference. \n "
" (all to unmute everyone, participants to unmute non-admins) \n "
" If the specified channel is a prefix, \n "
" the action will be taken on the first \n "
" matching channel. \n " ;
@ -2735,8 +2782,8 @@ static char *handle_cli_confbridge_stop_record(struct ast_cli_entry *e, int cmd,
static struct ast_cli_entry cli_confbridge [ ] = {
AST_CLI_DEFINE ( handle_cli_confbridge_list , " List conference bridges and participants. " ) ,
AST_CLI_DEFINE ( handle_cli_confbridge_kick , " Kick participants out of conference bridges. " ) ,
AST_CLI_DEFINE ( handle_cli_confbridge_mute , " Mute a participant." ) ,
AST_CLI_DEFINE ( handle_cli_confbridge_unmute , " Unmute a participant." ) ,
AST_CLI_DEFINE ( handle_cli_confbridge_mute , " Mute participants ." ) ,
AST_CLI_DEFINE ( handle_cli_confbridge_unmute , " Unmute participants ." ) ,
AST_CLI_DEFINE ( handle_cli_confbridge_lock , " Lock a conference. " ) ,
AST_CLI_DEFINE ( handle_cli_confbridge_unlock , " Unlock a conference. " ) ,
AST_CLI_DEFINE ( handle_cli_confbridge_start_record , " Start recording a conference " ) ,