switch_bool_t mux;
uint32_t member_id;
al_handle_t *al;
+ int layer_id;
} conference_file_node_t;
typedef enum {
int scale;
int floor;
int flooronly;
+ int fileonly;
int overlap;
char *res_id;
char *audio_position;
switch_image_t *logo_img;
switch_image_t *mute_img;
switch_img_txt_handle_t *txthandle;
+ conference_file_node_t *fnode;
} mcu_layer_t;
typedef struct video_layout_s {
static void member_bind_controls(conference_member_t *member, const char *controls);
static void conference_send_presence(conference_obj_t *conference);
static void conference_set_video_floor_holder(conference_obj_t *conference, conference_member_t *member, switch_bool_t force);
+static void canvas_del_fnode_layer(conference_obj_t *conference, conference_file_node_t *fnode);
+static void canvas_set_fnode_layer(conference_obj_t *conference, conference_file_node_t *fnode, int idx);
SWITCH_STANDARD_API(conf_api_main);
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, flooronly = 0, overlap = 0;
+ int x = -1, y = -1, scale = -1, floor = 0, flooronly = 0, fileonly = 0, overlap = 0;
if ((val = switch_xml_attr(x_image, "x"))) {
x = atoi(val);
flooronly = floor = switch_true(val);
}
+ if ((val = switch_xml_attr(x_image, "file-only"))) {
+ fileonly = floor = switch_true(val);
+ }
+
if ((val = switch_xml_attr(x_image, "overlap"))) {
overlap = switch_true(val);
}
vlayout->images[vlayout->layers].scale = scale;
vlayout->images[vlayout->layers].floor = floor;
vlayout->images[vlayout->layers].flooronly = flooronly;
+ vlayout->images[vlayout->layers].fileonly = fileonly;
vlayout->images[vlayout->layers].overlap = overlap;
if (res_id) {
layer->tagged = 0;
+ if (layer->fnode || layer->geometry.fileonly) {
+ switch_goto_status(SWITCH_STATUS_FALSE, end);
+ }
+
if (layer->geometry.flooronly && member->id != member->conference->video_floor_holder) {
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
attach_video_layer(imember, i);
break;
}
- } else if (xlayer->geometry.flooronly) {
+ } else if (xlayer->geometry.flooronly && !xlayer->fnode) {
if (imember->id == conference->video_floor_holder) {
layer = xlayer;
attach_video_layer(imember, i);
break;
}
- } else if (!xlayer->member_id) {
+ } else if (!xlayer->member_id && !xlayer->fnode && !xlayer->geometry.fileonly) {
switch_status_t lstatus;
lstatus = attach_video_layer(imember, i);
}
switch_mutex_unlock(conference->member_mutex);
-
+
+ if (conference->fnode &&
+ conference->fnode->layer_id > -1) {
+ mcu_layer_t *layer = &conference->canvas->layers[conference->fnode->layer_id];
+
+ if (switch_core_file_read_video(&conference->fnode->fh, &write_frame, SVR_FLUSH) == SWITCH_STATUS_SUCCESS) {
+ switch_img_free(&layer->cur_img);
+ layer->cur_img = write_frame.img;
+ layer->tagged = 1;
+ }
+ }
+
if (!conference->playing_video_file) {
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 || layer->geometry.overlap)) {
+ if ((layer->member_id > -1 || layer->fnode) && layer->cur_img && (layer->tagged || layer->geometry.overlap)) {
if (conference->canvas->refresh) {
layer->refresh = 1;
conference->canvas->refresh++;
conference_file_node_t *fnode;
switch_memory_pool_t *pool;
+ if (conference->canvas && conference->fnode->layer_id > -1 ) {
+ canvas_del_fnode_layer(conference, conference->fnode);
+ }
+
if (conference->fnode->type != NODE_TYPE_SPEECH) {
conference_file_close(conference, conference->fnode);
}
switch_mutex_unlock(conference->mutex);
}
+static void canvas_del_fnode_layer(conference_obj_t *conference, conference_file_node_t *fnode)
+{
+
+ switch_mutex_lock(conference->canvas->mutex);
+ if (fnode->layer_id > -1) {
+ mcu_layer_t *xlayer = &conference->canvas->layers[fnode->layer_id];
+
+ fnode->layer_id = -1;
+ xlayer->fnode = NULL;
+ reset_layer(conference->canvas, xlayer);
+ }
+ switch_mutex_unlock(conference->canvas->mutex);
+}
+
+static void canvas_set_fnode_layer(conference_obj_t *conference, conference_file_node_t *fnode, int idx)
+{
+ mcu_layer_t *layer = NULL;
+
+ switch_mutex_lock(conference->canvas->mutex);
+
+ if (idx == -1) {
+ int i;
+
+ if (conference->canvas->layout_floor_id > -1) {
+ idx = conference->canvas->layout_floor_id;
+ } else {
+ for (i = 0; i < conference->canvas->total_layers; i++) {
+ mcu_layer_t *xlayer = &conference->canvas->layers[i];
+
+ if (xlayer->geometry.res_id || xlayer->member_id) {
+ continue;
+ }
+
+ idx = i;
+ break;
+ }
+ }
+ }
+
+ if (idx < 0) return;
+
+ layer = &conference->canvas->layers[idx];
+
+ layer->fnode = fnode;
+ fnode->layer_id = idx;
+
+ if (layer->member_id > -1) {
+ conference_member_t *member;
+
+ if ((member = conference_member_get(conference, layer->member_id))) {
+ detach_video_layer(member);
+ switch_thread_rwlock_unlock(member->rwlock);
+ }
+ }
+
+ switch_mutex_unlock(conference->canvas->mutex);
+}
+
+
+
/* Play a file in the conference room */
static switch_status_t conference_play_file(conference_obj_t *conference, char *file, uint32_t leadin, switch_channel_t *channel, uint8_t async)
{
goto done;
}
+ fnode->layer_id = -1;
fnode->type = NODE_TYPE_FILE;
fnode->leadin = leadin;
fnode->file = switch_core_strdup(fnode->pool, file);
if (switch_core_file_has_video(&fnode->fh)) {
- conference->canvas->play_file = 1;
- conference->playing_video_file = 1;
+ int full_screen = 0;
+
+ if (fnode->fh.params) {
+ full_screen = switch_true(switch_event_get_header(fnode->fh.params, "full-screen"));
+ }
+
+ if (full_screen) {
+ conference->canvas->play_file = 1;
+ conference->playing_video_file = 1;
+ } else {
+ canvas_set_fnode_layer(conference, fnode, -1);
+ }
}
/* Queue the node */
status = SWITCH_STATUS_MEMERR;
goto done;
}
+
+ fnode->layer_id = -1;
fnode->type = NODE_TYPE_FILE;
fnode->leadin = leadin;
fnode->mux = mux;
return SWITCH_STATUS_MEMERR;
}
+ fnode->layer_id = -1;
+
if (*text == '{') {
char *new_fp;
return SWITCH_STATUS_MEMERR;
}
+ fnode->layer_id = -1;
if (*text == '{') {
char *new_fp;