]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-7513: improve reservation id and layout switching with overlap
authorAnthony Minessale <anthm@freeswitch.org>
Thu, 19 Feb 2015 02:27:08 +0000 (20:27 -0600)
committerMichael Jerris <mike@jerris.com>
Thu, 28 May 2015 17:47:03 +0000 (12:47 -0500)
src/mod/applications/mod_conference/mod_conference.c

index af4e043af0083d6e95ebd0786d3e76ce06644205..96ea703e019f02acddd806f3ca7aed27d2b4166a 100644 (file)
@@ -366,6 +366,7 @@ typedef struct mcu_layer_geometry_s {
        int y;
        int scale;
        int floor;
+       int overlap;
        char *res_id;
        char *audio_position;
 } mcu_layer_geometry_t;
@@ -627,6 +628,7 @@ struct conference_member {
        char *video_banner_text;
        char *video_logo;
        char *video_mute_png;
+       char *video_reservation_id;
 };
 
 typedef enum {
@@ -763,6 +765,7 @@ static void conference_parse_layouts(conference_obj_t *conference)
 {
        switch_event_t *params;
        switch_xml_t cxml = NULL, cfg = NULL, x_layouts, x_layout, x_layout_settings, x_group, x_groups, x_image;
+       char cmd_str[256] = "";
 
        if (!conference->layout_hash) {
                switch_core_hash_init(&conference->layout_hash);
@@ -801,7 +804,7 @@ static void conference_parse_layouts(conference_obj_t *conference)
 
                                for (x_image = switch_xml_child(x_layout, "image"); x_image; x_image = x_image->next) {
                                        const char *res_id = NULL, *audio_position = NULL;
-                                       int x = -1, y = -1, scale = -1, floor = 0;
+                                       int x = -1, y = -1, scale = -1, floor = 0, overlap = 0;
 
                                        if ((val = switch_xml_attr(x_image, "x"))) {
                                                x = atoi(val);
@@ -818,6 +821,10 @@ static void conference_parse_layouts(conference_obj_t *conference)
                                        if ((val = switch_xml_attr(x_image, "floor"))) {
                                                floor = switch_true(val);
                                        }
+
+                                       if ((val = switch_xml_attr(x_image, "overlap"))) {
+                                               overlap = switch_true(val);
+                                       }
                                        
                                        if ((val = switch_xml_attr(x_image, "reservation_id"))) {
                                                res_id = val;
@@ -838,6 +845,7 @@ static void conference_parse_layouts(conference_obj_t *conference)
                                        vlayout->images[vlayout->layers].y = y;
                                        vlayout->images[vlayout->layers].scale = scale;
                                        vlayout->images[vlayout->layers].floor = floor;
+                                       vlayout->images[vlayout->layers].overlap = overlap;
                                        
                                        if (res_id) {
                                                vlayout->images[vlayout->layers].res_id = switch_core_strdup(conference->pool, res_id);
@@ -851,6 +859,8 @@ static void conference_parse_layouts(conference_obj_t *conference)
                                }
 
                                switch_core_hash_insert(conference->layout_hash, name, vlayout);
+                               switch_snprintf(cmd_str, sizeof(cmd_str), "add conference ::conference::list_conferences vid-layout %s", name);
+                               switch_console_set_complete(cmd_str);
                        }
                        
                }
@@ -1248,7 +1258,6 @@ static switch_status_t attach_video_layer(conference_member_t *member, int idx)
 {
        mcu_layer_t *layer = NULL;
        switch_channel_t *channel = NULL;
-       const char *res_id = NULL;
        switch_status_t status = SWITCH_STATUS_SUCCESS;
        const char *var = NULL;
        switch_rgb_color_t color;
@@ -1257,6 +1266,7 @@ static switch_status_t attach_video_layer(conference_member_t *member, int idx)
 
        channel = switch_core_session_get_channel(member->session);
 
+
        if (!switch_channel_test_flag(channel, CF_VIDEO)) {
                return SWITCH_STATUS_FALSE;
        }
@@ -1264,12 +1274,24 @@ static switch_status_t attach_video_layer(conference_member_t *member, int idx)
        switch_mutex_lock(member->conference->canvas->mutex);
 
        layer = &member->conference->canvas->layers[idx];
+
        layer->tagged = 0;
+       if (layer->geometry.res_id) {
+               if (!member->video_reservation_id || strcmp(layer->geometry.res_id, member->video_reservation_id)) {
+                       switch_goto_status(SWITCH_STATUS_FALSE, end);
+               }
+       }
 
        if (layer->member_id && layer->member_id == member->id) {
                member->video_layer_id = idx;
                switch_goto_status(SWITCH_STATUS_BREAK, end);
        }
+       
+       if (layer->geometry.res_id || member->video_reservation_id) {
+               if (!layer->geometry.res_id || !member->video_reservation_id || strcmp(layer->geometry.res_id, member->video_reservation_id)) {
+                       switch_goto_status(SWITCH_STATUS_FALSE, end);
+               }
+       }
 
        if (member->video_layer_id > -1) {
                detach_video_layer(member);
@@ -1277,14 +1299,6 @@ static switch_status_t attach_video_layer(conference_member_t *member, int idx)
 
        reset_layer(member->conference->canvas, layer);
        switch_img_free(&layer->mute_img);
-
-       res_id = switch_channel_get_variable_dup(channel, "video_reservation_id", SWITCH_FALSE, -1);
-       
-       if (layer->geometry.res_id || res_id) {
-               if (!layer->geometry.res_id || !res_id || strcmp(layer->geometry.res_id, res_id)) {
-                       switch_goto_status(SWITCH_STATUS_FALSE, end);
-               }
-       }
        
        var = NULL;
        if (member->video_banner_text || (var = switch_channel_get_variable_dup(channel, "video_banner_text", SWITCH_FALSE, -1))) {
@@ -1331,6 +1345,7 @@ static void init_canvas_layers(conference_obj_t *conference, video_layout_t *vla
                layer->geometry.y = vlayout->images[i].y;
                layer->geometry.scale = vlayout->images[i].scale;
                layer->geometry.floor = vlayout->images[i].floor;
+               layer->geometry.overlap = vlayout->images[i].overlap;
                layer->idx = i;
 
 
@@ -1651,7 +1666,7 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
                                switch_mutex_lock(conference->canvas->mutex);
                                //printf("MEMBER %d layer_id %d canvas: %d/%d\n", imember->id, imember->video_layer_id,
                                //         conference->canvas->layers_used, conference->canvas->total_layers);
-
+                               
                                if (imember->video_layer_id > -1) {
                                        layer = &conference->canvas->layers[imember->video_layer_id];
                                        if (layer->member_id != imember->id) {
@@ -1663,10 +1678,21 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
                                if (!layer && conference->canvas->layers_used < conference->canvas->total_layers) {
                                        /* find an empty layer */
                                        for (i = 0; i < conference->canvas->total_layers; i++) {
-                                               layer = &conference->canvas->layers[i];
-                                               if (!layer->member_id) {
-                                                       switch_status_t lstatus = attach_video_layer(imember, i);
+                                               mcu_layer_t *xlayer = &conference->canvas->layers[i];
+
+                                               if (xlayer->geometry.res_id) {
+                                                       if (imember->video_reservation_id && !strcmp(xlayer->geometry.res_id, imember->video_reservation_id)) {
+                                                               layer = xlayer;
+                                                               attach_video_layer(imember, i);
+                                                               break;
+                                                       }
+                                               } else if (!xlayer->member_id) {
+                                                       switch_status_t lstatus;
+
+                                                       lstatus = attach_video_layer(imember, i);
+
                                                        if (lstatus == SWITCH_STATUS_SUCCESS || lstatus == SWITCH_STATUS_BREAK) {
+                                                               layer = xlayer;
                                                                break;
                                                        }
                                                }
@@ -1716,7 +1742,7 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
                for (i = 0; i < conference->canvas->total_layers; i++) {
                        mcu_layer_t *layer = &conference->canvas->layers[i];
 
-                       if (layer->member_id > -1 && layer->cur_img && layer->tagged) {
+                       if (layer->member_id > -1 && layer->cur_img && (layer->tagged || layer->geometry.overlap)) {
                                scale_and_patch(conference, layer, NULL);
                                layer->tagged = 0;
                        }
@@ -3547,6 +3573,10 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
                        member->video_mute_png = switch_core_strdup(member->pool, var);
                }
 
+               if ((var = switch_channel_get_variable_dup(member->channel, "video_reservation_id", SWITCH_FALSE, -1))) {
+                       member->video_reservation_id = switch_core_strdup(member->pool, var);
+               }
+
                switch_channel_set_variable_printf(channel, "conference_member_id", "%d", member->id);
                switch_channel_set_variable_printf(channel, "conference_moderator", "%s", switch_test_flag(member, MFLAG_MOD) ? "true" : "false");
                switch_channel_set_variable_printf(channel, "conference_ghost", "%s", switch_test_flag(member, MFLAG_GHOST) ? "true" : "false");
@@ -8140,6 +8170,17 @@ static switch_status_t conf_api_sub_vid_layout(conference_obj_t *conference, swi
                return SWITCH_STATUS_SUCCESS;
        }
 
+       if (!strcasecmp(argv[2], "list")) {
+               switch_hash_index_t *hi;
+               void *val;
+               const void *vvar;
+               for (hi = switch_core_hash_first(conference->layout_hash); hi; hi = switch_core_hash_next(&hi)) {
+                       switch_core_hash_this(hi, &vvar, NULL, &val);
+                       stream->write_function(stream, "%s\n", (char *)vvar);
+               }
+               return SWITCH_STATUS_SUCCESS;
+       }
+
        if (!strcasecmp(argv[2], "group")) {
                layout_group_t *lg = NULL;
 
@@ -8425,15 +8466,15 @@ static switch_status_t conf_api_sub_vid_logo_img(conference_member_t *member, sw
                return SWITCH_STATUS_FALSE;
        }
 
-       switch_mutex_lock(member->conference->canvas->mutex);
-
        if (member->video_layer_id == -1 || !member->conference->canvas) {
                goto end;
        }
 
+       switch_mutex_lock(member->conference->canvas->mutex);
+
        layer = &member->conference->canvas->layers[member->video_layer_id];
        
-       if (!strcasecmp(text, "clear")) {
+       if (strcasecmp(text, "clear")) {
                member->video_logo = switch_core_strdup(member->pool, text);
        }
 
@@ -8449,6 +8490,43 @@ static switch_status_t conf_api_sub_vid_logo_img(conference_member_t *member, sw
 
 }
 
+static switch_status_t conf_api_sub_vid_res_id(conference_member_t *member, switch_stream_handle_t *stream, void *data)
+{
+       char *text = (char *) data;
+       //mcu_layer_t *layer = NULL;
+
+       if (member == NULL)
+               return SWITCH_STATUS_GENERR;
+
+       if (!switch_channel_test_flag(member->channel, CF_VIDEO)) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       if (!member->conference->canvas) {
+               stream->write_function(stream, "-ERR conference is not in mixing mode\n");
+               return SWITCH_STATUS_SUCCESS;
+       }
+
+       switch_mutex_lock(member->conference->canvas->mutex);
+
+       //layer = &member->conference->canvas->layers[member->video_layer_id];
+       
+       if (!strcasecmp(text, "clear")) {
+               member->video_reservation_id = NULL;
+               stream->write_function(stream, "+OK reservation_id cleared\n");
+       } else {
+               member->video_reservation_id = switch_core_strdup(member->pool, text);
+               stream->write_function(stream, "+OK reservation_id %s\n", text);
+       }
+
+       detach_video_layer(member);
+
+       switch_mutex_unlock(member->conference->canvas->mutex);
+
+       return SWITCH_STATUS_SUCCESS;
+
+}
+
 static switch_status_t conf_api_sub_vid_banner(conference_member_t *member, switch_stream_handle_t *stream, void *data)
 {
        mcu_layer_t *layer = NULL;
@@ -9919,6 +9997,7 @@ static api_command_t conf_api_sub_commands[] = {
        {"vid-banner", (void_fn_t) & conf_api_sub_vid_banner, CONF_API_SUB_MEMBER_TARGET, "vid-banner", "<member_id|last> <text>"},
        {"vid-mute-img", (void_fn_t) & conf_api_sub_vid_mute_img, CONF_API_SUB_MEMBER_TARGET, "vid-mute-img", "<member_id|last> [<path>|clear]"},
        {"vid-logo-img", (void_fn_t) & conf_api_sub_vid_logo_img, CONF_API_SUB_MEMBER_TARGET, "vid-logo-img", "<member_id|last> [<path>|clear]"},
+       {"vid-res-id", (void_fn_t) & conf_api_sub_vid_res_id, CONF_API_SUB_MEMBER_TARGET, "vid-res-id", "<member_id|last> <val>|clear"},
        {"clear-vid-floor", (void_fn_t) & conf_api_sub_clear_vid_floor, CONF_API_SUB_ARGS_AS_ONE, "clear-vid-floor", ""},
        {"vid-layout", (void_fn_t) & conf_api_sub_vid_layout, CONF_API_SUB_ARGS_SPLIT, "vid-layout", "<layout name>"},
        {"vid-write-png", (void_fn_t) & conf_api_sub_write_png, CONF_API_SUB_ARGS_SPLIT, "vid-write-png", "<path>"},