void compositor_init_svg_audio(GF_Compositor *compositor, GF_Node *node, Bool slaved_timing) { SVG_audio_stack *stack; GF_SAFEALLOC(stack, SVG_audio_stack) gf_sc_audio_setup(&stack->input, compositor, node); /*force first processing of xlink-href*/ gf_node_dirty_set(node, GF_SG_SVG_XLINK_HREF_DIRTY, GF_FALSE); if (!slaved_timing) gf_smil_set_evaluation_callback(node, svg_audio_smil_evaluate); gf_node_set_private(node, stack); gf_node_set_callback_function(node, svg_traverse_audio); }
void compositor_init_anchor(GF_Compositor *compositor, GF_Node *node) { AnchorStack *stack; GF_SAFEALLOC(stack, AnchorStack); stack->hdl.IsEnabled = anchor_is_enabled; stack->hdl.OnUserEvent = OnAnchor; stack->hdl.sensor = node; if (gf_node_get_tag(node)==TAG_MPEG4_Anchor) { ((M_Anchor *)node)->on_activate = on_activate_anchor; } stack->compositor = compositor; mpeg4_sensor_created(compositor, node); gf_node_set_private(node, stack); gf_node_set_callback_function(node, TraverseAnchor); }
void compositor_init_plane_clipper(GF_Compositor *compositor, GF_Node *node) { PlaneClipper pc; if (PlaneClipper_GetNode(node, &pc)) { PlaneClipperStack *stack; GF_SAFEALLOC(stack, PlaneClipperStack); //SetupGroupingNode(stack, compositor->compositor, node, & pc.children); gf_node_set_private(node, stack); gf_node_set_callback_function(node, TraversePlaneClipper); /*we're a grouping node, force bounds rebuild as soon as loaded*/ gf_node_dirty_set(node, GF_SG_CHILD_DIRTY, 0); stack->pc = pc; gf_node_proto_set_grouping(node); } }
void R2D_InitAnchor(Render2D *sr, GF_Node *node) { AnchorStack *stack; M_Anchor *an = (M_Anchor *)node; GF_SAFEALLOC(stack, AnchorStack); SetupGroupingNode2D((GroupingNode2D*)stack, sr, node); sr->compositor->interaction_sensors++; an->on_activate = on_activate_anchor; stack->hdl.IsEnabled = anchor_is_enabled; stack->hdl.OnUserEvent = OnAnchor; stack->hdl.owner = node; gf_node_set_private(node, stack); gf_node_set_callback_function(node, RenderAnchor); }
void compositor_init_timesensor(GF_Compositor *compositor, GF_Node *node) { TimeSensorStack *st; GF_SAFEALLOC(st, TimeSensorStack); st->time_handle.UpdateTimeNode = timesensor_update_time; st->time_handle.udta = node; st->store_info = 1; st->compositor = compositor; #ifndef GPAC_DISABLE_X3D st->is_x3d = (gf_node_get_tag(node)==TAG_X3D_TimeSensor) ? 1 : 0; #endif gf_node_set_private(node, st); gf_node_set_callback_function(node, timesensor_destroy); /*time sensor needs to be run only if def'ed, otherwise it doesn't impact scene*/ //if (gf_node_get_id(node)) gf_sc_register_time_node(compositor, &st->time_handle); }
static void svg2bifs_node_end(void *sax_cbck, const char *name, const char *name_space) { SVG_SANI_BIFS_Converter *converter = (SVG_SANI_BIFS_Converter *)sax_cbck; GF_Node *parent; SVGPropertiesPointers *backup_props = gf_node_get_private(converter->svg_parent); memcpy(&converter->svg_props, backup_props, sizeof(SVGPropertiesPointers)); // free(backup_props); gf_node_set_private(converter->svg_parent, NULL); converter->bifs_parent = gf_node_get_parent(converter->bifs_parent, 0); parent = gf_node_get_parent(converter->svg_parent, 0); gf_node_unregister(converter->svg_parent, parent); if (!parent) gf_sg_set_root_node(converter->svg_sg, NULL); converter->svg_parent = parent; converter->bifs_text_node = NULL; }
void SetupConditional(GF_BifsDecoder *codec, GF_Node *node) { ConditionalStack *priv; if (gf_node_get_tag(node) != TAG_MPEG4_Conditional) return; priv = (ConditionalStack*)gf_malloc(sizeof(ConditionalStack)); /*needed when initializing extern protos*/ if (!codec->info) codec->info = (BIFSStreamInfo*)gf_list_get(codec->streamInfo, 0); if (!codec->info) return; priv->info = codec->info; priv->codec = codec; gf_node_set_callback_function(node, Conditional_PreDestroy); gf_node_set_private(node, priv); ((M_Conditional *)node)->on_activate = Conditional_OnActivate; ((M_Conditional *)node)->on_reverseActivate = Conditional_OnReverseActivate; }
static void gf_seng_on_node_modified(void *_seng, u32 type, GF_Node *node, void *ctxdata) { switch (type) { #ifndef GPAC_DISABLE_VRML case GF_SG_CALLBACK_INIT: if (gf_node_get_tag(node) == TAG_MPEG4_Conditional) { M_Conditional*c = (M_Conditional*)node; c->on_activate = seng_conditional_activate; c->on_reverseActivate = seng_conditional_reverse_activate; gf_node_set_private(node, _seng); } break; #endif case GF_SG_CALLBACK_MODIFIED: gf_node_dirty_parents(node); break; } }
void compositor_init_svg_image(GF_Compositor *compositor, GF_Node *node) { SVG_video_stack *stack; GF_SAFEALLOC(stack, SVG_video_stack) stack->graph = drawable_new(); stack->graph->flags = DRAWABLE_USE_TRAVERSE_DRAW; stack->graph->node = node; gf_sc_texture_setup(&stack->txh, compositor, node); stack->txh.update_texture_fcnt = SVG_Update_image; stack->txh.flags = GF_SR_TEXTURE_SVG; /*force first processing of xlink-href*/ gf_node_dirty_set(node, GF_SG_SVG_XLINK_HREF_DIRTY, GF_FALSE); gf_node_set_private(node, stack); gf_node_set_callback_function(node, svg_traverse_image); }
void compositor_init_svg_svg(GF_Compositor *compositor, GF_Node *node) { GF_Node *root; SVGsvgStack *stack; GF_SAFEALLOC(stack, SVGsvgStack); root = gf_sg_get_root_node(gf_node_get_graph(node)); stack->root_svg = (root==node) ? 1 : 0; if (stack->root_svg) { GF_SAFEALLOC(stack->svg_props, SVGPropertiesPointers); gf_svg_properties_init_pointers(stack->svg_props); } gf_mx2d_init(stack->viewbox_mx); gf_node_set_private(node, stack); gf_node_set_callback_function(node, svg_traverse_svg); }
void R3D_InitAnchor(Render3D *sr, GF_Node *node) { AnchorStack *stack; GF_SAFEALLOC(stack, AnchorStack); stack->hdl.IsEnabled = anchor_is_enabled; stack->hdl.OnUserEvent = OnAnchor; stack->hdl.owner = node; if (gf_node_get_tag(node)==TAG_MPEG4_Anchor) { ((M_Anchor *)node)->on_activate = on_activate_anchor; SetupGroupingNode((GroupingNode*)stack, sr->compositor, node, & ((M_Anchor *)node)->children); } else { SetupGroupingNode((GroupingNode*)stack, sr->compositor, node, & ((X_Anchor *)node)->children); } sr->compositor->interaction_sensors++; gf_node_set_private(node, stack); gf_node_set_callback_function(node, RenderAnchor); }
void compositor_init_compositetexture3d(GF_Compositor *compositor, GF_Node *node) { M_CompositeTexture3D *c3d = (M_CompositeTexture3D *)node; CompositeTextureStack *st; GF_SAFEALLOC(st, CompositeTextureStack); st->sensors = gf_list_new(); st->previous_sensors = gf_list_new(); gf_sc_texture_setup(&st->txh, compositor, node); /*remove texture from compositor and add it at the end, so that any sub-textures are handled before*/ gf_list_del_item(compositor->textures, &st->txh); gf_list_add(compositor->textures, &st->txh); st->txh.update_texture_fcnt = composite_update; if (c3d->repeatS) st->txh.flags |= GF_SR_TEXTURE_REPEAT_S; if (c3d->repeatT) st->txh.flags |= GF_SR_TEXTURE_REPEAT_T; /*create composite visual*/ st->visual = visual_new(compositor); st->visual->offscreen = node; st->visual->GetSurfaceAccess = composite_get_video_access; st->visual->ReleaseSurfaceAccess = composite_release_video_access; st->first = 1; st->visual->compositor = compositor; gf_node_set_private(node, st); gf_node_set_callback_function(node, composite_traverse); gf_sc_visual_register(compositor, st->visual); #ifdef GPAC_USE_TINYGL st->visual->type_3d = 2; st->visual->camera.is_3D = 1; #else if (! (compositor->video_out->hw_caps & GF_VIDEO_HW_OPENGL_OFFSCREEN)) { st->visual->type_3d = 0; st->visual->camera.is_3D = 0; } else { st->visual->type_3d = 2; st->visual->camera.is_3D = 1; } #endif camera_invalidate(&st->visual->camera); }
void compositor_init_test_sensor(GF_Compositor *compositor, GF_Node *node) { TestSensor ts; if (TestSensor_GetNode(node, &ts)) { GF_Err e; TestSensorStack *stack; GF_SAFEALLOC(stack, TestSensorStack); gf_node_set_private(node, stack); gf_node_set_callback_function(node, TraverseTestSensor); stack->ts = ts; e = gf_node_set_proto_eventin_handler(node, 0, TestSensor_OnTrigger); if (e) { GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to initialize Proto TestSensor callback: %s\n", gf_error_to_string(e) )); } } else { GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Compositor] Unable to initialize test sensor\n")); } }
void compositor_init_imagetexture(GF_Compositor *compositor, GF_Node *node) { GF_TextureHandler *txh; GF_SAFEALLOC(txh, GF_TextureHandler); gf_sc_texture_setup(txh, compositor, node); txh->update_texture_fcnt = imagetexture_update; gf_node_set_private(node, txh); gf_node_set_callback_function(node, imagetexture_destroy); txh->flags = 0; if (gf_node_get_tag(txh->owner)!=TAG_MPEG4_CacheTexture) { if (((M_ImageTexture*)node)->repeatS) txh->flags |= GF_SR_TEXTURE_REPEAT_S; if (((M_ImageTexture*)node)->repeatT) txh->flags |= GF_SR_TEXTURE_REPEAT_T; } else { const char *url; u32 i, count; M_CacheTexture*ct = (M_CacheTexture*)node; if (!ct->image.buffer) return; if (ct->repeatS) txh->flags |= GF_SR_TEXTURE_REPEAT_S; if (ct->repeatT) txh->flags |= GF_SR_TEXTURE_REPEAT_T; /*locate existing cache*/ url = gf_scene_get_service_url( gf_node_get_graph(node) ); count = gf_cfg_get_section_count(compositor->user->config); for (i=0; i<count; i++) { const char *opt; const char *name = gf_cfg_get_section_name(compositor->user->config, i); if (strncmp(name, "@cache=", 7)) continue; opt = gf_cfg_get_key(compositor->user->config, name, "serviceURL"); if (!opt || stricmp(opt, url)) continue; opt = gf_cfg_get_key(compositor->user->config, name, "cacheName"); if (opt && ct->cacheURL.buffer && !stricmp(opt, ct->cacheURL.buffer)) { opt = gf_cfg_get_key(compositor->user->config, name, "cacheFile"); if (opt) gf_delete_file((char*)opt); gf_cfg_del_section(compositor->user->config, name); break; } } } }
void compositor_init_audiobuffer(GF_Compositor *compositor, GF_Node *node) { AudioBufferStack *st; GF_SAFEALLOC(st, AudioBufferStack); /*use our private input*/ setup_audiobufer(&st->output, compositor, node); st->add_source = audiobuffer_add_source; st->time_handle.UpdateTimeNode = audiobuffer_update_time; st->time_handle.udta = node; st->set_duration = 1; st->am = gf_mixer_new(NULL); st->new_inputs = gf_list_new(); gf_node_set_private(node, st); gf_node_set_callback_function(node, audiobuffer_traverse); gf_sc_register_time_node(compositor, &st->time_handle); }
static void svg2bifs_node_end(void *sax_cbck, const char *name, const char *name_space) { SVG2BIFS_Converter *converter = (SVG2BIFS_Converter *)sax_cbck; GF_Node *parent; SVGPropertiesPointers *backup_props = gf_node_get_private(converter->svg_parent); memcpy(&converter->svg_props, backup_props, sizeof(SVGPropertiesPointers)); // gf_free(backup_props); gf_node_set_private(converter->svg_parent, NULL); if (!(gf_node_get_tag(converter->svg_parent) == TAG_SVG_animateTransform)) converter->bifs_parent = gf_node_get_parent(converter->bifs_parent, 0); parent = gf_node_get_parent(converter->svg_parent, 0); gf_node_unregister(converter->svg_parent, parent); if (!parent) gf_sg_set_root_node(converter->svg_sg, NULL); converter->svg_parent = parent; converter->bifs_text_node = NULL; fprintf(stdout, "END:\t%s\t%s\n", converter->svg_parent ? gf_node_get_class_name(converter->svg_parent) : "none", converter->bifs_parent ? gf_node_get_class_name(converter->bifs_parent) : "none"); }
/*this is ugly but we have no choice, we need to clone the conditional stack because of externProto*/ void BIFS_SetupConditionalClone(GF_Node *node, GF_Node *orig) { #ifndef GPAC_DISABLE_BIFS M_Conditional *ptr; ConditionalStack *priv_orig, *priv; priv_orig = (ConditionalStack*)gf_node_get_private(orig); /*looks we're not in BIFS*/ if (!priv_orig) { #else { #endif #ifndef GPAC_DISABLE_VRML u32 i; GF_Command *ori_com; M_Conditional *c_orig, *c_dest; c_orig = (M_Conditional *)orig; c_dest = (M_Conditional *)node; gf_node_init(node); /*and clone all commands*/ i=0; while ((ori_com = (GF_Command*)gf_list_enum(c_orig->buffer.commandList, &i))) { GF_Command *dest_com = gf_sg_vrml_command_clone(ori_com, gf_node_get_graph(node), 1); if (dest_com) gf_list_add(c_dest->buffer.commandList, dest_com); } #endif return; } #ifndef GPAC_DISABLE_BIFS priv = (ConditionalStack*)gf_malloc(sizeof(ConditionalStack)); priv->codec = priv_orig->codec; priv->info = priv_orig->info; gf_node_set_callback_function(node, Conditional_PreDestroy); gf_node_set_private(node, priv); ptr = (M_Conditional *)node; ptr->on_activate = Conditional_OnActivate; ptr->on_reverseActivate = Conditional_OnReverseActivate; #endif }
void compositor_init_layer3d(GF_Compositor *compositor, GF_Node *node) { Layer3DStack *stack; GF_SAFEALLOC(stack, Layer3DStack); stack->visual = visual_new(compositor); stack->visual->type_3d = 2; stack->visual->camera.is_3D = 1; stack->visual->camera.visibility = 0; stack->visual->camera.speed = FIX_ONE; camera_invalidate(&stack->visual->camera); stack->first = 1; stack->txh.compositor = compositor; stack->drawable = drawable_new(); stack->drawable->node = node; stack->drawable->flags = DRAWABLE_USE_TRAVERSE_DRAW; gf_node_set_private(node, stack); gf_node_set_callback_function(node, TraverseLayer3D); }
void compositor_init_background2d(GF_Compositor *compositor, GF_Node *node) { Background2DStack *ptr; GF_SAFEALLOC(ptr, Background2DStack); ptr->status_stack = gf_list_new(); ptr->reg_stacks = gf_list_new(); /*setup drawable object for background*/ ptr->drawable = drawable_stack_new(compositor, node); ptr->drawable->flags = DRAWABLE_USE_TRAVERSE_DRAW; ((M_Background2D *)node)->on_set_bind = b2D_set_bind; gf_sc_texture_setup(&ptr->txh, compositor, node); ptr->txh.update_texture_fcnt = UpdateBackgroundTexture; ptr->txh.flags = GF_SR_TEXTURE_REPEAT_S | GF_SR_TEXTURE_REPEAT_T; ptr->flags = CTX_IS_BACKGROUND; gf_node_set_private(node, ptr); gf_node_set_callback_function(node, TraverseBackground2D); }
static Bool gf_inline_set_scene(M_Inline *root) { GF_MediaObject *mo; GF_Scene *parent; GF_SceneGraph *graph = gf_node_get_graph((GF_Node *) root); parent = (GF_Scene *)gf_sg_get_private(graph); if (!parent) return 0; mo = gf_scene_get_media_object_ex(parent, &root->url, GF_MEDIA_OBJECT_SCENE, 0, NULL, 0, (GF_Node*)root); if (!mo || !mo->odm) return 0; if (!mo->odm->subscene) { gf_term_invalidate_compositor(parent->root_od->term); return 0; } /*assign inline scene as private stack of inline node, and remember inline node for event propagation*/ gf_node_set_private((GF_Node *)root, mo->odm->subscene); /*play*/ gf_mo_play(mo, 0, -1, 0); return 1; }
void gf_scene_init_storage(GF_Scene *scene, GF_Node *node) { GF_ClientService *net_service; M_Storage *storage = (M_Storage *) node; if (!storage->name.buffer || !strlen(storage->name.buffer) ) return; if (!storage->storageList.count) return; storage->on_forceSave = on_force_save; storage->on_forceRestore = on_force_restore; gf_node_set_callback_function(node, gf_storage_traverse); gf_node_set_private(node, scene); net_service = scene->root_od->net_service; while (scene->root_od->parentscene) { if (scene->root_od->parentscene->root_od->net_service != net_service) break; scene = scene->root_od->parentscene; } gf_list_add(scene->storages, node); if (storage->_auto) gf_storage_load(storage); }
void compositor_init_movietexture(GF_Compositor *compositor, GF_Node *node) { MovieTextureStack *st; GF_SAFEALLOC(st, MovieTextureStack); gf_sc_texture_setup(&st->txh, compositor, node); st->txh.update_texture_fcnt = movietexture_update; st->time_handle.UpdateTimeNode = movietexture_update_time; st->time_handle.udta = node; st->fetch_first_frame = 1; st->txh.flags = 0; if (((M_MovieTexture*)node)->repeatS) st->txh.flags |= GF_SR_TEXTURE_REPEAT_S; if (((M_MovieTexture*)node)->repeatT) st->txh.flags |= GF_SR_TEXTURE_REPEAT_T; #ifndef GPAC_DISABLE_X3D st->is_x3d = (gf_node_get_tag(node)==TAG_X3D_MovieTexture) ? 1 : 0; #endif gf_node_set_private(node, st); gf_node_set_callback_function(node, movietexture_destroy); gf_sc_register_time_node(compositor, &st->time_handle); }
static void svg2bifs_node_start(void *sax_cbck, const char *name, const char *name_space, const GF_XMLAttribute *attributes, u32 nb_attributes) { u32 i; SVG_SANI_BIFS_Converter *converter = (SVG_SANI_BIFS_Converter *)sax_cbck; SVGPropertiesPointers *backup_props; char *id_string = NULL; u32 tag = gf_svg_get_element_tag(name); SVG_Element *elt = (SVG_Element*)gf_node_new(converter->svg_sg, tag); if (!gf_sg_get_root_node(converter->svg_sg)) { gf_node_register((GF_Node *)elt, NULL); gf_sg_set_root_node(converter->svg_sg, (GF_Node *)elt); } else { gf_node_register((GF_Node *)elt, converter->svg_parent); //gf_node_list_add_child(&((GF_ParentNode*)converter->svg_parent)->children, (GF_Node *)elt); } converter->svg_parent = (GF_Node *)elt; // fprintf(stdout, "Converting %s\n", gf_node_get_class_name((GF_Node *)elt)); // if (converter->bifs_parent) fprintf(stdout, "%s\n", gf_node_get_class_name(converter->bifs_parent)); for (i=0; i<nb_attributes; i++) { GF_XMLAttribute *att = (GF_XMLAttribute *)&attributes[i]; if (!att->value || !strlen(att->value)) continue; if (!stricmp(att->name, "style")) { gf_svg_parse_style((GF_Node *)elt, att->value); } else if (!stricmp(att->name, "id") || !stricmp(att->name, "xml:id")) { gf_svg_parse_element_id((GF_Node *)elt, att->value, 0); id_string = att->value; } else { GF_FieldInfo info; if (gf_node_get_field_by_name((GF_Node *)elt, att->name, &info)==GF_OK) { gf_svg_parse_attribute((GF_Node *)elt, &info, att->value, 0); } else { fprintf(stdout, "Skipping attribute %s\n", att->name); } } } memset(&converter->all_atts, 0, sizeof(SVGAllAttributes)); gf_svg_flatten_attributes(elt, &converter->all_atts); backup_props = gf_malloc(sizeof(SVGPropertiesPointers)); memcpy(backup_props, &converter->svg_props, sizeof(SVGPropertiesPointers)); gf_node_set_private((GF_Node *)elt, backup_props); gf_svg_apply_inheritance(&converter->all_atts, &converter->svg_props); if (!gf_sg_get_root_node(converter->bifs_sg)) { if (tag == TAG_SVG_svg) { GF_Node *node, *child; converter->bifs_sg->usePixelMetrics = 1; if (converter->all_atts.width && converter->all_atts.width->type == SVG_NUMBER_VALUE) { converter->bifs_sg->width = FIX2INT(converter->all_atts.width->value); } else { converter->bifs_sg->width = 320; } if (converter->all_atts.height && converter->all_atts.height->type == SVG_NUMBER_VALUE) { converter->bifs_sg->height = FIX2INT(converter->all_atts.height->value); } else { converter->bifs_sg->height = 200; } node = gf_node_new(converter->bifs_sg, TAG_MPEG4_OrderedGroup); gf_node_register(node, NULL); gf_sg_set_root_node(converter->bifs_sg, node); /* SVG to BIFS coordinate transformation */ child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Viewport); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); if (converter->all_atts.viewBox) { M_Viewport *vp = (M_Viewport*)child; vp->size.x = converter->all_atts.viewBox->width; vp->size.y = converter->all_atts.viewBox->height; vp->position.x = converter->all_atts.viewBox->x+converter->all_atts.viewBox->width/2; vp->position.y = -(converter->all_atts.viewBox->y+converter->all_atts.viewBox->height/2); } else { M_Viewport *vp = (M_Viewport*)child; vp->size.x = INT2FIX(converter->bifs_sg->width); vp->size.y = INT2FIX(converter->bifs_sg->height); vp->position.x = INT2FIX(converter->bifs_sg->width)/2; vp->position.y = -INT2FIX(converter->bifs_sg->height)/2; } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Background2D); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); { M_Background2D *b = (M_Background2D *)child; b->backColor.red = FIX_ONE; b->backColor.green = FIX_ONE; b->backColor.blue = FIX_ONE; } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; { M_Transform2D *tr = (M_Transform2D *)node; tr->scale.y = -FIX_ONE; } converter->bifs_parent = node; } } else { GF_Node *node, *child; node = converter->bifs_parent; switch(tag) { case TAG_SVG_g: { if (converter->all_atts.transform) { node = add_transform(converter, node); converter->bifs_parent = node; } else { M_Group *g = (M_Group*)gf_node_new(converter->bifs_sg, TAG_MPEG4_Group); gf_node_register((GF_Node *)g, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, (GF_Node *)g); node = (GF_Node *)g; converter->bifs_parent = node; } } break; case TAG_SVG_rect: { Bool is_parent_set = 0; if (converter->all_atts.transform) { node = add_transform(converter, node); converter->bifs_parent = node; is_parent_set = 1; } if (converter->all_atts.x || converter->all_atts.y) { child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } { M_Transform2D *tr = (M_Transform2D *)node; if (converter->all_atts.x) tr->translation.x = converter->all_atts.x->value + (converter->all_atts.width?converter->all_atts.width->value/2:0); if (converter->all_atts.y) tr->translation.y = converter->all_atts.y->value + (converter->all_atts.height?converter->all_atts.height->value/2:0); } } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; if (!is_parent_set) converter->bifs_parent = node; { M_Shape *shape = (M_Shape *)node; shape->geometry = gf_node_new(converter->bifs_sg, TAG_MPEG4_Rectangle); gf_node_register(shape->geometry, (GF_Node *)shape); { M_Rectangle *rect = (M_Rectangle *)shape->geometry; if (converter->all_atts.width) rect->size.x = converter->all_atts.width->value; if (converter->all_atts.height) rect->size.y = converter->all_atts.height->value; } shape->appearance = create_appearance(&converter->svg_props, converter->bifs_sg); gf_node_register(shape->appearance, (GF_Node *)shape); } } break; case TAG_SVG_path: { Bool is_parent_set = 0; if (converter->all_atts.transform) { node = add_transform(converter, node); converter->bifs_parent = node; is_parent_set = 1; } if (converter->all_atts.x || converter->all_atts.y) { child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } { M_Transform2D *tr = (M_Transform2D *)node; if (converter->all_atts.x) tr->translation.x = converter->all_atts.x->value; if (converter->all_atts.y) tr->translation.y = converter->all_atts.y->value; } } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; if (!is_parent_set) converter->bifs_parent = node; { M_Shape *shape = (M_Shape *)node; shape->geometry = gf_node_new(converter->bifs_sg, TAG_MPEG4_XCurve2D); gf_node_register(shape->geometry, (GF_Node *)shape); if (converter->all_atts.d) { M_Coordinate2D *c2d; M_XCurve2D *xc = (M_XCurve2D *)shape->geometry; u32 i, j, c; xc->point = gf_node_new(converter->bifs_sg, TAG_MPEG4_Coordinate2D); c2d = (M_Coordinate2D *)xc->point; gf_node_register(xc->point, (GF_Node *)xc); gf_sg_vrml_mf_alloc(&c2d->point, GF_SG_VRML_MFVEC2F, converter->all_atts.d->n_points); j= 0; for (i = 0; i < converter->all_atts.d->n_points; i++) { if (converter->all_atts.d->tags[i] != GF_PATH_CLOSE || i == converter->all_atts.d->n_points-1) { c2d->point.vals[j] = converter->all_atts.d->points[i]; j++; } } c2d->point.count = j; gf_sg_vrml_mf_alloc(&xc->type, GF_SG_VRML_MFINT32, converter->all_atts.d->n_points); c = 0; j = 0; xc->type.vals[0] = 0; for (i = 1; i < converter->all_atts.d->n_points; i++) { switch(converter->all_atts.d->tags[i]) { case GF_PATH_CURVE_ON: if (c < converter->all_atts.d->n_contours && i-1 == converter->all_atts.d->contours[c]) { xc->type.vals[j] = 0; c++; } else { xc->type.vals[j] = 1; } break; case GF_PATH_CURVE_CUBIC: xc->type.vals[j] = 2; i+=2; break; case GF_PATH_CLOSE: xc->type.vals[j] = 6; break; case GF_PATH_CURVE_CONIC: xc->type.vals[j] = 7; i++; break; } j++; } xc->type.count = j; } shape->appearance = create_appearance(&converter->svg_props, converter->bifs_sg); gf_node_register(shape->appearance, (GF_Node *)shape); } } break; case TAG_SVG_polyline: { Bool is_parent_set = 0; if (converter->all_atts.transform) { node = add_transform(converter, node); converter->bifs_parent = node; is_parent_set = 1; } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; if (!is_parent_set) converter->bifs_parent = node; { M_Shape *shape = (M_Shape *)node; shape->geometry = gf_node_new(converter->bifs_sg, TAG_MPEG4_IndexedFaceSet2D); gf_node_register(shape->geometry, (GF_Node *)shape); if (converter->all_atts.points) { M_Coordinate2D *c2d; M_IndexedFaceSet2D *ifs = (M_IndexedFaceSet2D *)shape->geometry; u32 i; ifs->coord = gf_node_new(converter->bifs_sg, TAG_MPEG4_Coordinate2D); c2d = (M_Coordinate2D *)ifs->coord; gf_node_register(ifs->coord, (GF_Node *)ifs); gf_sg_vrml_mf_alloc(&c2d->point, GF_SG_VRML_MFVEC2F, gf_list_count(*converter->all_atts.points)); for (i = 0; i < gf_list_count(*converter->all_atts.points); i++) { SVG_Point *p = (SVG_Point *)gf_list_get(*converter->all_atts.points, i); c2d->point.vals[i].x = p->x; c2d->point.vals[i].y = p->y; } } shape->appearance = create_appearance(&converter->svg_props, converter->bifs_sg); gf_node_register(shape->appearance, (GF_Node *)shape); } } break; case TAG_SVG_text: { Bool is_parent_set = 0; if (converter->all_atts.transform) { node = add_transform(converter, node); converter->bifs_parent = node; is_parent_set = 1; } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); { M_Transform2D *tr = (M_Transform2D *)child; if (converter->all_atts.text_x) tr->translation.x = ((SVG_Coordinate *)gf_list_get(*converter->all_atts.text_x, 0))->value; if (converter->all_atts.text_y) tr->translation.y = ((SVG_Coordinate *)gf_list_get(*converter->all_atts.text_y, 0))->value; tr->scale.y = -FIX_ONE; } node = child; child = NULL; if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; if (!is_parent_set) converter->bifs_parent = node; { M_FontStyle *fs; M_Text *text; M_Shape *shape = (M_Shape *)node; text = (M_Text *)gf_node_new(converter->bifs_sg, TAG_MPEG4_Text); shape->geometry = (GF_Node *)text; converter->bifs_text_node = shape->geometry; gf_node_register(shape->geometry, (GF_Node *)shape); fs = (M_FontStyle *)gf_node_new(converter->bifs_sg, TAG_MPEG4_XFontStyle); gf_node_register((GF_Node *)fs, (GF_Node*)text); text->fontStyle = (GF_Node *)fs; gf_sg_vrml_mf_alloc(&fs->family, GF_SG_VRML_MFSTRING, 1); fs->family.vals[0] = strdup(converter->svg_props.font_family->value); fs->size = converter->svg_props.font_size->value; shape->appearance = create_appearance(&converter->svg_props, converter->bifs_sg); gf_node_register(shape->appearance, (GF_Node *)shape); } } break; case TAG_SVG_ellipse: case TAG_SVG_circle: { Bool is_parent_set = 0; if (converter->all_atts.transform) { node = add_transform(converter, node); converter->bifs_parent = node; is_parent_set = 1; } if (converter->all_atts.cx || converter->all_atts.cy) { child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); { M_Transform2D *tr = (M_Transform2D *)child; if (converter->all_atts.cx) tr->translation.x = converter->all_atts.cx->value; if (converter->all_atts.cy) tr->translation.y = converter->all_atts.cy->value; } node = child; child = NULL; if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; if (!is_parent_set) converter->bifs_parent = node; { M_Shape *shape = (M_Shape *)node; if (tag == TAG_SVG_ellipse) { M_Ellipse *e = (M_Ellipse *)gf_node_new(converter->bifs_sg, TAG_MPEG4_Ellipse); shape->geometry = (GF_Node *)e; e->radius.x = converter->all_atts.rx->value; e->radius.y = converter->all_atts.ry->value; } else { M_Circle *c = (M_Circle *)gf_node_new(converter->bifs_sg, TAG_MPEG4_Circle); shape->geometry = (GF_Node *)c; c->radius = converter->all_atts.r->value; } gf_node_register(shape->geometry, (GF_Node *)shape); shape->appearance = create_appearance(&converter->svg_props, converter->bifs_sg); gf_node_register(shape->appearance, (GF_Node *)shape); } } break; case TAG_SVG_defs: { child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Switch); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; { M_Switch *sw = (M_Switch *)node; sw->whichChoice = -1; } converter->bifs_parent = node; } break; case TAG_SVG_solidColor: { child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; converter->bifs_parent = node; } break; default: { fprintf(stdout, "Warning: element %s not supported \n", gf_node_get_class_name((GF_Node *)elt)); child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; converter->bifs_parent = node; } break; } if (id_string) gf_node_set_id(converter->bifs_parent, gf_node_get_id((GF_Node *)elt), gf_node_get_name((GF_Node *)elt)); } }
void compositor_init_svg_font(GF_Compositor *compositor, GF_Node *node) { SVG_handlerElement *handler; GF_Err e; SVGAllAttributes atts; GF_Font *font; GF_Node *node_font = gf_node_get_parent(node, 0); if (!node_font) return; if (gf_node_get_tag(node_font)!=TAG_SVG_font) return; gf_svg_flatten_attributes((SVG_Element*)node, &atts); if (!atts.font_family) return; /*register font to font manager*/ GF_SAFEALLOC(font, GF_Font); e = gf_font_manager_register_font(compositor->font_manager, font); if (e) { gf_free(font); return; } font->ft_mgr = compositor->font_manager; font->get_glyphs = svg_font_get_glyphs; font->load_glyph = svg_font_load_glyph; font->udta = node_font; gf_node_set_private(node_font, font); gf_node_set_callback_function(node_font, svg_traverse_font); font->name = gf_strdup(atts.font_family->value); font->em_size = atts.units_per_em ? FIX2INT( gf_ceil(atts.units_per_em->value) ) : 1000; /*Inconsistency between SVG 1.2 and 1.1 when not specify, ascent and descent are computed based on font.vert-origin-y, WHICH DOES NOT EXIST IN Tiny 1.2 !!! We assume it to be 0. */ font->ascent = atts.ascent ? FIX2INT( gf_ceil(atts.ascent->value) ) : 0; if (!font->ascent) font->ascent = font->em_size; font->descent = atts.descent ? FIX2INT( gf_ceil(atts.descent->value) ) : 0; font->baseline = atts.alphabetic ? FIX2INT( gf_ceil(atts.alphabetic->value) ) : 0; font->line_spacing = font->em_size; font->styles = 0; if (atts.font_style) { switch (*atts.font_style) { case SVG_FONTSTYLE_ITALIC: font->styles |= GF_FONT_ITALIC; break; case SVG_FONTSTYLE_OBLIQUE: font->styles |= GF_FONT_OBLIQUE; break; } } if (atts.font_variant && (*atts.font_variant ==SVG_FONTVARIANT_SMALLCAPS)) font->styles |= GF_FONT_SMALLCAPS; if (atts.font_weight) { switch(*atts.font_weight) { case SVG_FONTWEIGHT_100: font->styles |= GF_FONT_WEIGHT_100; break; case SVG_FONTWEIGHT_LIGHTER: font->styles |= GF_FONT_WEIGHT_LIGHTER; break; case SVG_FONTWEIGHT_200: font->styles |= GF_FONT_WEIGHT_200; break; case SVG_FONTWEIGHT_300: font->styles |= GF_FONT_WEIGHT_300; break; case SVG_FONTWEIGHT_400: font->styles |= GF_FONT_WEIGHT_400; break; case SVG_FONTWEIGHT_NORMAL: font->styles |= GF_FONT_WEIGHT_NORMAL; break; case SVG_FONTWEIGHT_500: font->styles |= GF_FONT_WEIGHT_500; break; case SVG_FONTWEIGHT_600: font->styles |= GF_FONT_WEIGHT_600; break; case SVG_FONTWEIGHT_700: font->styles |= GF_FONT_WEIGHT_700; break; case SVG_FONTWEIGHT_BOLD: font->styles |= GF_FONT_WEIGHT_BOLD; break; case SVG_FONTWEIGHT_800: font->styles |= GF_FONT_WEIGHT_800; break; case SVG_FONTWEIGHT_900: font->styles |= GF_FONT_WEIGHT_900; break; case SVG_FONTWEIGHT_BOLDER: font->styles |= GF_FONT_WEIGHT_BOLDER; break; } } gf_svg_flatten_attributes((SVG_Element*)node_font, &atts); font->max_advance_h = atts.horiz_adv_x ? FIX2INT( gf_ceil(atts.horiz_adv_x->value) ) : 0; font->not_loaded = 1; /*wait for onLoad event before activating the font, otherwise we may not have all the glyphs*/ handler = gf_dom_listener_build(node_font, GF_EVENT_LOAD, 0); handler->handle_event = svg_font_on_load; gf_node_set_private((GF_Node *)handler, compositor); }
void compositor_init_svg_glyph(GF_Compositor *compositor, GF_Node *node) { u16 utf_name[20]; u8 *utf8; u32 len; GF_Rect rc; GF_Glyph *glyph; GF_Font *font; SVG_GlyphStack *st; SVGAllAttributes atts; GF_Node *node_font = gf_node_get_parent(node, 0); /*locate the font node*/ if (node_font) node_font = gf_node_get_parent(node, 0); if (!node_font || (gf_node_get_tag(node_font)!=TAG_SVG_font) ) return; font = gf_node_get_private(node_font); if (!font) return; gf_svg_flatten_attributes((SVG_Element*)node, &atts); if (gf_node_get_tag(node)==TAG_SVG_missing_glyph) { GF_SAFEALLOC(st, SVG_GlyphStack); goto reg_common; } /*we must have unicode specified*/ if (!atts.unicode) return; GF_SAFEALLOC(st, SVG_GlyphStack); utf8 = (u8 *) *atts.unicode; len = gf_utf8_mbstowcs(utf_name, 200, (const char **) &utf8); /*this is a single glyph*/ if (len==1) { st->glyph.utf_name = utf_name[0]; st->uni_len = 1; } else { st->glyph.utf_name = (u32) (PTR_TO_U_CAST st); st->unicode = gf_malloc(sizeof(u16)*len); st->uni_len = len; memcpy(st->unicode, utf_name, sizeof(u16)*len); } reg_common: st->glyph.ID = (u32) (PTR_TO_U_CAST st); st->font = font; st->glyph.horiz_advance = font->max_advance_h; if (atts.horiz_adv_x) st->glyph.horiz_advance = FIX2INT( gf_ceil(atts.horiz_adv_x->value) ); if (atts.d) { st->glyph.path = atts.d; gf_path_get_bounds(atts.d, &rc); st->glyph.width = FIX2INT( gf_ceil(rc.width) ); st->glyph.height = FIX2INT( gf_ceil(rc.height) ); } st->glyph.vert_advance = st->glyph.height; if (!st->glyph.vert_advance) st->glyph.vert_advance = font->max_advance_v; /*register glyph*/ if (!font->glyph) { font->glyph = &st->glyph; } else { glyph = font->glyph; while (glyph->next) glyph = glyph->next; glyph->next = &st->glyph; } gf_node_set_private(node, st); gf_node_set_callback_function(node, svg_traverse_glyph); }
void InitKeySensor(GF_Scene *scene, GF_Node *node) { gf_node_set_private(node, scene->root_od->term); gf_node_set_callback_function(node, DestroyKeySensor); gf_list_add(scene->root_od->term->x3d_sensors, node); }
void gf_inline_on_modified(GF_Node *node) { u32 ODID; GF_MediaObject *mo; M_Inline *pInline = (M_Inline *) node; GF_Scene *scene = (GF_Scene *)gf_node_get_private(node); ODID = gf_mo_get_od_id(&pInline->url); if (scene) { mo = (scene->root_od) ? scene->root_od->mo : NULL; /*disconnect current inline if we're the last one using it (same as regular OD session leave/join)*/ if (mo) { Bool changed = 1; if (ODID != GF_MEDIA_EXTERNAL_ID) { if (ODID && (ODID==scene->root_od->OD->objectDescriptorID)) changed = 0; } else { if (gf_mo_is_same_url(mo, &pInline->url, NULL, 0) ) changed = 0; } if (mo->num_open) { if (!changed) return; gf_scene_notify_event(scene, GF_EVENT_UNLOAD, node, NULL, GF_OK); gf_node_dirty_parents(node); gf_list_del_item(mo->nodes, node); /*reset the scene pointer as it may get destroyed*/ switch (gf_node_get_tag(node)) { case TAG_MPEG4_Inline: #ifndef GPAC_DISABLE_X3D case TAG_X3D_Inline: #endif gf_node_set_private(node, NULL); break; } mo->num_open --; if (!mo->num_open) { if (ODID == GF_MEDIA_EXTERNAL_ID) { GF_Scene *parent = scene->root_od->parentscene; /*!!! THIS WILL DESTROY THE INLINE SCENE OBJECT !!!*/ gf_odm_disconnect(scene->root_od, 1); /*and force removal of the media object*/ if (parent) { if (gf_list_del_item(parent->scene_objects, mo)>=0) { gf_sg_vrml_mf_reset(&mo->URLs, GF_SG_VRML_MFURL); gf_list_del(mo->nodes); gf_free(mo); } } } else { gf_term_lock_media_queue(scene->root_od->term, 1); /*external media are completely unloaded*/ if (scene->root_od->OD->objectDescriptorID==GF_MEDIA_EXTERNAL_ID) { scene->root_od->action_type = GF_ODM_ACTION_DELETE; } else { scene->root_od->action_type = GF_ODM_ACTION_STOP; } if (gf_list_find(scene->root_od->term->media_queue, scene->root_od)<0) gf_list_add(scene->root_od->term->media_queue, scene->root_od); gf_term_lock_media_queue(scene->root_od->term, 0); } } } } } else { gf_node_dirty_parents(node); } if (ODID) gf_inline_set_scene(pInline); }
static void svg2bifs_node_start(void *sax_cbck, const char *name, const char *name_space, const GF_XMLAttribute *attributes, u32 nb_attributes) { u32 i; SVG2BIFS_Converter *converter = (SVG2BIFS_Converter *)sax_cbck; SVGPropertiesPointers *backup_props; char *id_string = NULL; u32 tag; SVG_Element *elt; SVG_DeferedAnimation *anim = NULL; tag = gf_xml_get_element_tag(name, 0); elt = (SVG_Element*)gf_node_new(converter->svg_sg, tag); if (!gf_sg_get_root_node(converter->svg_sg)) { gf_node_register((GF_Node *)elt, NULL); gf_sg_set_root_node(converter->svg_sg, (GF_Node *)elt); } else { gf_node_register((GF_Node *)elt, converter->svg_parent); //gf_node_list_add_child(&((GF_ParentNode*)converter->svg_parent)->children, (GF_Node *)elt); } // fprintf(stdout, "Converting %s\n", gf_node_get_class_name((GF_Node *)elt)); // if (converter->bifs_parent) fprintf(stdout, "%s\n", gf_node_get_class_name(converter->bifs_parent)); if (gf_svg_is_animation_tag(tag)) { GF_SAFEALLOC(anim, SVG_DeferedAnimation); /*default anim target is parent node*/ anim->animation_elt = elt; if (converter->svg_parent) { anim->target = anim->anim_parent = (SVG_Element*) converter->svg_parent; } } for (i=0; i<nb_attributes; i++) { GF_XMLAttribute *att = (GF_XMLAttribute *)&attributes[i]; if (!att->value || !strlen(att->value)) continue; if (!stricmp(att->name, "style")) { gf_svg_parse_style((GF_Node *)elt, att->value); } else if (!stricmp(att->name, "id") || !stricmp(att->name, "xml:id")) { gf_svg_parse_element_id((GF_Node *)elt, att->value, 0); id_string = att->value; } else if (anim && !stricmp(att->name, "to")) { anim->to = gf_strdup(att->value); } else if (anim && !stricmp(att->name, "from")) { anim->from = gf_strdup(att->value); } else if (anim && !stricmp(att->name, "by")) { anim->by = gf_strdup(att->value); } else if (anim && !stricmp(att->name, "values")) { anim->values = gf_strdup(att->value); } else if (anim && (tag == TAG_SVG_animateTransform) && !stricmp(att->name, "type")) { anim->type = gf_strdup(att->value); } else { GF_FieldInfo info; if (gf_node_get_field_by_name((GF_Node *)elt, att->name, &info)==GF_OK) { gf_svg_parse_attribute((GF_Node *)elt, &info, att->value, 0); } else { fprintf(stdout, "Skipping attribute %s\n", att->name); } } } if (anim) { svg_parse_animation(converter->svg_sg, anim); } memset(&converter->all_atts, 0, sizeof(SVGAllAttributes)); gf_svg_flatten_attributes(elt, &converter->all_atts); backup_props = gf_malloc(sizeof(SVGPropertiesPointers)); memcpy(backup_props, &converter->svg_props, sizeof(SVGPropertiesPointers)); gf_node_set_private((GF_Node *)elt, backup_props); gf_svg_apply_inheritance(&converter->all_atts, &converter->svg_props); fprintf(stdout, "START\t%s\t%s\t%s", converter->svg_parent ? gf_node_get_class_name(converter->svg_parent) : "none", converter->bifs_parent ? gf_node_get_class_name(converter->bifs_parent) : "none", name); converter->svg_parent = (GF_Node *)elt; if (!gf_sg_get_root_node(converter->bifs_sg)) { if (tag == TAG_SVG_svg) { GF_Node *node, *child; converter->bifs_sg->usePixelMetrics = 1; if (converter->all_atts.width && converter->all_atts.width->type == SVG_NUMBER_VALUE) { converter->bifs_sg->width = FIX2INT(converter->all_atts.width->value); } else { converter->bifs_sg->width = 320; } if (converter->all_atts.height && converter->all_atts.height->type == SVG_NUMBER_VALUE) { converter->bifs_sg->height = FIX2INT(converter->all_atts.height->value); } else { converter->bifs_sg->height = 200; } node = gf_node_new(converter->bifs_sg, TAG_MPEG4_OrderedGroup); gf_node_register(node, NULL); gf_sg_set_root_node(converter->bifs_sg, node); child = gf_node_new(converter->bifs_sg, TAG_MPEG4_QuantizationParameter); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); { M_QuantizationParameter *qp = (M_QuantizationParameter *)child; qp->useEfficientCoding = 1; } /* SVG to BIFS coordinate transformation */ child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Viewport); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); { M_Viewport *vp = (M_Viewport*)child; if (converter->all_atts.viewBox) { vp->size.x = converter->all_atts.viewBox->width; vp->size.y = converter->all_atts.viewBox->height; vp->position.x = converter->all_atts.viewBox->x+converter->all_atts.viewBox->width/2; vp->position.y = -(converter->all_atts.viewBox->y+converter->all_atts.viewBox->height/2); } else { vp->size.x = INT2FIX(converter->bifs_sg->width); vp->size.y = INT2FIX(converter->bifs_sg->height); vp->position.x = INT2FIX(converter->bifs_sg->width)/2; vp->position.y = -INT2FIX(converter->bifs_sg->height)/2; } } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Background2D); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); { M_Background2D *b = (M_Background2D *)child; b->backColor.red = FIX_ONE; b->backColor.green = FIX_ONE; b->backColor.blue = FIX_ONE; } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; { M_Transform2D *tr = (M_Transform2D *)node; tr->scale.y = -FIX_ONE; } converter->bifs_parent = node; } } else { GF_Node *node, *child; node = converter->bifs_parent; switch(tag) { case TAG_SVG_g: { if (converter->all_atts.transform) { node = add_transform_matrix(converter, node); converter->bifs_parent = node; } else { M_Group *g = (M_Group*)gf_node_new(converter->bifs_sg, TAG_MPEG4_Group); gf_node_register((GF_Node *)g, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, (GF_Node *)g); node = (GF_Node *)g; converter->bifs_parent = node; } } break; case TAG_SVG_rect: { Bool is_parent_set = 0; if (converter->all_atts.transform) { node = add_transform_matrix(converter, node); converter->bifs_parent = node; is_parent_set = 1; } if (converter->force_transform) { node = add_transform2d(converter, node); if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } } if (converter->all_atts.x || converter->all_atts.y) { child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } { M_Transform2D *tr = (M_Transform2D *)node; if (converter->all_atts.x) tr->translation.x = converter->all_atts.x->value + (converter->all_atts.width?converter->all_atts.width->value/2:0); if (converter->all_atts.y) tr->translation.y = converter->all_atts.y->value + (converter->all_atts.height?converter->all_atts.height->value/2:0); } } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; if (!is_parent_set) converter->bifs_parent = node; { M_Shape *shape = (M_Shape *)node; shape->geometry = gf_node_new(converter->bifs_sg, TAG_MPEG4_Rectangle); gf_node_register(shape->geometry, (GF_Node *)shape); { M_Rectangle *rect = (M_Rectangle *)shape->geometry; if (converter->all_atts.width) rect->size.x = converter->all_atts.width->value; if (converter->all_atts.height) rect->size.y = converter->all_atts.height->value; } shape->appearance = create_appearance(&converter->svg_props, converter->bifs_sg); gf_node_register(shape->appearance, (GF_Node *)shape); } } break; case TAG_SVG_path: { Bool is_parent_set = 0; if (converter->all_atts.transform) { node = add_transform_matrix(converter, node); converter->bifs_parent = node; is_parent_set = 1; } if (converter->force_transform) { node = add_transform2d(converter, node); if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } } if (converter->all_atts.x || converter->all_atts.y) { child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } { M_Transform2D *tr = (M_Transform2D *)node; if (converter->all_atts.x) tr->translation.x = converter->all_atts.x->value; if (converter->all_atts.y) tr->translation.y = converter->all_atts.y->value; } } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; if (!is_parent_set) converter->bifs_parent = node; { M_Shape *shape = (M_Shape *)node; shape->geometry = gf_node_new(converter->bifs_sg, TAG_MPEG4_XCurve2D); gf_node_register(shape->geometry, (GF_Node *)shape); if (converter->all_atts.d) { M_Coordinate2D *c2d; M_XCurve2D *xc = (M_XCurve2D *)shape->geometry; u32 i, j, c, k; xc->point = gf_node_new(converter->bifs_sg, TAG_MPEG4_Coordinate2D); c2d = (M_Coordinate2D *)xc->point; gf_node_register(xc->point, (GF_Node *)xc); gf_sg_vrml_mf_alloc(&c2d->point, GF_SG_VRML_MFVEC2F, converter->all_atts.d->n_points); gf_sg_vrml_mf_alloc(&xc->type, GF_SG_VRML_MFINT32, converter->all_atts.d->n_points); c = 0; k = 0; j = 0; c2d->point.vals[k] = converter->all_atts.d->points[0]; k++; xc->type.vals[0] = 0; for (i = 1; i < converter->all_atts.d->n_points; ) { switch(converter->all_atts.d->tags[i]) { case GF_PATH_CURVE_ON: c2d->point.vals[k] = converter->all_atts.d->points[i]; k++; if (i-1 == converter->all_atts.d->contours[c]) { xc->type.vals[j] = 0; c++; } else { xc->type.vals[j] = 1; } i++; break; case GF_PATH_CURVE_CUBIC: c2d->point.vals[k] = converter->all_atts.d->points[i]; c2d->point.vals[k+1] = converter->all_atts.d->points[i+1]; c2d->point.vals[k+2] = converter->all_atts.d->points[i+2]; k+=3; xc->type.vals[j] = 2; if (converter->all_atts.d->tags[i+2]==GF_PATH_CLOSE) { j++; xc->type.vals[j] = 6; } i+=3; break; case GF_PATH_CLOSE: xc->type.vals[j] = 6; i++; break; case GF_PATH_CURVE_CONIC: c2d->point.vals[k] = converter->all_atts.d->points[i]; c2d->point.vals[k+1] = converter->all_atts.d->points[i+1]; k+=2; xc->type.vals[j] = 7; if (converter->all_atts.d->tags[i+1]==GF_PATH_CLOSE) { j++; xc->type.vals[j] = 6; } i+=2; break; } j++; } xc->type.count = j; c2d->point.count = k; } shape->appearance = create_appearance(&converter->svg_props, converter->bifs_sg); gf_node_register(shape->appearance, (GF_Node *)shape); } } break; case TAG_SVG_polyline: { Bool is_parent_set = 0; if (converter->all_atts.transform) { node = add_transform_matrix(converter, node); converter->bifs_parent = node; is_parent_set = 1; } if (converter->force_transform) { node = add_transform2d(converter, node); if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; if (!is_parent_set) converter->bifs_parent = node; { M_Shape *shape = (M_Shape *)node; shape->geometry = gf_node_new(converter->bifs_sg, TAG_MPEG4_IndexedFaceSet2D); gf_node_register(shape->geometry, (GF_Node *)shape); if (converter->all_atts.points) { M_Coordinate2D *c2d; M_IndexedFaceSet2D *ifs = (M_IndexedFaceSet2D *)shape->geometry; u32 i; ifs->coord = gf_node_new(converter->bifs_sg, TAG_MPEG4_Coordinate2D); c2d = (M_Coordinate2D *)ifs->coord; gf_node_register(ifs->coord, (GF_Node *)ifs); gf_sg_vrml_mf_alloc(&c2d->point, GF_SG_VRML_MFVEC2F, gf_list_count(*converter->all_atts.points)); for (i = 0; i < gf_list_count(*converter->all_atts.points); i++) { SVG_Point *p = (SVG_Point *)gf_list_get(*converter->all_atts.points, i); c2d->point.vals[i].x = p->x; c2d->point.vals[i].y = p->y; } } shape->appearance = create_appearance(&converter->svg_props, converter->bifs_sg); gf_node_register(shape->appearance, (GF_Node *)shape); } } break; case TAG_SVG_text: { Bool is_parent_set = 0; if (converter->all_atts.transform) { node = add_transform_matrix(converter, node); converter->bifs_parent = node; is_parent_set = 1; } if (converter->force_transform) { node = add_transform2d(converter, node); if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); { M_Transform2D *tr = (M_Transform2D *)child; if (converter->all_atts.text_x) tr->translation.x = ((SVG_Coordinate *)gf_list_get(*converter->all_atts.text_x, 0))->value; if (converter->all_atts.text_y) tr->translation.y = ((SVG_Coordinate *)gf_list_get(*converter->all_atts.text_y, 0))->value; tr->scale.y = -FIX_ONE; } node = child; child = NULL; if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; if (!is_parent_set) converter->bifs_parent = node; { M_FontStyle *fs; M_Text *text; M_Shape *shape = (M_Shape *)node; text = (M_Text *)gf_node_new(converter->bifs_sg, TAG_MPEG4_Text); shape->geometry = (GF_Node *)text; converter->bifs_text_node = shape->geometry; gf_node_register(shape->geometry, (GF_Node *)shape); fs = (M_FontStyle *)gf_node_new(converter->bifs_sg, TAG_MPEG4_XFontStyle); gf_node_register((GF_Node *)fs, (GF_Node*)text); text->fontStyle = (GF_Node *)fs; gf_sg_vrml_mf_alloc(&fs->family, GF_SG_VRML_MFSTRING, 1); fs->family.vals[0] = gf_strdup(converter->svg_props.font_family->value); fs->size = converter->svg_props.font_size->value; shape->appearance = create_appearance(&converter->svg_props, converter->bifs_sg); gf_node_register(shape->appearance, (GF_Node *)shape); } } break; case TAG_SVG_ellipse: case TAG_SVG_circle: { Bool is_parent_set = 0; if (converter->all_atts.transform) { node = add_transform_matrix(converter, node); converter->bifs_parent = node; is_parent_set = 1; } if (converter->force_transform) { node = add_transform2d(converter, node); if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } } if (converter->all_atts.cx || converter->all_atts.cy) { child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); { M_Transform2D *tr = (M_Transform2D *)child; if (converter->all_atts.cx) tr->translation.x = converter->all_atts.cx->value; if (converter->all_atts.cy) tr->translation.y = converter->all_atts.cy->value; } node = child; child = NULL; if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; if (!is_parent_set) converter->bifs_parent = node; { M_Shape *shape = (M_Shape *)node; if (tag == TAG_SVG_ellipse) { M_Ellipse *e = (M_Ellipse *)gf_node_new(converter->bifs_sg, TAG_MPEG4_Ellipse); shape->geometry = (GF_Node *)e; e->radius.x = converter->all_atts.rx->value; e->radius.y = converter->all_atts.ry->value; } else { M_Circle *c = (M_Circle *)gf_node_new(converter->bifs_sg, TAG_MPEG4_Circle); shape->geometry = (GF_Node *)c; c->radius = converter->all_atts.r->value; } gf_node_register(shape->geometry, (GF_Node *)shape); shape->appearance = create_appearance(&converter->svg_props, converter->bifs_sg); gf_node_register(shape->appearance, (GF_Node *)shape); } } break; case TAG_SVG_defs: { child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Switch); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; { M_Switch *sw = (M_Switch *)node; sw->whichChoice = -1; } converter->bifs_parent = node; } break; case TAG_SVG_solidColor: { child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; converter->bifs_parent = node; } break; case TAG_SVG_animateTransform: { GF_Node *child_ts; if (!gf_node_get_id(node)) { gf_node_set_id(node, gf_sg_get_next_available_node_id(converter->bifs_sg), NULL); } child_ts = gf_node_new(converter->bifs_sg, TAG_MPEG4_TimeSensor); if (!gf_node_get_id(child_ts)) { gf_node_set_id(child_ts, gf_sg_get_next_available_node_id(converter->bifs_sg), NULL); } gf_node_register(child_ts, node); gf_node_list_add_child(&((GF_ParentNode *)node)->children, child_ts); { M_TimeSensor *ts = (M_TimeSensor *)child_ts; if (converter->all_atts.dur) { ts->cycleInterval = converter->all_atts.dur->clock_value; } if (converter->all_atts.repeatCount && converter->all_atts.repeatCount->type == SMIL_REPEATCOUNT_INDEFINITE) { ts->loop = 1; } } if (converter->all_atts.transform_type) { GF_FieldInfo fromField, toField; switch (*converter->all_atts.transform_type) { case SVG_TRANSFORM_ROTATE: child = gf_node_new(converter->bifs_sg, TAG_MPEG4_PositionInterpolator2D); if (!gf_node_get_id(child)) { gf_node_set_id(child, gf_sg_get_next_available_node_id(converter->bifs_sg), NULL); } gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode *)node)->children, child); gf_node_get_field_by_name(child_ts, "fraction_changed", &fromField); gf_node_get_field_by_name(child, "set_fraction", &toField); gf_sg_route_new(converter->bifs_sg, child_ts, fromField.fieldIndex, child, toField.fieldIndex); gf_node_get_field_by_name(child, "value_changed", &fromField); gf_node_get_field_by_name(node, "rotationAngle", &toField); gf_sg_route_new(converter->bifs_sg, child, fromField.fieldIndex, node, toField.fieldIndex); { M_PositionInterpolator2D *pi2d = (M_PositionInterpolator2D *)child; if (converter->all_atts.keyTimes) { SFFloat *g; u32 count, i; count = gf_list_count(*converter->all_atts.keyTimes); for (i = 0; i < count; i++) { Fixed *f = gf_list_get(*converter->all_atts.keyTimes, i); gf_sg_vrml_mf_append(&pi2d->key, GF_SG_VRML_MFFLOAT, &g); *g = *f; } } if (converter->all_atts.values) { SFVec2f *g; u32 count, i; count = gf_list_count(converter->all_atts.values->values); for (i = 0; i < count; i++) { SVG_Point_Angle *p; p = gf_list_get(converter->all_atts.values->values, i); gf_sg_vrml_mf_append(&pi2d->keyValue, GF_SG_VRML_MFVEC2F, &g); g->x = p->x; g->y = p->y; } } } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_ScalarInterpolator); if (!gf_node_get_id(child)) { gf_node_set_id(child, gf_sg_get_next_available_node_id(converter->bifs_sg), NULL); } gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode *)node)->children, child); gf_node_get_field_by_name(child_ts, "fraction_changed", &fromField); gf_node_get_field_by_name(child, "set_fraction", &toField); gf_sg_route_new(converter->bifs_sg, child_ts, fromField.fieldIndex, child, toField.fieldIndex); gf_node_get_field_by_name(child, "value_changed", &fromField); gf_node_get_field_by_name(node, "center", &toField); gf_sg_route_new(converter->bifs_sg, child, fromField.fieldIndex, node, toField.fieldIndex); { M_ScalarInterpolator *si = (M_ScalarInterpolator *)child; if (converter->all_atts.keyTimes) { SFFloat *g; u32 count, i; count = gf_list_count(*converter->all_atts.keyTimes); for (i = 0; i < count; i++) { Fixed *f = gf_list_get(*converter->all_atts.keyTimes, i); gf_sg_vrml_mf_append(&si->key, GF_SG_VRML_MFFLOAT, &g); *g = *f; } } if (converter->all_atts.values) { SFFloat *g; u32 count, i; count = gf_list_count(converter->all_atts.values->values); for (i = 0; i < count; i++) { SVG_Point_Angle *p; p = gf_list_get(converter->all_atts.values->values, i); gf_sg_vrml_mf_append(&si->keyValue, GF_SG_VRML_MFFLOAT, &g); *g = p->angle; } } } break; case SVG_TRANSFORM_SCALE: case SVG_TRANSFORM_TRANSLATE: child = gf_node_new(converter->bifs_sg, TAG_MPEG4_PositionInterpolator2D); if (!gf_node_get_id(child)) { gf_node_set_id(child, gf_sg_get_next_available_node_id(converter->bifs_sg), NULL); } gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode *)node)->children, child); gf_node_get_field_by_name(child_ts, "fraction_changed", &fromField); gf_node_get_field_by_name(child, "set_fraction", &toField); gf_sg_route_new(converter->bifs_sg, child_ts, fromField.fieldIndex, child, toField.fieldIndex); gf_node_get_field_by_name(child, "value_changed", &fromField); if (*converter->all_atts.transform_type == SVG_TRANSFORM_SCALE) gf_node_get_field_by_name(node, "scale", &toField); else gf_node_get_field_by_name(node, "translation", &toField); gf_sg_route_new(converter->bifs_sg, child, fromField.fieldIndex, node, toField.fieldIndex); { M_PositionInterpolator2D *pi2d = (M_PositionInterpolator2D *)child; if (converter->all_atts.keyTimes) { SFFloat *g; u32 count, i; count = gf_list_count(*converter->all_atts.keyTimes); for (i = 0; i < count; i++) { Fixed *f = gf_list_get(*converter->all_atts.keyTimes, i); gf_sg_vrml_mf_append(&pi2d->key, GF_SG_VRML_MFFLOAT, &g); *g = *f; } } if (converter->all_atts.values) { SFVec2f *g; u32 count, i; count = gf_list_count(converter->all_atts.values->values); for (i = 0; i < count; i++) { SVG_Point *p; p = gf_list_get(converter->all_atts.values->values, i); gf_sg_vrml_mf_append(&pi2d->keyValue, GF_SG_VRML_MFVEC2F, &g); g->x = p->x; g->y = p->y; } } } break; default: fprintf(stdout, "Warning: transformation type not supported \n"); } } //converter->bifs_parent = node; } break; default: { fprintf(stdout, "Warning: element %s not supported \n", gf_node_get_class_name((GF_Node *)elt)); child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D); gf_node_register(child, node); //gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; converter->bifs_parent = node; } break; } if (id_string) gf_node_set_id(converter->bifs_parent, gf_sg_get_next_available_node_id(converter->bifs_sg), NULL);//gf_node_get_name((GF_Node *)elt)); } fprintf(stdout, "\t%s\n", converter->bifs_parent ? gf_node_get_class_name(converter->bifs_parent) : "none"); }
void gf_term_on_node_init(void *_scene, GF_Node *node) { GF_Scene *scene = (GF_Scene *)_scene; if (!node || !scene) return; switch (gf_node_get_tag(node)) { #ifndef GPAC_DISABLE_VRML case TAG_MPEG4_Inline: #ifndef GPAC_DISABLE_X3D case TAG_X3D_Inline: #endif gf_init_inline(scene, node); break; case TAG_MPEG4_MediaBuffer: break; case TAG_MPEG4_MediaControl: InitMediaControl(scene, node); break; case TAG_MPEG4_MediaSensor: InitMediaSensor(scene, node); break; case TAG_MPEG4_InputSensor: InitInputSensor(scene, node); break; /*BIFS nodes, get back to codec, but filter externProtos*/ case TAG_MPEG4_Conditional: break; case TAG_MPEG4_QuantizationParameter: break; /*world info is stored at the inline scene level*/ case TAG_MPEG4_WorldInfo: #ifndef GPAC_DISABLE_X3D case TAG_X3D_WorldInfo: #endif gf_node_set_callback_function(node, TraverseWorldInfo); gf_node_set_private(node, scene); break; #ifndef GPAC_DISABLE_X3D case TAG_X3D_KeySensor: InitKeySensor(scene, node); break; case TAG_X3D_StringSensor: InitStringSensor(scene, node); break; #endif case TAG_MPEG4_TermCap: InitTermCap(scene, node); break; case TAG_MPEG4_Storage: gf_scene_init_storage(scene, node); break; case TAG_MPEG4_KeyNavigator: gf_node_set_callback_function(node, TraverseKeyNavigator); gf_node_set_private(node, scene); gf_list_add(scene->keynavigators, node); ((M_KeyNavigator*)node)->on_setFocus = on_kn_set_focus; break; #endif #ifndef GPAC_DISABLE_SVG case TAG_SVG_title: gf_node_set_callback_function(node, svg_traverse_title); gf_node_set_private(node, scene); break; #endif default: gf_sc_on_node_init(scene->root_od->term->compositor, node); break; } }
void gf_inline_on_modified(GF_Node *node) { u32 ODID; GF_MediaObject *mo; M_Inline *pInline = (M_Inline *) node; GF_Scene *scene = (GF_Scene *)gf_node_get_private(node); ODID = gf_mo_get_od_id(&pInline->url); if (scene) { mo = (scene->root_od) ? scene->root_od->mo : NULL; /*disconnect current inline if we're the last one using it (same as regular OD session leave/join)*/ if (mo) { Bool changed = GF_TRUE; if (ODID != GF_MEDIA_EXTERNAL_ID) { if (ODID && (ODID==scene->root_od->OD->objectDescriptorID)) changed = GF_FALSE; } else { if (gf_mo_is_same_url(mo, &pInline->url, NULL, 0) ) changed = GF_FALSE; } if (mo->num_open) { if (!changed) return; gf_scene_notify_event(scene, GF_EVENT_UNLOAD, node, NULL, GF_OK, GF_TRUE); gf_node_dirty_parents(node); gf_mo_event_target_remove_by_node(mo, node); /*reset the scene pointer as it may get destroyed*/ switch (gf_node_get_tag(node)) { case TAG_MPEG4_Inline: #ifndef GPAC_DISABLE_X3D case TAG_X3D_Inline: #endif gf_node_set_private(node, NULL); break; } mo->num_open --; if (!mo->num_open) { if (ODID == GF_MEDIA_EXTERNAL_ID) { GF_Scene *parent = scene->root_od->parentscene; /*!!! THIS WILL DESTROY THE INLINE SCENE OBJECT !!!*/ gf_odm_disconnect(scene->root_od, GF_TRUE); /*and force removal of the media object*/ if (parent) { if (gf_list_del_item(parent->scene_objects, mo)>=0) { gf_sg_vrml_mf_reset(&mo->URLs, GF_SG_VRML_MFURL); gf_mo_del(mo); } } } else { gf_term_lock_media_queue(scene->root_od->term, GF_TRUE); /*external media are completely unloaded, except addons which are only declared once */ if (!scene->root_od->addon && (scene->root_od->OD->objectDescriptorID==GF_MEDIA_EXTERNAL_ID)) { scene->root_od->action_type = GF_ODM_ACTION_DELETE; } else { scene->root_od->action_type = GF_ODM_ACTION_STOP; } if (gf_list_find(scene->root_od->term->media_queue, scene->root_od)<0) gf_list_add(scene->root_od->term->media_queue, scene->root_od); gf_term_lock_media_queue(scene->root_od->term, GF_FALSE); } } } } } /*force a redraw and load scene at next pass - we cannot load the scene now because - we can be in a JS call (eg JS mutex blocked) - locating scene objects matching the new url needs exclusive access to the MediaObject list, achieved with the term net mutex - another service may already be setting up objects (eg exclusive access to the net mutex grabbed), which can trigger event forwarding - some event forwarders may request JS context (eg access to JS mutex) In such a case we would end up in a deadlock - this needs urgent fixing ... */ if (ODID) { /*if no parent we must process the url change as we may not be traversed later on (not in the scene tree)*/ if (gf_node_get_parent(node, 0)==NULL) { gf_inline_set_scene(pInline); } else { gf_node_dirty_parents(node); } } }