switch_mutex_lock(conference->member_mutex);
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++;
}
}
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;
}
{"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]>"},
{"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>]"},
{"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>]"},
if (member == NULL)
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_TALKING);
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)
{
if (member == NULL)
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)) {
return conference_api_sub_mute(member, stream, data);
}
if (member == NULL)
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);
if (member->session && !conference_utils_member_test_flag(member, MFLAG_MUTE_DETECT)) {
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) {
stream->write_function(stream, "+OK vmute image snapped %u\n", member->id);
}
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_video_reset_video_bitrate_counters(member);
if (member == NULL)
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)) {
return conference_api_sub_vmute(member, stream, data);
}
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))) {
layer->clear = 1;
conference_video_release_layer(&layer);
if (member == NULL)
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);
conference_utils_member_clear_flag_locked(member, MFLAG_CAN_SEE);
conference_video_reset_video_bitrate_counters(member);
if (member == NULL)
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)) {
return conference_api_sub_vblind(member, stream, data);
}
if (member == NULL)
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_video_reset_video_bitrate_counters(member);
if (member == NULL)
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);
if (!(data) || !strstr((char *) data, "quiet")) {
if (member == NULL)
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);
if (!(data) || !strstr((char *) data, "quiet")) {
if (member == NULL)
return;
+ if (conference_utils_member_test_flag(member, MFLAG_HOLD)) return;
+
if (conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) {
conference_api_sub_mute(member, NULL, NULL);
} else {
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)) {
conference_api_sub_mute(member, NULL, NULL);
}
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)) {
conference_api_sub_unmute(member, NULL, NULL);
if (!conference_utils_member_test_flag(member, MFLAG_CAN_HEAR)) {
if (member == NULL)
return;
+ if (conference_utils_member_test_flag(member, MFLAG_HOLD)) return;
+
if (conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) {
conference_api_sub_mute(member, NULL, NULL);
if (conference_utils_member_test_flag(member, MFLAG_CAN_HEAR)) {
/* if the member can speak, compute the audio energy level and */
/* 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;
int16_t *data;
int gate_check = 0;
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->score > member->max_energy_level && ++member->max_energy_hits > member->max_energy_hit_trigger) {
member->mute_counter = member->burst_mute_count;
member->talking_count = 0;
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) {
conference_member_add_event_data(member, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "start-talking");
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) {
hangover_hits = hangunder_hits = 0;
/* 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))
- && 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))) {
switch_audio_resampler_t *read_resampler = member->read_resampler;
void *data;
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";
} else if (switch_channel_test_flag(member->channel, CF_HOLD)) {
str = "HOLD";
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, "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-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");
*next++ = '\0';
}
- if (!strcmp(event, "add-member")) {
- *f &= ~EFLAG_ADD_MEMBER;
- } else if (!strcmp(event, "del-member")) {
+ if (!strcmp(event, "del-member")) {
*f &= ~EFLAG_DEL_MEMBER;
} else if (!strcmp(event, "energy-level")) {
*f &= ~EFLAG_ENERGY_LEVEL;
*f &= ~EFLAG_MUTE_DETECT;
} else if (!strcmp(event, "mute-member")) {
*f &= ~EFLAG_MUTE_MEMBER;
+ } else if (!strcmp(event, "hold-member")) {
+ *f &= ~EFLAG_HOLD_MEMBER;
} else if (!strcmp(event, "kick-member")) {
*f &= ~EFLAG_KICK_MEMBER;
} else if (!strcmp(event, "dtmf-member")) {
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) {
conference_utils_member_clear_flag(member, MFLAG_DED_VID_LAYER);
return SWITCH_STATUS_FALSE;
}
+
+
switch_mutex_lock(canvas->mutex);
layer = &canvas->layers[idx];
return SWITCH_STATUS_FALSE;
}
+ if (conference_utils_member_test_flag(member, MFLAG_HOLD)) {
+ return SWITCH_STATUS_FALSE;
+ }
+
switch_mutex_lock(canvas->mutex);
for (i = 0; i < canvas->total_layers; i++) {
size = switch_queue_size(member->video_queue);
} 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 &&
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_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);
} 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) {
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);
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 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) &&
imember->watching_canvas_id == canvas->canvas_id) {
}
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))
&& imember->canvas_id == canvas->canvas_id && imember->video_media_flow != SWITCH_MEDIA_FLOW_SENDONLY && imember->video_media_flow != SWITCH_MEDIA_FLOW_INACTIVE) {
video_count++;
continue;
}
- if (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) {
+ if ((conference_utils_member_test_flag(imember, MFLAG_HOLD) ||
+ (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);
switch_img_free(&imember->video_mute_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;
} else {
if (total > 0 &&
(!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_INACTIVE) {
}
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;
} else if (!conference_utils_test_flag(omember->conference, CFLAG_VIDEO_MUTE_EXIT_CANVAS)) {
if (!layer->mute_patched) {
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_HOLD) &&
switch_queue_size(member->video_queue) < member->conference->video_fps.fps &&
!member->conference->canvases[canvas_id]->playing_video_file) {
char *uuid;
char *name;
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)) {
continue;
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);
- 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");
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");
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");
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)) {
stream->write_function(stream, "%s%s", count ? "|" : "", "video");
count++;
switch_channel_test_flag(channel, CF_VIDEO_READY) &&
imember->video_media_flow != SWITCH_MEDIA_FLOW_SENDONLY &&
!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_member_test_flag(imember, MFLAG_CAN_BE_SEEN))) {
members_with_video++;
switch_xml_t x_tag;
int toff = 0;
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 (member->rec_path) {
x_member = switch_xml_add_child_d(x_members, "member", moff++);
switch_assert(x_flags);
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++);
- 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++);
- 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++);
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++);
- 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++);
switch_xml_set_txt_d(x_tag, switch_channel_test_flag(switch_core_session_get_channel(member->session), CF_VIDEO) ? "true" : "false");
switch_channel_t *channel;
switch_caller_profile_t *profile;
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());
if (conference_utils_member_test_flag(member, MFLAG_NOCHANNEL)) {
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, "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_see", 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_hear", !hold && conference_utils_member_test_flag(member, MFLAG_CAN_HEAR));
+ ADDBOOL(json_conference_member_flags, "can_see", !hold && conference_utils_member_test_flag(member, MFLAG_CAN_SEE));
+ 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, "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));
MFLAG_NO_VIDEO_BLANKS,
MFLAG_VIDEO_JOIN,
MFLAG_DED_VID_LAYER,
+ MFLAG_HOLD,
///////////////////////////
MFLAG_MAX
} member_flag_t;
} node_flag_t;
typedef enum {
- EFLAG_ADD_MEMBER = (1 << 0),
+ EFLAG_HOLD_MEMBER = (1 << 0),
EFLAG_DEL_MEMBER = (1 << 1),
EFLAG_ENERGY_LEVEL = (1 << 2),
EFLAG_VOLUME_LEVEL = (1 << 3),
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_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_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);