FS-11206: [mod_conference] add conference hold feature

This commit is contained in:
Mike Jerris 2018-06-21 05:32:22 -04:00 committed by Muteesa Fred
parent 868e92649e
commit 7f3878dfcb
8 changed files with 242 additions and 30 deletions

View File

@ -78,7 +78,9 @@ void conference_al_gen_arc(conference_obj_t *conference, switch_stream_handle_t
switch_mutex_lock(conference->member_mutex); switch_mutex_lock(conference->member_mutex);
for (member = conference->members; member; member = member->next) { for (member = conference->members; member; member = member->next) {
if (member->channel && conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK) && !conference_utils_member_test_flag(member, MFLAG_NO_POSITIONAL)) { if (member->channel && conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK) &&
!conference_utils_member_test_flag(member, MFLAG_HOLD) &&
!conference_utils_member_test_flag(member, MFLAG_NO_POSITIONAL)) {
count++; count++;
} }
} }
@ -112,7 +114,9 @@ void conference_al_gen_arc(conference_obj_t *conference, switch_stream_handle_t
for (member = conference->members; member; member = member->next) { for (member = conference->members; member; member = member->next) {
if (!member->channel || conference_utils_member_test_flag(member, MFLAG_NO_POSITIONAL) || !conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) { if (!member->channel || conference_utils_member_test_flag(member, MFLAG_NO_POSITIONAL) ||
conference_utils_member_test_flag(member, MFLAG_HOLD) ||
!conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) {
continue; continue;
} }

View File

@ -72,6 +72,8 @@ api_command_t conference_api_sub_commands[] = {
{"vid-flip", (void_fn_t) & conference_api_sub_vid_flip, CONF_API_SUB_MEMBER_TARGET, "vid-flip", "<[member_id|all|last|non_moderator]>"}, {"vid-flip", (void_fn_t) & conference_api_sub_vid_flip, CONF_API_SUB_MEMBER_TARGET, "vid-flip", "<[member_id|all|last|non_moderator]>"},
{"vid-border", (void_fn_t) & conference_api_sub_vid_border, CONF_API_SUB_MEMBER_TARGET, "vid-border", "<[member_id|all|last|non_moderator]>"}, {"vid-border", (void_fn_t) & conference_api_sub_vid_border, CONF_API_SUB_MEMBER_TARGET, "vid-border", "<[member_id|all|last|non_moderator]>"},
{"hup", (void_fn_t) & conference_api_sub_hup, CONF_API_SUB_MEMBER_TARGET, "hup", "<[member_id|all|last|non_moderator]>"}, {"hup", (void_fn_t) & conference_api_sub_hup, CONF_API_SUB_MEMBER_TARGET, "hup", "<[member_id|all|last|non_moderator]>"},
{"hold", (void_fn_t) & conference_api_sub_hold, CONF_API_SUB_MEMBER_TARGET, "hold", "<[member_id|all]|last|non_moderator> [file]"},
{"unhold", (void_fn_t) & conference_api_sub_unhold, CONF_API_SUB_MEMBER_TARGET, "unhold", "<[member_id|all]|last|non_moderator>"},
{"mute", (void_fn_t) & conference_api_sub_mute, CONF_API_SUB_MEMBER_TARGET, "mute", "<[member_id|all]|last|non_moderator> [<quiet>]"}, {"mute", (void_fn_t) & conference_api_sub_mute, CONF_API_SUB_MEMBER_TARGET, "mute", "<[member_id|all]|last|non_moderator> [<quiet>]"},
{"tmute", (void_fn_t) & conference_api_sub_tmute, CONF_API_SUB_MEMBER_TARGET, "tmute", "<[member_id|all]|last|non_moderator> [<quiet>]"}, {"tmute", (void_fn_t) & conference_api_sub_tmute, CONF_API_SUB_MEMBER_TARGET, "tmute", "<[member_id|all]|last|non_moderator> [<quiet>]"},
{"unmute", (void_fn_t) & conference_api_sub_unmute, CONF_API_SUB_MEMBER_TARGET, "unmute", "<[member_id|all]|last|non_moderator> [<quiet>]"}, {"unmute", (void_fn_t) & conference_api_sub_unmute, CONF_API_SUB_MEMBER_TARGET, "unmute", "<[member_id|all]|last|non_moderator> [<quiet>]"},
@ -313,6 +315,11 @@ switch_status_t conference_api_sub_mute(conference_member_t *member, switch_stre
if (member == NULL) if (member == NULL)
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
if (conference_utils_member_test_flag(member, MFLAG_HOLD)) {
if (stream) stream->write_function(stream, "-ERR mute %u\n", member->id);
return SWITCH_STATUS_SUCCESS;
}
conference_utils_member_clear_flag_locked(member, MFLAG_CAN_SPEAK); conference_utils_member_clear_flag_locked(member, MFLAG_CAN_SPEAK);
conference_utils_member_clear_flag_locked(member, MFLAG_TALKING); conference_utils_member_clear_flag_locked(member, MFLAG_TALKING);
@ -345,6 +352,107 @@ switch_status_t conference_api_sub_mute(conference_member_t *member, switch_stre
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
switch_status_t conference_api_sub_unhold(conference_member_t *member, switch_stream_handle_t *stream, void *data)
{
mcu_layer_t *layer = NULL;
switch_event_t *event;
if (member == NULL)
return SWITCH_STATUS_GENERR;
conference_utils_member_clear_flag_locked(member, MFLAG_HOLD);
if (member->session && !conference_utils_member_test_flag(member, MFLAG_MUTE_DETECT)) {
switch_core_media_hard_mute(member->session, SWITCH_FALSE);
}
conference_member_stop_file(member, FILE_STOP_ALL);
if (switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_SENDONLY) {
if ((layer = conference_video_get_layer_locked(member))) {
layer->clear = 1;
conference_video_release_layer(&layer);
}
conference_video_reset_video_bitrate_counters(member);
if (member->channel) {
switch_channel_clear_flag(member->channel, CF_VIDEO_PAUSE_READ);
switch_channel_video_sync(member->channel);
}
}
if (stream != NULL) {
stream->write_function(stream, "+OK unhold %u\n", member->id);
}
if (test_eflag(member->conference, EFLAG_HOLD_MEMBER) &&
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
conference_member_add_event_data(member, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "unhold-member");
switch_event_fire(&event);
}
if (conference_utils_test_flag(member->conference, CFLAG_POSITIONAL)) {
conference_al_gen_arc(member->conference, NULL);
}
conference_member_update_status_field(member);
return SWITCH_STATUS_SUCCESS;
}
switch_status_t conference_api_sub_hold(conference_member_t *member, switch_stream_handle_t *stream, void *data)
{
switch_event_t *event;
if (member == NULL)
return SWITCH_STATUS_GENERR;
conference_utils_member_clear_flag_locked(member, MFLAG_TALKING);
if (switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_SENDONLY) {
conference_video_reset_video_bitrate_counters(member);
if (member->channel) {
switch_channel_set_flag(member->channel, CF_VIDEO_PAUSE_READ);
switch_core_session_request_video_refresh(member->session);
switch_channel_video_sync(member->channel);
}
}
if (member->session) {
switch_core_media_hard_mute(member->session, SWITCH_TRUE);
}
conference_utils_member_set_flag(member, MFLAG_HOLD);
conference_member_set_score_iir(member, 0);
if (!zstr(data)) {
conference_member_play_file(member, data, 0, SWITCH_FALSE);
}
if (stream != NULL) {
stream->write_function(stream, "+OK hold %u\n", member->id);
}
if (test_eflag(member->conference, EFLAG_HOLD_MEMBER) &&
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
conference_member_add_event_data(member, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "hold-member");
switch_event_fire(&event);
}
if (conference_utils_test_flag(member->conference, CFLAG_POSITIONAL)) {
conference_al_gen_arc(member->conference, NULL);
}
conference_member_update_status_field(member);
return SWITCH_STATUS_SUCCESS;
}
switch_status_t conference_api_sub_tmute(conference_member_t *member, switch_stream_handle_t *stream, void *data) switch_status_t conference_api_sub_tmute(conference_member_t *member, switch_stream_handle_t *stream, void *data)
{ {
@ -352,6 +460,11 @@ switch_status_t conference_api_sub_tmute(conference_member_t *member, switch_str
if (member == NULL) if (member == NULL)
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
if (conference_utils_member_test_flag(member, MFLAG_HOLD)) {
if (stream) stream->write_function(stream, "-ERR mute %u\n", member->id);
return SWITCH_STATUS_SUCCESS;
}
if (conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) { if (conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) {
return conference_api_sub_mute(member, stream, data); return conference_api_sub_mute(member, stream, data);
} }
@ -367,6 +480,11 @@ switch_status_t conference_api_sub_unmute(conference_member_t *member, switch_st
if (member == NULL) if (member == NULL)
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
if (conference_utils_member_test_flag(member, MFLAG_HOLD)) {
if (stream) stream->write_function(stream, "-ERR unmute %u\n", member->id);
return SWITCH_STATUS_SUCCESS;
}
conference_utils_member_set_flag_locked(member, MFLAG_CAN_SPEAK); conference_utils_member_set_flag_locked(member, MFLAG_CAN_SPEAK);
if (member->session && !conference_utils_member_test_flag(member, MFLAG_MUTE_DETECT)) { if (member->session && !conference_utils_member_test_flag(member, MFLAG_MUTE_DETECT)) {
@ -413,6 +531,11 @@ switch_status_t conference_api_sub_conference_video_vmute_snap(conference_member
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
if (conference_utils_member_test_flag(member, MFLAG_HOLD)) {
if (stream) stream->write_function(stream, "-ERR member %u is on hold\n", member->id);
return SWITCH_STATUS_SUCCESS;
}
if (stream != NULL) { if (stream != NULL) {
stream->write_function(stream, "+OK vmute image snapped %u\n", member->id); stream->write_function(stream, "+OK vmute image snapped %u\n", member->id);
} }
@ -437,6 +560,11 @@ switch_status_t conference_api_sub_vmute(conference_member_t *member, switch_str
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
if (conference_utils_member_test_flag(member, MFLAG_HOLD)) {
if (stream) stream->write_function(stream, "-ERR member %u is on hold\n", member->id);
return SWITCH_STATUS_SUCCESS;
}
conference_utils_member_clear_flag_locked(member, MFLAG_CAN_BE_SEEN); conference_utils_member_clear_flag_locked(member, MFLAG_CAN_BE_SEEN);
conference_video_reset_video_bitrate_counters(member); conference_video_reset_video_bitrate_counters(member);
@ -473,6 +601,11 @@ switch_status_t conference_api_sub_tvmute(conference_member_t *member, switch_st
if (member == NULL) if (member == NULL)
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
if (conference_utils_member_test_flag(member, MFLAG_HOLD)) {
if (stream) stream->write_function(stream, "-ERR member %u is on hold\n", member->id);
return SWITCH_STATUS_SUCCESS;
}
if (conference_utils_member_test_flag(member, MFLAG_CAN_BE_SEEN)) { if (conference_utils_member_test_flag(member, MFLAG_CAN_BE_SEEN)) {
return conference_api_sub_vmute(member, stream, data); return conference_api_sub_vmute(member, stream, data);
} }
@ -493,6 +626,11 @@ switch_status_t conference_api_sub_unvmute(conference_member_t *member, switch_s
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
if (conference_utils_member_test_flag(member, MFLAG_HOLD)) {
if (stream) stream->write_function(stream, "-ERR member %u is on hold\n", member->id);
return SWITCH_STATUS_SUCCESS;
}
if ((layer = conference_video_get_layer_locked(member))) { if ((layer = conference_video_get_layer_locked(member))) {
layer->clear = 1; layer->clear = 1;
conference_video_release_layer(&layer); conference_video_release_layer(&layer);
@ -534,6 +672,11 @@ switch_status_t conference_api_sub_vblind(conference_member_t *member, switch_st
if (member == NULL) if (member == NULL)
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
if (conference_utils_member_test_flag(member, MFLAG_HOLD)) {
if (stream) stream->write_function(stream, "-ERR member %u is on hold\n", member->id);
return SWITCH_STATUS_SUCCESS;
}
switch_core_session_write_blank_video(member->session, 50); switch_core_session_write_blank_video(member->session, 50);
conference_utils_member_clear_flag_locked(member, MFLAG_CAN_SEE); conference_utils_member_clear_flag_locked(member, MFLAG_CAN_SEE);
conference_video_reset_video_bitrate_counters(member); conference_video_reset_video_bitrate_counters(member);
@ -565,6 +708,11 @@ switch_status_t conference_api_sub_tvblind(conference_member_t *member, switch_s
if (member == NULL) if (member == NULL)
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
if (conference_utils_member_test_flag(member, MFLAG_HOLD)) {
if (stream) stream->write_function(stream, "-ERR member %u is on hold\n", member->id);
return SWITCH_STATUS_SUCCESS;
}
if (conference_utils_member_test_flag(member, MFLAG_CAN_SEE)) { if (conference_utils_member_test_flag(member, MFLAG_CAN_SEE)) {
return conference_api_sub_vblind(member, stream, data); return conference_api_sub_vblind(member, stream, data);
} }
@ -580,6 +728,11 @@ switch_status_t conference_api_sub_unvblind(conference_member_t *member, switch_
if (member == NULL) if (member == NULL)
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
if (conference_utils_member_test_flag(member, MFLAG_HOLD)) {
if (stream) stream->write_function(stream, "-ERR member %u is on hold\n", member->id);
return SWITCH_STATUS_SUCCESS;
}
conference_utils_member_set_flag_locked(member, MFLAG_CAN_SEE); conference_utils_member_set_flag_locked(member, MFLAG_CAN_SEE);
conference_video_reset_video_bitrate_counters(member); conference_video_reset_video_bitrate_counters(member);
@ -613,6 +766,11 @@ switch_status_t conference_api_sub_deaf(conference_member_t *member, switch_stre
if (member == NULL) if (member == NULL)
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
if (conference_utils_member_test_flag(member, MFLAG_HOLD)) {
if (stream) stream->write_function(stream, "-ERR member %u is on hold\n", member->id);
return SWITCH_STATUS_SUCCESS;
}
conference_utils_member_clear_flag_locked(member, MFLAG_CAN_HEAR); conference_utils_member_clear_flag_locked(member, MFLAG_CAN_HEAR);
if (!(data) || !strstr((char *) data, "quiet")) { if (!(data) || !strstr((char *) data, "quiet")) {
@ -655,6 +813,11 @@ switch_status_t conference_api_sub_undeaf(conference_member_t *member, switch_st
if (member == NULL) if (member == NULL)
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
if (conference_utils_member_test_flag(member, MFLAG_HOLD)) {
if (stream) stream->write_function(stream, "-ERR member %u is on hold\n", member->id);
return SWITCH_STATUS_SUCCESS;
}
conference_utils_member_set_flag_locked(member, MFLAG_CAN_HEAR); conference_utils_member_set_flag_locked(member, MFLAG_CAN_HEAR);
if (!(data) || !strstr((char *) data, "quiet")) { if (!(data) || !strstr((char *) data, "quiet")) {

View File

@ -132,6 +132,8 @@ void conference_loop_mute_toggle(conference_member_t *member, caller_control_act
if (member == NULL) if (member == NULL)
return; return;
if (conference_utils_member_test_flag(member, MFLAG_HOLD)) return;
if (conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) { if (conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) {
conference_api_sub_mute(member, NULL, NULL); conference_api_sub_mute(member, NULL, NULL);
} else { } else {
@ -144,6 +146,8 @@ void conference_loop_mute_toggle(conference_member_t *member, caller_control_act
void conference_loop_mute_on(conference_member_t *member, caller_control_action_t *action) void conference_loop_mute_on(conference_member_t *member, caller_control_action_t *action)
{ {
if (conference_utils_member_test_flag(member, MFLAG_HOLD)) return;
if (conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) { if (conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) {
conference_api_sub_mute(member, NULL, NULL); conference_api_sub_mute(member, NULL, NULL);
} }
@ -151,6 +155,8 @@ void conference_loop_mute_on(conference_member_t *member, caller_control_action_
void conference_loop_mute_off(conference_member_t *member, caller_control_action_t *action) void conference_loop_mute_off(conference_member_t *member, caller_control_action_t *action)
{ {
if (conference_utils_member_test_flag(member, MFLAG_HOLD)) return;
if (!conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) { if (!conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) {
conference_api_sub_unmute(member, NULL, NULL); conference_api_sub_unmute(member, NULL, NULL);
if (!conference_utils_member_test_flag(member, MFLAG_CAN_HEAR)) { if (!conference_utils_member_test_flag(member, MFLAG_CAN_HEAR)) {
@ -280,6 +286,8 @@ void conference_loop_deafmute_toggle(conference_member_t *member, caller_control
if (member == NULL) if (member == NULL)
return; return;
if (conference_utils_member_test_flag(member, MFLAG_HOLD)) return;
if (conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) { if (conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) {
conference_api_sub_mute(member, NULL, NULL); conference_api_sub_mute(member, NULL, NULL);
if (conference_utils_member_test_flag(member, MFLAG_CAN_HEAR)) { if (conference_utils_member_test_flag(member, MFLAG_CAN_HEAR)) {
@ -933,7 +941,8 @@ void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, void *ob
/* if the member can speak, compute the audio energy level and */ /* if the member can speak, compute the audio energy level and */
/* generate events when the level crosses the threshold */ /* generate events when the level crosses the threshold */
if ((conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK) || conference_utils_member_test_flag(member, MFLAG_MUTE_DETECT))) { if (((conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK) && !conference_utils_member_test_flag(member, MFLAG_HOLD)) ||
conference_utils_member_test_flag(member, MFLAG_MUTE_DETECT))) {
uint32_t energy = 0, i = 0, samples = 0, j = 0; uint32_t energy = 0, i = 0, samples = 0, j = 0;
int16_t *data; int16_t *data;
int gate_check = 0; int gate_check = 0;
@ -990,7 +999,7 @@ void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, void *ob
gate_check = conference_member_noise_gate_check(member); gate_check = conference_member_noise_gate_check(member);
if (conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) { if (conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK) && !conference_utils_member_test_flag(member, MFLAG_HOLD)) {
if (member->max_energy_level) { if (member->max_energy_level) {
if (member->score > member->max_energy_level && ++member->max_energy_hits > member->max_energy_hit_trigger) { if (member->score > member->max_energy_level && ++member->max_energy_hits > member->max_energy_hit_trigger) {
member->mute_counter = member->burst_mute_count; member->mute_counter = member->burst_mute_count;
@ -1131,6 +1140,7 @@ void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, void *ob
member->talking_count = 0; member->talking_count = 0;
if (test_eflag(member->conference, EFLAG_START_TALKING) && conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK) && if (test_eflag(member->conference, EFLAG_START_TALKING) && conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK) &&
!conference_utils_member_test_flag(member, MFLAG_HOLD) &&
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
conference_member_add_event_data(member, event); conference_member_add_event_data(member, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "start-talking"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "start-talking");
@ -1157,7 +1167,8 @@ void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, void *ob
hangunder_hits--; hangunder_hits--;
} }
if (conference_utils_member_test_flag(member, MFLAG_TALKING) && conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) { if (conference_utils_member_test_flag(member, MFLAG_TALKING) && conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK) &&
!conference_utils_member_test_flag(member, MFLAG_HOLD)) {
if (++hangover_hits >= hangover) { if (++hangover_hits >= hangover) {
hangover_hits = hangunder_hits = 0; hangover_hits = hangunder_hits = 0;
@ -1189,6 +1200,7 @@ void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, void *ob
/* skip frames that are not actual media or when we are muted or silent */ /* skip frames that are not actual media or when we are muted or silent */
if ((conference_utils_member_test_flag(member, MFLAG_TALKING) || member->energy_level == 0 || conference_utils_test_flag(member->conference, CFLAG_AUDIO_ALWAYS)) if ((conference_utils_member_test_flag(member, MFLAG_TALKING) || member->energy_level == 0 || conference_utils_test_flag(member->conference, CFLAG_AUDIO_ALWAYS))
&& conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK) && !conference_utils_test_flag(member->conference, CFLAG_WAIT_MOD) && conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK) && !conference_utils_test_flag(member->conference, CFLAG_WAIT_MOD)
&& !conference_utils_member_test_flag(member, MFLAG_HOLD)
&& (member->conference->count > 1 || (member->conference->record_count && member->conference->count >= member->conference->min_recording_participants))) { && (member->conference->count > 1 || (member->conference->record_count && member->conference->count >= member->conference->min_recording_participants))) {
switch_audio_resampler_t *read_resampler = member->read_resampler; switch_audio_resampler_t *read_resampler = member->read_resampler;
void *data; void *data;

View File

@ -133,7 +133,9 @@ void conference_member_update_status_field(conference_member_t *member)
switch_live_array_lock(member->conference->la); switch_live_array_lock(member->conference->la);
if (!conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) { if (conference_utils_member_test_flag(member, MFLAG_HOLD)) {
str = "HOLD";
} else if (!conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) {
str = "MUTE"; str = "MUTE";
} else if (switch_channel_test_flag(member->channel, CF_HOLD)) { } else if (switch_channel_test_flag(member->channel, CF_HOLD)) {
str = "HOLD"; str = "HOLD";
@ -258,6 +260,7 @@ switch_status_t conference_member_add_event_data(conference_member_t *member, sw
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Speak", "%s", conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK) ? "true" : "false" ); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Speak", "%s", conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK) ? "true" : "false" );
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Talking", "%s", conference_utils_member_test_flag(member, MFLAG_TALKING) ? "true" : "false" ); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Talking", "%s", conference_utils_member_test_flag(member, MFLAG_TALKING) ? "true" : "false" );
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Mute-Detect", "%s", conference_utils_member_test_flag(member, MFLAG_MUTE_DETECT) ? "true" : "false" ); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Mute-Detect", "%s", conference_utils_member_test_flag(member, MFLAG_MUTE_DETECT) ? "true" : "false" );
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Hold", "%s", conference_utils_member_test_flag(member, MFLAG_HOLD) ? "true" : "false" );
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-ID", "%u", member->id); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-ID", "%u", member->id);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-Type", "%s", conference_utils_member_test_flag(member, MFLAG_MOD) ? "moderator" : "member"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-Type", "%s", conference_utils_member_test_flag(member, MFLAG_MOD) ? "moderator" : "member");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-Ghost", "%s", conference_utils_member_test_flag(member, MFLAG_GHOST) ? "true" : "false"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-Ghost", "%s", conference_utils_member_test_flag(member, MFLAG_GHOST) ? "true" : "false");

View File

@ -237,9 +237,7 @@ void conference_utils_clear_eflags(char *events, uint32_t *f)
*next++ = '\0'; *next++ = '\0';
} }
if (!strcmp(event, "add-member")) { if (!strcmp(event, "del-member")) {
*f &= ~EFLAG_ADD_MEMBER;
} else if (!strcmp(event, "del-member")) {
*f &= ~EFLAG_DEL_MEMBER; *f &= ~EFLAG_DEL_MEMBER;
} else if (!strcmp(event, "energy-level")) { } else if (!strcmp(event, "energy-level")) {
*f &= ~EFLAG_ENERGY_LEVEL; *f &= ~EFLAG_ENERGY_LEVEL;
@ -257,6 +255,8 @@ void conference_utils_clear_eflags(char *events, uint32_t *f)
*f &= ~EFLAG_MUTE_DETECT; *f &= ~EFLAG_MUTE_DETECT;
} else if (!strcmp(event, "mute-member")) { } else if (!strcmp(event, "mute-member")) {
*f &= ~EFLAG_MUTE_MEMBER; *f &= ~EFLAG_MUTE_MEMBER;
} else if (!strcmp(event, "hold-member")) {
*f &= ~EFLAG_HOLD_MEMBER;
} else if (!strcmp(event, "kick-member")) { } else if (!strcmp(event, "kick-member")) {
*f &= ~EFLAG_KICK_MEMBER; *f &= ~EFLAG_KICK_MEMBER;
} else if (!strcmp(event, "dtmf-member")) { } else if (!strcmp(event, "dtmf-member")) {

View File

@ -1414,6 +1414,10 @@ switch_status_t conference_video_attach_video_layer(conference_member_t *member,
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
if (conference_utils_member_test_flag(member, MFLAG_HOLD)) {
conference_utils_member_clear_flag(member, MFLAG_DED_VID_LAYER);
return SWITCH_STATUS_FALSE;
}
if (!switch_channel_test_flag(channel, CF_VIDEO_READY) && !member->avatar_png_img) { if (!switch_channel_test_flag(channel, CF_VIDEO_READY) && !member->avatar_png_img) {
conference_utils_member_clear_flag(member, MFLAG_DED_VID_LAYER); conference_utils_member_clear_flag(member, MFLAG_DED_VID_LAYER);
@ -1425,6 +1429,8 @@ switch_status_t conference_video_attach_video_layer(conference_member_t *member,
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
switch_mutex_lock(canvas->mutex); switch_mutex_lock(canvas->mutex);
layer = &canvas->layers[idx]; layer = &canvas->layers[idx];
@ -2606,6 +2612,10 @@ switch_status_t conference_video_find_layer(conference_obj_t *conference, mcu_ca
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
if (conference_utils_member_test_flag(member, MFLAG_HOLD)) {
return SWITCH_STATUS_FALSE;
}
switch_mutex_lock(canvas->mutex); switch_mutex_lock(canvas->mutex);
for (i = 0; i < canvas->total_layers; i++) { for (i = 0; i < canvas->total_layers; i++) {
@ -2730,7 +2740,7 @@ void conference_video_pop_next_image(conference_member_t *member, switch_image_t
size = switch_queue_size(member->video_queue); size = switch_queue_size(member->video_queue);
} while(size > 1); } while(size > 1);
if (conference_utils_member_test_flag(member, MFLAG_CAN_BE_SEEN) && if (conference_utils_member_test_flag(member, MFLAG_CAN_BE_SEEN) && !conference_utils_member_test_flag(member, MFLAG_HOLD) &&
member->video_layer_id > -1 && member->video_layer_id > -1 &&
switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_SENDONLY && switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_SENDONLY &&
switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_INACTIVE switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_INACTIVE
@ -2961,7 +2971,7 @@ void conference_video_check_auto_bitrate(conference_member_t *member, mcu_layer_
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%s setting bitrate to %dkps because it was forced.\n", switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%s setting bitrate to %dkps because it was forced.\n",
switch_channel_get_name(member->channel), kps); switch_channel_get_name(member->channel), kps);
} else { } else {
if (layer && conference_utils_member_test_flag(member, MFLAG_CAN_BE_SEEN)) { if (layer && conference_utils_member_test_flag(member, MFLAG_CAN_BE_SEEN) && !conference_utils_member_test_flag(member, MFLAG_HOLD)) {
if (layer->screen_w != screen_w) { if (layer->screen_w != screen_w) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%s auto-setting bitrate to %dkps (max res %dx%d) to accommodate %dx%d resolution\n", switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%s auto-setting bitrate to %dkps (max res %dx%d) to accommodate %dx%d resolution\n",
switch_channel_get_name(member->channel), kps, screen_w, screen_h, layer->screen_w, layer->screen_h); switch_channel_get_name(member->channel), kps, screen_w, screen_h, layer->screen_w, layer->screen_h);
@ -3177,6 +3187,7 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
int no_muted = conference_utils_test_flag(imember->conference, CFLAG_VIDEO_MUTE_EXIT_CANVAS); int no_muted = conference_utils_test_flag(imember->conference, CFLAG_VIDEO_MUTE_EXIT_CANVAS);
int no_av = conference_utils_test_flag(imember->conference, CFLAG_VIDEO_REQUIRED_FOR_CANVAS); int no_av = conference_utils_test_flag(imember->conference, CFLAG_VIDEO_REQUIRED_FOR_CANVAS);
int seen = conference_utils_member_test_flag(imember, MFLAG_CAN_BE_SEEN); int seen = conference_utils_member_test_flag(imember, MFLAG_CAN_BE_SEEN);
int hold = conference_utils_member_test_flag(imember, MFLAG_HOLD);
if (imember->channel && switch_channel_ready(imember->channel) && switch_channel_test_flag(imember->channel, CF_VIDEO_READY) && if (imember->channel && switch_channel_ready(imember->channel) && switch_channel_test_flag(imember->channel, CF_VIDEO_READY) &&
imember->watching_canvas_id == canvas->canvas_id) { imember->watching_canvas_id == canvas->canvas_id) {
@ -3184,7 +3195,7 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
} }
if (imember->channel && switch_channel_ready(imember->channel) && switch_channel_test_flag(imember->channel, CF_VIDEO_READY) && if (imember->channel && switch_channel_ready(imember->channel) && switch_channel_test_flag(imember->channel, CF_VIDEO_READY) &&
!conference_utils_member_test_flag(imember, MFLAG_SECOND_SCREEN) && !conference_utils_member_test_flag(imember, MFLAG_SECOND_SCREEN) && !hold &&
conference_utils_member_test_flag(imember, MFLAG_RUNNING) && (!no_muted || seen) && (!no_av || (no_av && !imember->avatar_png_img)) conference_utils_member_test_flag(imember, MFLAG_RUNNING) && (!no_muted || seen) && (!no_av || (no_av && !imember->avatar_png_img))
&& imember->canvas_id == canvas->canvas_id && imember->video_media_flow != SWITCH_MEDIA_FLOW_SENDONLY && imember->video_media_flow != SWITCH_MEDIA_FLOW_INACTIVE) { && imember->canvas_id == canvas->canvas_id && imember->video_media_flow != SWITCH_MEDIA_FLOW_SENDONLY && imember->video_media_flow != SWITCH_MEDIA_FLOW_INACTIVE) {
video_count++; video_count++;
@ -3403,8 +3414,9 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
continue; continue;
} }
if (conference_utils_test_flag(imember->conference, CFLAG_VIDEO_MUTE_EXIT_CANVAS) && if ((conference_utils_member_test_flag(imember, MFLAG_HOLD) ||
!conference_utils_member_test_flag(imember, MFLAG_CAN_BE_SEEN) && imember->video_layer_id > -1) { (conference_utils_test_flag(imember->conference, CFLAG_VIDEO_MUTE_EXIT_CANVAS) &&
!conference_utils_member_test_flag(imember, MFLAG_CAN_BE_SEEN))) && imember->video_layer_id > -1) {
conference_video_detach_video_layer(imember); conference_video_detach_video_layer(imember);
switch_img_free(&imember->video_mute_img); switch_img_free(&imember->video_mute_img);
@ -3518,7 +3530,7 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
// switch_img_free(&layer->cur_img); // switch_img_free(&layer->cur_img);
//} //}
if (conference_utils_member_test_flag(imember, MFLAG_CAN_BE_SEEN) || switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY || switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE || conference_utils_test_flag(imember->conference, CFLAG_VIDEO_MUTE_EXIT_CANVAS)) { if ((conference_utils_member_test_flag(imember, MFLAG_CAN_BE_SEEN) && !conference_utils_member_test_flag(imember, MFLAG_HOLD)) || switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY || switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_INACTIVE || conference_utils_test_flag(imember->conference, CFLAG_VIDEO_MUTE_EXIT_CANVAS)) {
layer->mute_patched = 0; layer->mute_patched = 0;
} else { } else {
@ -3637,7 +3649,7 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
if (total > 0 && if (total > 0 &&
(!conference_utils_test_flag(imember->conference, CFLAG_VIDEO_MUTE_EXIT_CANVAS) || (!conference_utils_test_flag(imember->conference, CFLAG_VIDEO_MUTE_EXIT_CANVAS) ||
conference_utils_member_test_flag(imember, MFLAG_CAN_BE_SEEN)) && (conference_utils_member_test_flag(imember, MFLAG_CAN_BE_SEEN) && !conference_utils_member_test_flag(imember, MFLAG_HOLD))) &&
imember->session && switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_SENDONLY && imember->session && switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_SENDONLY &&
imember->session && switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_INACTIVE) { imember->session && switch_core_session_media_flow(imember->session, SWITCH_MEDIA_TYPE_VIDEO) != SWITCH_MEDIA_FLOW_INACTIVE) {
@ -3804,7 +3816,7 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
} }
if (layer) { if (layer) {
if (conference_utils_member_test_flag(omember, MFLAG_CAN_BE_SEEN)) { if (conference_utils_member_test_flag(omember, MFLAG_CAN_BE_SEEN) && !conference_utils_member_test_flag(imember, MFLAG_HOLD)) {
layer->mute_patched = 0; layer->mute_patched = 0;
} else if (!conference_utils_test_flag(omember->conference, CFLAG_VIDEO_MUTE_EXIT_CANVAS)) { } else if (!conference_utils_test_flag(omember->conference, CFLAG_VIDEO_MUTE_EXIT_CANVAS)) {
if (!layer->mute_patched) { if (!layer->mute_patched) {
@ -4954,6 +4966,7 @@ switch_status_t conference_video_thread_callback(switch_core_session_t *session,
if (frame->img && (((member->video_layer_id > -1) && canvas_id > -1) || member->canvas) && if (frame->img && (((member->video_layer_id > -1) && canvas_id > -1) || member->canvas) &&
conference_utils_member_test_flag(member, MFLAG_CAN_BE_SEEN) && conference_utils_member_test_flag(member, MFLAG_CAN_BE_SEEN) &&
!conference_utils_member_test_flag(member, MFLAG_HOLD) &&
switch_queue_size(member->video_queue) < member->conference->video_fps.fps && switch_queue_size(member->video_queue) < member->conference->video_fps.fps &&
!member->conference->canvases[canvas_id]->playing_video_file) { !member->conference->canvases[canvas_id]->playing_video_file) {

View File

@ -84,6 +84,7 @@ void conference_list(conference_obj_t *conference, switch_stream_handle_t *strea
char *uuid; char *uuid;
char *name; char *name;
uint32_t count = 0; uint32_t count = 0;
switch_bool_t hold = conference_utils_member_test_flag(member, MFLAG_HOLD);
if (conference_utils_member_test_flag(member, MFLAG_NOCHANNEL)) { if (conference_utils_member_test_flag(member, MFLAG_NOCHANNEL)) {
continue; continue;
@ -97,21 +98,26 @@ void conference_list(conference_obj_t *conference, switch_stream_handle_t *strea
stream->write_function(stream, "%u%s%s%s%s%s%s%s%s%s", stream->write_function(stream, "%u%s%s%s%s%s%s%s%s%s",
member->id, delim, name, delim, uuid, delim, profile->caller_id_name, delim, profile->caller_id_number, delim); member->id, delim, name, delim, uuid, delim, profile->caller_id_name, delim, profile->caller_id_number, delim);
if (conference_utils_member_test_flag(member, MFLAG_CAN_HEAR)) { if (!hold && conference_utils_member_test_flag(member, MFLAG_CAN_HEAR)) {
stream->write_function(stream, "hear"); stream->write_function(stream, "hear");
count++; count++;
} }
if (conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) { if (!hold && conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) {
stream->write_function(stream, "%s%s", count ? "|" : "", "speak"); stream->write_function(stream, "%s%s", count ? "|" : "", "speak");
count++; count++;
} }
if (conference_utils_member_test_flag(member, MFLAG_TALKING)) { if (!hold && conference_utils_member_test_flag(member, MFLAG_TALKING)) {
stream->write_function(stream, "%s%s", count ? "|" : "", "talking"); stream->write_function(stream, "%s%s", count ? "|" : "", "talking");
count++; count++;
} }
if (hold) {
stream->write_function(stream, "%s%s", count ? "|" : "", "hold");
count++;
}
if (switch_channel_test_flag(switch_core_session_get_channel(member->session), CF_VIDEO)) { if (switch_channel_test_flag(switch_core_session_get_channel(member->session), CF_VIDEO)) {
stream->write_function(stream, "%s%s", count ? "|" : "", "video"); stream->write_function(stream, "%s%s", count ? "|" : "", "video");
count++; count++;
@ -331,6 +337,7 @@ void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, void *ob
switch_channel_test_flag(channel, CF_VIDEO_READY) && switch_channel_test_flag(channel, CF_VIDEO_READY) &&
imember->video_media_flow != SWITCH_MEDIA_FLOW_SENDONLY && imember->video_media_flow != SWITCH_MEDIA_FLOW_SENDONLY &&
!conference_utils_member_test_flag(imember, MFLAG_SECOND_SCREEN) && !conference_utils_member_test_flag(imember, MFLAG_SECOND_SCREEN) &&
!conference_utils_member_test_flag(imember, MFLAG_HOLD) &&
(!conference_utils_test_flag(conference, CFLAG_VIDEO_MUTE_EXIT_CANVAS) || (!conference_utils_test_flag(conference, CFLAG_VIDEO_MUTE_EXIT_CANVAS) ||
conference_utils_member_test_flag(imember, MFLAG_CAN_BE_SEEN))) { conference_utils_member_test_flag(imember, MFLAG_CAN_BE_SEEN))) {
members_with_video++; members_with_video++;
@ -1225,6 +1232,7 @@ void conference_xlist(conference_obj_t *conference, switch_xml_t x_conference, i
switch_xml_t x_tag; switch_xml_t x_tag;
int toff = 0; int toff = 0;
char tmp[50] = ""; char tmp[50] = "";
switch_bool_t hold = conference_utils_member_test_flag(member, MFLAG_HOLD);
if (conference_utils_member_test_flag(member, MFLAG_NOCHANNEL)) { if (conference_utils_member_test_flag(member, MFLAG_NOCHANNEL)) {
if (member->rec_path) { if (member->rec_path) {
@ -1286,19 +1294,22 @@ void conference_xlist(conference_obj_t *conference, switch_xml_t x_conference, i
switch_assert(x_flags); switch_assert(x_flags);
x_tag = switch_xml_add_child_d(x_flags, "can_hear", count++); x_tag = switch_xml_add_child_d(x_flags, "can_hear", count++);
switch_xml_set_txt_d(x_tag, conference_utils_member_test_flag(member, MFLAG_CAN_HEAR) ? "true" : "false"); switch_xml_set_txt_d(x_tag, (!hold && conference_utils_member_test_flag(member, MFLAG_CAN_HEAR)) ? "true" : "false");
x_tag = switch_xml_add_child_d(x_flags, "can_see", count++); x_tag = switch_xml_add_child_d(x_flags, "can_see", count++);
switch_xml_set_txt_d(x_tag, conference_utils_member_test_flag(member, MFLAG_CAN_SEE) ? "true" : "false"); switch_xml_set_txt_d(x_tag, (!hold && conference_utils_member_test_flag(member, MFLAG_CAN_SEE)) ? "true" : "false");
x_tag = switch_xml_add_child_d(x_flags, "can_speak", count++); x_tag = switch_xml_add_child_d(x_flags, "can_speak", count++);
switch_xml_set_txt_d(x_tag, conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK) ? "true" : "false"); switch_xml_set_txt_d(x_tag, (!hold && conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) ? "true" : "false");
x_tag = switch_xml_add_child_d(x_flags, "mute_detect", count++); x_tag = switch_xml_add_child_d(x_flags, "mute_detect", count++);
switch_xml_set_txt_d(x_tag, conference_utils_member_test_flag(member, MFLAG_MUTE_DETECT) ? "true" : "false"); switch_xml_set_txt_d(x_tag, conference_utils_member_test_flag(member, MFLAG_MUTE_DETECT) ? "true" : "false");
x_tag = switch_xml_add_child_d(x_flags, "talking", count++); x_tag = switch_xml_add_child_d(x_flags, "talking", count++);
switch_xml_set_txt_d(x_tag, conference_utils_member_test_flag(member, MFLAG_TALKING) ? "true" : "false"); switch_xml_set_txt_d(x_tag, (!hold && conference_utils_member_test_flag(member, MFLAG_TALKING)) ? "true" : "false");
x_tag = switch_xml_add_child_d(x_flags, "hold", count++);
switch_xml_set_txt_d(x_tag, hold ? "true" : "false");
x_tag = switch_xml_add_child_d(x_flags, "has_video", count++); x_tag = switch_xml_add_child_d(x_flags, "has_video", count++);
switch_xml_set_txt_d(x_tag, switch_channel_test_flag(switch_core_session_get_channel(member->session), CF_VIDEO) ? "true" : "false"); switch_xml_set_txt_d(x_tag, switch_channel_test_flag(switch_core_session_get_channel(member->session), CF_VIDEO) ? "true" : "false");
@ -1374,6 +1385,8 @@ void conference_jlist(conference_obj_t *conference, cJSON *json_conferences)
switch_channel_t *channel; switch_channel_t *channel;
switch_caller_profile_t *profile; switch_caller_profile_t *profile;
char *uuid; char *uuid;
switch_bool_t hold = conference_utils_member_test_flag(member, MFLAG_HOLD);
cJSON_AddItemToObject(json_conference_members, "member", json_conference_member = cJSON_CreateObject()); cJSON_AddItemToObject(json_conference_members, "member", json_conference_member = cJSON_CreateObject());
if (conference_utils_member_test_flag(member, MFLAG_NOCHANNEL)) { if (conference_utils_member_test_flag(member, MFLAG_NOCHANNEL)) {
@ -1405,9 +1418,10 @@ void conference_jlist(conference_obj_t *conference, cJSON *json_conferences)
cJSON_AddNumberToObject(json_conference_member, "volume_out", member->volume_out_level); cJSON_AddNumberToObject(json_conference_member, "volume_out", member->volume_out_level);
cJSON_AddNumberToObject(json_conference_member, "output-volume", member->volume_out_level); cJSON_AddNumberToObject(json_conference_member, "output-volume", member->volume_out_level);
cJSON_AddNumberToObject(json_conference_member, "input-volume", member->volume_in_level); cJSON_AddNumberToObject(json_conference_member, "input-volume", member->volume_in_level);
ADDBOOL(json_conference_member_flags, "can_hear", conference_utils_member_test_flag(member, MFLAG_CAN_HEAR)); ADDBOOL(json_conference_member_flags, "can_hear", !hold && conference_utils_member_test_flag(member, MFLAG_CAN_HEAR));
ADDBOOL(json_conference_member_flags, "can_see", conference_utils_member_test_flag(member, MFLAG_CAN_SEE)); ADDBOOL(json_conference_member_flags, "can_see", !hold && conference_utils_member_test_flag(member, MFLAG_CAN_SEE));
ADDBOOL(json_conference_member_flags, "can_speak", conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)); ADDBOOL(json_conference_member_flags, "can_speak", !hold && conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK));
ADDBOOL(json_conference_member_flags, "hold", hold);
ADDBOOL(json_conference_member_flags, "mute_detect", conference_utils_member_test_flag(member, MFLAG_MUTE_DETECT)); ADDBOOL(json_conference_member_flags, "mute_detect", conference_utils_member_test_flag(member, MFLAG_MUTE_DETECT));
ADDBOOL(json_conference_member_flags, "talking", conference_utils_member_test_flag(member, MFLAG_TALKING)); ADDBOOL(json_conference_member_flags, "talking", conference_utils_member_test_flag(member, MFLAG_TALKING));
ADDBOOL(json_conference_member_flags, "has_video", switch_channel_test_flag(switch_core_session_get_channel(member->session), CF_VIDEO)); ADDBOOL(json_conference_member_flags, "has_video", switch_channel_test_flag(switch_core_session_get_channel(member->session), CF_VIDEO));

View File

@ -220,6 +220,7 @@ typedef enum {
MFLAG_NO_VIDEO_BLANKS, MFLAG_NO_VIDEO_BLANKS,
MFLAG_VIDEO_JOIN, MFLAG_VIDEO_JOIN,
MFLAG_DED_VID_LAYER, MFLAG_DED_VID_LAYER,
MFLAG_HOLD,
/////////////////////////// ///////////////////////////
MFLAG_MAX MFLAG_MAX
} member_flag_t; } member_flag_t;
@ -322,7 +323,7 @@ typedef enum {
} node_flag_t; } node_flag_t;
typedef enum { typedef enum {
EFLAG_ADD_MEMBER = (1 << 0), EFLAG_HOLD_MEMBER = (1 << 0),
EFLAG_DEL_MEMBER = (1 << 1), EFLAG_DEL_MEMBER = (1 << 1),
EFLAG_ENERGY_LEVEL = (1 << 2), EFLAG_ENERGY_LEVEL = (1 << 2),
EFLAG_VOLUME_LEVEL = (1 << 3), EFLAG_VOLUME_LEVEL = (1 << 3),
@ -1210,6 +1211,8 @@ switch_status_t conference_api_sub_file_seek(conference_obj_t *conference, switc
switch_status_t conference_api_sub_cam(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv); switch_status_t conference_api_sub_cam(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv);
switch_status_t conference_api_sub_stop(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv); switch_status_t conference_api_sub_stop(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv);
switch_status_t conference_api_sub_hup(conference_member_t *member, switch_stream_handle_t *stream, void *data); switch_status_t conference_api_sub_hup(conference_member_t *member, switch_stream_handle_t *stream, void *data);
switch_status_t conference_api_sub_hold(conference_member_t *member, switch_stream_handle_t *stream, void *data);
switch_status_t conference_api_sub_unhold(conference_member_t *member, switch_stream_handle_t *stream, void *data);
switch_status_t conference_api_sub_pauserec(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv); switch_status_t conference_api_sub_pauserec(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv);
switch_status_t conference_api_sub_volume_out(conference_member_t *member, switch_stream_handle_t *stream, void *data); switch_status_t conference_api_sub_volume_out(conference_member_t *member, switch_stream_handle_t *stream, void *data);
switch_status_t conference_api_sub_lock(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv); switch_status_t conference_api_sub_lock(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv);