]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-10121: [mod_conference] Add role-id and layout transitions to conference #resolve
authorAnthony Minessale <anthm@freeswitch.org>
Thu, 9 Mar 2017 20:18:16 +0000 (14:18 -0600)
committerAnthony Minessale <anthm@freeswitch.org>
Thu, 9 Mar 2017 20:18:16 +0000 (14:18 -0600)
src/mod/applications/mod_conference/conference_api.c
src/mod/applications/mod_conference/conference_member.c
src/mod/applications/mod_conference/conference_video.c
src/mod/applications/mod_conference/mod_conference.h

index 46176a03acb6781a3729e5c7c7e05397bc6e2916..ec129e5bb93df9c4aa5b60a178dd14ae77209e89 100644 (file)
@@ -103,6 +103,7 @@ api_command_t conference_api_sub_commands[] = {
        {"vid-mute-img", (void_fn_t) & conference_api_sub_vid_mute_img, CONF_API_SUB_MEMBER_TARGET, "vid-mute-img", "<member_id|last> [<path>|clear]"},
        {"vid-logo-img", (void_fn_t) & conference_api_sub_vid_logo_img, CONF_API_SUB_MEMBER_TARGET, "vid-logo-img", "<member_id|last> [<path>|clear]"},
        {"vid-res-id", (void_fn_t) & conference_api_sub_vid_res_id, CONF_API_SUB_MEMBER_TARGET, "vid-res-id", "<member_id|last> <val>|clear"},
+       {"vid-role-id", (void_fn_t) & conference_api_sub_vid_role_id, CONF_API_SUB_MEMBER_TARGET, "vid-role-id", "<member_id|last> <val>|clear"},
        {"get-uuid", (void_fn_t) & conference_api_sub_get_uuid, CONF_API_SUB_MEMBER_TARGET, "get-uuid", "<member_id|last>"},
        {"clear-vid-floor", (void_fn_t) & conference_api_sub_clear_vid_floor, CONF_API_SUB_ARGS_AS_ONE, "clear-vid-floor", ""},
        {"vid-layout", (void_fn_t) & conference_api_sub_vid_layout, CONF_API_SUB_ARGS_SPLIT, "vid-layout", "<layout name>|group <group name> [<canvas id>]"},
@@ -1875,6 +1876,24 @@ static void clear_res_id(conference_obj_t *conference, conference_member_t *memb
        switch_mutex_unlock(conference->member_mutex);
 }
 
+static void clear_role_id(conference_obj_t *conference, conference_member_t *member, const char *id)
+{
+       conference_member_t *imember;
+
+       switch_mutex_lock(conference->member_mutex);
+       for (imember = conference->members; imember; imember = imember->next) {
+               if (imember == member) {
+                       continue;
+               }
+
+               if (imember->video_role_id && !strcasecmp(imember->video_role_id, id)) {
+                       imember->video_role_id = NULL;
+                       conference_video_detach_video_layer(imember);
+               }
+       }
+       switch_mutex_unlock(conference->member_mutex);
+}
+
 switch_status_t conference_api_sub_vid_res_id(conference_member_t *member, switch_stream_handle_t *stream, void *data)
 {
        char *text = (char *) data;
@@ -1907,6 +1926,41 @@ switch_status_t conference_api_sub_vid_res_id(conference_member_t *member, switc
 
 
 
+       return SWITCH_STATUS_SUCCESS;
+
+}
+
+
+switch_status_t conference_api_sub_vid_role_id(conference_member_t *member, switch_stream_handle_t *stream, void *data)
+{
+       char *text = (char *) data;
+
+       if (member == NULL)
+               return SWITCH_STATUS_GENERR;
+
+       if (!switch_channel_test_flag(member->channel, CF_VIDEO)) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       if (!member->conference->canvases[0]) {
+               stream->write_function(stream, "-ERR conference is not in mixing mode\n");
+               return SWITCH_STATUS_SUCCESS;
+       }
+
+       if (zstr(text) || !strcasecmp(text, "clear") || (member->video_role_id && !strcasecmp(text, member->video_role_id))) {
+               member->video_role_id = NULL;
+               stream->write_function(stream, "+OK role_id cleared\n");
+       } else {
+               clear_role_id(member->conference, member, text);
+               if (!member->video_role_id || strcmp(member->video_role_id, text)) {
+                       member->video_role_id = switch_core_strdup(member->pool, text);
+               }
+               stream->write_function(stream, "+OK role_id %s\n", text);
+               conference_video_find_floor(member, SWITCH_FALSE);
+       }
+
+
+
        return SWITCH_STATUS_SUCCESS;
 
 }
index 55958661b3b66fab6793087af26665f995074dbb..62fa00827768b4bb11ecdc61d461c9d4c1c4280e 100644 (file)
@@ -197,6 +197,9 @@ void conference_member_update_status_field(conference_member_t *member)
                        cJSON_AddItemToObject(video, "reservationID", member->video_reservation_id ?
                                                                  cJSON_CreateString(member->video_reservation_id) : cJSON_CreateNull());
 
+                       cJSON_AddItemToObject(video, "roleID", member->video_role_id ?
+                                                                 cJSON_CreateString(member->video_role_id) : cJSON_CreateNull());
+
                        cJSON_AddItemToObject(video, "videoLayerID", cJSON_CreateNumber(member->video_layer_id));
 
                        cJSON_AddItemToObject(json, "video", video);
@@ -759,6 +762,10 @@ switch_status_t conference_member_add(conference_obj_t *conference, conference_m
                                member->video_reservation_id = switch_core_strdup(member->pool, var);
                        }
 
+                       if ((var = switch_channel_get_variable_dup(member->channel, "video_role_id", SWITCH_FALSE, -1))) {
+                               member->video_role_id = switch_core_strdup(member->pool, var);
+                       }
+
                        if ((var = switch_channel_get_variable(channel, "video_use_dedicated_encoder")) && switch_true(var)) {
                                conference_utils_member_set_flag_locked(member, MFLAG_NO_MINIMIZE_ENCODING);
                        }
index 6c8e744f228106ba49f8b880130b797028b1d4ac..a449cea499951d6a275c23f5045effd7f3c1221d 100644 (file)
@@ -110,7 +110,7 @@ void conference_video_parse_layouts(conference_obj_t *conference, int WIDTH, int
                if ((x_layouts = switch_xml_child(x_layout_settings, "layouts"))) {
                        for (x_layout = switch_xml_child(x_layouts, "layout"); x_layout; x_layout = x_layout->next) {
                                video_layout_t *vlayout;
-                               const char *val = NULL, *name = NULL, *bgimg = NULL, *fgimg = NULL;
+                               const char *val = NULL, *name = NULL, *bgimg = NULL, *fgimg = NULL, *transition_in = NULL, *transition_out = NULL;
                                switch_bool_t auto_3d = SWITCH_FALSE;
                                int border = 0;
 
@@ -128,6 +128,9 @@ void conference_video_parse_layouts(conference_obj_t *conference, int WIDTH, int
                                bgimg = switch_xml_attr(x_layout, "bgimg");
                                fgimg = switch_xml_attr(x_layout, "fgimg");
 
+                               transition_in = switch_xml_attr(x_layout, "transition-in");
+                               transition_out = switch_xml_attr(x_layout, "transition-out");
+                               
                                if ((val = switch_xml_attr(x_layout, "border"))) {
                                        border = atoi(val);
                                        if (border < 0) border = 0;
@@ -145,8 +148,16 @@ void conference_video_parse_layouts(conference_obj_t *conference, int WIDTH, int
                                        vlayout->fgimg = switch_core_strdup(conference->pool, fgimg);
                                }
 
+                               if (transition_in) {
+                                       vlayout->transition_in = switch_core_sprintf(conference->pool, "{full-screen=true}%s", transition_in);
+                               }
+                               
+                               if (transition_out) {
+                                       vlayout->transition_out = switch_core_sprintf(conference->pool, "{full-screen=true}%s", transition_out);
+                               }
+
                                for (x_image = switch_xml_child(x_layout, "image"); x_image; x_image = x_image->next) {
-                                       const char *res_id = NULL, *audio_position = NULL;
+                                       const char *res_id = NULL, *audio_position = NULL, *role_id = NULL;
                                        int x = -1, y = -1, scale = -1, hscale = -1, floor = 0, flooronly = 0, fileonly = 0, overlap = 0, zoom = 0;
 
                                        if ((val = switch_xml_attr(x_image, "x"))) {
@@ -189,6 +200,14 @@ void conference_video_parse_layouts(conference_obj_t *conference, int WIDTH, int
                                                res_id = val;
                                        }
 
+                                       if ((val = switch_xml_attr(x_image, "reservation-id"))) {
+                                               res_id = val;
+                                       }
+
+                                       if ((val = switch_xml_attr(x_image, "role-id"))) {
+                                               role_id = val;
+                                       }
+                                       
                                        if ((val = switch_xml_attr(x_image, "audio-position"))) {
                                                audio_position = val;
                                        }
@@ -231,6 +250,10 @@ void conference_video_parse_layouts(conference_obj_t *conference, int WIDTH, int
                                                vlayout->images[vlayout->layers].res_id = switch_core_strdup(conference->pool, res_id);
                                        }
 
+                                       if (role_id) {
+                                               vlayout->images[vlayout->layers].role_id = switch_core_strdup(conference->pool, role_id);
+                                       }
+
                                        if (auto_3d || audio_position) {
                                                if (auto_3d || !strcasecmp(audio_position, "auto")) {
                                                        int x_pos = (int)(WIDTH * x / VIDEO_LAYOUT_SCALE);
@@ -1368,6 +1391,11 @@ void conference_video_init_canvas_layers(conference_obj_t *conference, mcu_canva
        switch_mutex_lock(canvas->mutex);
        canvas->layout_floor_id = -1;
 
+       if (canvas->vlayout && canvas->vlayout->transition_out) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Play transition out [%s]\n", canvas->vlayout->transition_out);
+               conference_file_play(conference, canvas->vlayout->transition_out, 0, NULL, 0);
+       }
+
        if (!vlayout) {
                vlayout = canvas->new_vlayout;
                canvas->new_vlayout = NULL;
@@ -1417,10 +1445,11 @@ void conference_video_init_canvas_layers(conference_obj_t *conference, mcu_canva
                if (layer->geometry.floor) {
                        canvas->layout_floor_id = i;
                }
-
+               
                /* if we ever decided to reload layers config on demand the pointer assignment below  will lead to segs but we
                   only load them once forever per conference so these pointers are valid for the life of the conference */
                layer->geometry.res_id = vlayout->images[i].res_id;
+               layer->geometry.role_id = vlayout->images[i].role_id;
                layer->geometry.audio_position = vlayout->images[i].audio_position;
        }
 
@@ -1469,6 +1498,10 @@ void conference_video_init_canvas_layers(conference_obj_t *conference, mcu_canva
 
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Canvas position %d applied layout %s\n", canvas->canvas_id + 1, vlayout->name);
 
+       if (vlayout->transition_in) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Play transition in [%s]\n", vlayout->transition_in);
+               conference_file_play(conference, vlayout->transition_in, 0, NULL, 0);
+       }
 }
 
 switch_status_t conference_video_set_canvas_bgimg(mcu_canvas_t *canvas, const char *img_path)
@@ -3014,7 +3047,7 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
                        layer = NULL;
 
                        switch_mutex_lock(canvas->mutex);
-
+                       
                        if (canvas->layout_floor_id > -1 && imember->id == conference->video_floor_holder &&
                                imember->video_layer_id != canvas->layout_floor_id) {
                                conference_video_attach_video_layer(imember, canvas, canvas->layout_floor_id);
@@ -3023,8 +3056,27 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
                        //printf("MEMBER %d layer_id %d canvas: %d/%d\n", imember->id, imember->video_layer_id,
                        //         canvas->layers_used, canvas->total_layers);
 
-                       if (imember->video_layer_id > -1) {
+                       if (imember->video_role_id) {
+                               if (imember->video_layer_id > -1) {
+                                       layer = &canvas->layers[imember->video_layer_id];
+                               }
+
+                               if (!layer || (!layer->geometry.role_id || strcmp(layer->geometry.role_id, imember->video_role_id))) {
+                                       for (i = 0; i < canvas->total_layers; i++) {
+                                               mcu_layer_t *xlayer = &canvas->layers[i];
+                                               
+                                               if (imember->video_role_id && xlayer->geometry.role_id && !strcmp(xlayer->geometry.role_id, imember->video_role_id)) {
+                                                       conference_video_attach_video_layer(imember, canvas, i);
+                                                       layer = xlayer;
+                                               }
+                                       }
+                               }
+                       }
+
+
+                       if (!layer && imember->video_layer_id > -1) {
                                layer = &canvas->layers[imember->video_layer_id];
+                               
                                if (layer->member_id != (int)imember->id) {
                                        imember->video_layer_id = -1;
                                        layer = NULL;
@@ -3530,7 +3582,7 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
                                                canvas->send_keyframe = 1;
                                                canvas->play_file = 0;
                                        }
-
+                                       
                                        switch_img_free(&file_img);
                                        file_img = write_img = write_frame.img;
 
index ebb70f09784eceb73a4fa8ac6e7b73070fd43df9..556380fa85427adfc4471e258329fe1f1cba9641 100644 (file)
@@ -422,6 +422,7 @@ typedef struct mcu_layer_geometry_s {
        int zoom;
        int border;
        char *res_id;
+       char *role_id;
        char *audio_position;
 } mcu_layer_geometry_t;
 
@@ -500,6 +501,8 @@ typedef struct video_layout_s {
        char *audio_position;
        char *bgimg;
        char *fgimg;
+       char *transition_in;
+       char *transition_out;
        mcu_layer_geometry_t images[MCU_MAX_LAYERS];
        int layers;
 } video_layout_t;
@@ -834,6 +837,7 @@ struct conference_member {
        switch_img_fit_t logo_fit;
        char *video_mute_png;
        char *video_reservation_id;
+       char *video_role_id;
        switch_vid_params_t vid_params;
        uint32_t auto_kps_debounce_ticks;
        uint32_t layer_loops;
@@ -1181,6 +1185,7 @@ switch_status_t conference_api_sub_vid_banner(conference_member_t *member, switc
 switch_status_t conference_api_sub_enter_sound(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv);
 switch_status_t conference_api_sub_set(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv);
 switch_status_t conference_api_sub_vid_res_id(conference_member_t *member, switch_stream_handle_t *stream, void *data);
+switch_status_t conference_api_sub_vid_role_id(conference_member_t *member, switch_stream_handle_t *stream, void *data);
 switch_status_t conference_api_sub_get_uuid(conference_member_t *member, switch_stream_handle_t *stream, void *data);
 switch_status_t conference_api_sub_get(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv);
 switch_status_t conference_api_sub_vid_mute_img(conference_member_t *member, switch_stream_handle_t *stream, void *data);