diff --git a/src/mod/applications/mod_conference/conference_api.c b/src/mod/applications/mod_conference/conference_api.c index c25dc038d7..4ec801a093 100644 --- a/src/mod/applications/mod_conference/conference_api.c +++ b/src/mod/applications/mod_conference/conference_api.c @@ -62,6 +62,7 @@ api_command_t conference_api_sub_commands[] = { {"stop", (void_fn_t) & conference_api_sub_stop, CONF_API_SUB_ARGS_SPLIT, "stop", "<[current|all|async|last]> []"}, {"dtmf", (void_fn_t) & conference_api_sub_dtmf, CONF_API_SUB_MEMBER_TARGET, "dtmf", "<[member_id|all|last|non_moderator]> "}, {"kick", (void_fn_t) & conference_api_sub_kick, CONF_API_SUB_MEMBER_TARGET, "kick", "<[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]>"}, {"hup", (void_fn_t) & conference_api_sub_hup, CONF_API_SUB_MEMBER_TARGET, "hup", "<[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> []"}, {"tmute", (void_fn_t) & conference_api_sub_tmute, CONF_API_SUB_MEMBER_TARGET, "tmute", "<[member_id|all]|last|non_moderator> []"}, @@ -655,6 +656,36 @@ switch_status_t conference_api_sub_kick(conference_member_t *member, switch_stre } +switch_status_t conference_api_sub_vid_flip(conference_member_t *member, switch_stream_handle_t *stream, void *data) +{ + switch_event_t *event; + + if (member == NULL) { + return SWITCH_STATUS_GENERR; + } + + if (conference_utils_member_test_flag(member, MFLAG_FLIP_VIDEO)) { + conference_utils_member_clear_flag_locked(member, MFLAG_FLIP_VIDEO); + } else { + conference_utils_member_set_flag_locked(member, MFLAG_FLIP_VIDEO); + } + + if (stream != NULL) { + stream->write_function(stream, "OK flipped %u\n", member->id); + } + + if (member->conference && test_eflag(member->conference, EFLAG_KICK_MEMBER)) { + if (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", "vid-flip-member"); + switch_event_fire(&event); + } + } + + return SWITCH_STATUS_SUCCESS; +} + + switch_status_t conference_api_sub_dtmf(conference_member_t *member, switch_stream_handle_t *stream, void *data) { switch_event_t *event; diff --git a/src/mod/applications/mod_conference/conference_utils.c b/src/mod/applications/mod_conference/conference_utils.c index 269e558879..be02472460 100644 --- a/src/mod/applications/mod_conference/conference_utils.c +++ b/src/mod/applications/mod_conference/conference_utils.c @@ -74,6 +74,13 @@ const char *conference_utils_combine_flag_var(switch_core_session_t *session, co ret = switch_core_session_sprintf(session, "%s|%s", ret, val); } } + } else if (!strncasecmp(var, var_name, strlen(var_name)) && switch_true(val)) { + char *p = var + strlen(var_name); + + if (*p == '_' && *(p+1)) { + p++; + ret = switch_core_session_sprintf(session, "%s|%s", ret, p); + } } } @@ -129,6 +136,8 @@ void conference_utils_set_mflags(const char *flags, member_flag_t *f) f[MFLAG_GHOST] = 1; } else if (!strcasecmp(argv[i], "join-only")) { f[MFLAG_JOIN_ONLY] = 1; + } else if (!strcasecmp(argv[i], "flip-video")) { + f[MFLAG_FLIP_VIDEO] = 1; } else if (!strcasecmp(argv[i], "positional")) { f[MFLAG_POSITIONAL] = 1; } else if (!strcasecmp(argv[i], "no-positional")) { diff --git a/src/mod/applications/mod_conference/conference_video.c b/src/mod/applications/mod_conference/conference_video.c index 5c638c5b89..bf6c22a196 100644 --- a/src/mod/applications/mod_conference/conference_video.c +++ b/src/mod/applications/mod_conference/conference_video.c @@ -3729,6 +3729,11 @@ switch_status_t conference_video_thread_callback(switch_core_session_t *session, switch_queue_size(member->video_queue) < member->conference->video_fps.fps * 2 && !member->conference->playing_video_file) { switch_img_copy(frame->img, &img_copy); + + if (conference_utils_member_test_flag(member, MFLAG_FLIP_VIDEO)) { + switch_img_flip(img_copy); + } + if (switch_queue_trypush(member->video_queue, img_copy) != SWITCH_STATUS_SUCCESS) { switch_img_free(&img_copy); } diff --git a/src/mod/applications/mod_conference/mod_conference.h b/src/mod/applications/mod_conference/mod_conference.h index 102f1e334d..863bf39ff8 100644 --- a/src/mod/applications/mod_conference/mod_conference.h +++ b/src/mod/applications/mod_conference/mod_conference.h @@ -208,6 +208,7 @@ typedef enum { MFLAG_CAN_BE_SEEN, MFLAG_SECOND_SCREEN, MFLAG_SILENT, + MFLAG_FLIP_VIDEO, /////////////////////////// MFLAG_MAX } member_flag_t; @@ -1105,6 +1106,7 @@ switch_status_t conference_api_sub_watching_canvas(conference_member_t *member, switch_status_t conference_api_sub_canvas(conference_member_t *member, switch_stream_handle_t *stream, void *data); switch_status_t conference_api_sub_layer(conference_member_t *member, switch_stream_handle_t *stream, void *data); switch_status_t conference_api_sub_kick(conference_member_t *member, switch_stream_handle_t *stream, void *data); +switch_status_t conference_api_sub_vid_flip(conference_member_t *member, switch_stream_handle_t *stream, void *data); switch_status_t conference_api_sub_transfer(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv); switch_status_t conference_api_sub_record(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv); switch_status_t conference_api_sub_norecord(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv);