Exemple #1
0
static GF_MediaObject *get_sync_reference(GF_Scene *scene, XMLRI *iri, u32 o_type, GF_Node *orig_ref, Bool *post_pone)
{
	MFURL mfurl;
	SFURL sfurl;
	GF_MediaObject *res;
	GF_Node *ref = NULL;

	u32 stream_id = 0;
	if (iri->type==XMLRI_STREAMID) {
		stream_id = iri->lsr_stream_id;
	} else if (!iri->string) {
		return NULL;
	} else {
		if (iri->target) ref = iri->target;
		else if (iri->string[0]=='#') ref = gf_sg_find_node_by_name(scene->graph, iri->string+1);
		else ref = gf_sg_find_node_by_name(scene->graph, iri->string);

		if (ref) {
#ifndef GPAC_DISABLE_SVG
			GF_FieldInfo info;
#endif
			/*safety check, break cyclic references*/
			if (ref==orig_ref) return NULL;

			switch (ref->sgprivate->tag) {
#ifndef GPAC_DISABLE_SVG
			case TAG_SVG_audio:
				o_type = GF_MEDIA_OBJECT_AUDIO; 
				if (gf_node_get_attribute_by_tag(ref, TAG_XLINK_ATT_href, 0, 0, &info)==GF_OK) {
					return get_sync_reference(scene, info.far_ptr, o_type, orig_ref ? orig_ref : ref, post_pone);
				}
				return NULL;
			case TAG_SVG_video:
				o_type = GF_MEDIA_OBJECT_VIDEO; 
				if (gf_node_get_attribute_by_tag(ref, TAG_XLINK_ATT_href, 0, 0, &info)==GF_OK) {
					return get_sync_reference(scene, info.far_ptr, o_type, orig_ref ? orig_ref : ref, post_pone);
				}
				return NULL;
#endif
			default:
				return NULL;
			}
		}
	}
	*post_pone = 0;
	mfurl.count = 1;
	mfurl.vals = &sfurl;
	mfurl.vals[0].OD_ID = stream_id;
	mfurl.vals[0].url = iri->string;

	res = gf_scene_get_media_object(scene, &mfurl, o_type, 0);
	if (!res) *post_pone = 1;
	return res;
}
Exemple #2
0
GF_Node *gf_xml_node_clone(GF_SceneGraph *inScene, GF_Node *orig, GF_Node *cloned_parent, char *inst_id, Bool deep)
{
	GF_DOMAttribute *att;
	GF_Node *clone = gf_node_new(inScene, orig->sgprivate->tag);
	if (!clone) return NULL;

	if (orig->sgprivate->tag == TAG_DOMText) {
		GF_DOMText *n_src,*n_dst;
		n_src = (GF_DOMText *)orig;
		n_dst = (GF_DOMText *)clone;
		n_dst->type = n_src->type;
		n_dst->textContent = gf_strdup(n_src->textContent);
	} else {
		if (orig->sgprivate->tag == TAG_DOMFullNode) {
			GF_DOMFullNode *n_src,*n_dst;
			n_src = (GF_DOMFullNode *)orig;
			n_dst = (GF_DOMFullNode *)clone;
			n_dst->ns = n_src->ns;
			n_dst->name = gf_strdup(n_dst->name);
		} 
		
		att = ((GF_DOMNode *)orig)->attributes;
		while (att) {
			GF_FieldInfo dst, src;
			/*create by name*/
			if (att->tag==TAG_DOM_ATT_any) {
				gf_node_get_attribute_by_name(clone, ((GF_DOMFullAttribute*)att)->name, 0, 1, 0, &dst);
			} else {
				gf_node_get_attribute_by_tag(clone, att->tag, 1, 0, &dst);
			}
			src.far_ptr = att->data;
			src.fieldType = att->data_type;
			src.fieldIndex = att->tag;
			gf_svg_attributes_copy(&dst, &src, 0);
			if (att->tag==TAG_XLINK_ATT_href) {
				XMLRI *iri = (XMLRI *)att->data;
				if (iri->target == gf_node_get_parent(orig, 0)) {
					((XMLRI *)dst.far_ptr)->target = cloned_parent;
				} else {
					((XMLRI *)dst.far_ptr)->target = NULL;
				}
			}
			att = att->next;
		}	
	}
	if (cloned_parent) {
		gf_node_list_add_child( & ((GF_ParentNode*)cloned_parent)->children, clone);
		gf_node_register(clone, cloned_parent);
		/*TO CLARIFY: can we init the node right now or should we wait for insertion in the scene tree ?*/
		gf_node_init(clone);
	}
	if (deep) {
		GF_ChildNodeItem *child = ((GF_ParentNode *)orig)->children;
		while (child) {
			gf_node_clone(inScene, child->node, clone, inst_id, 1);
			child = child->next;
		}
	}
	return clone;
}
Exemple #3
0
void VTT_load_script(VTTDec *vttdec, GF_SceneGraph *graph)
{
	GF_Node *n, *root;
	GF_FieldInfo info;
	const char *path;
	FILE *jsfile;

	if (!graph) return;
	gf_sg_add_namespace(graph, "http://www.w3.org/2000/svg", NULL);
	gf_sg_add_namespace(graph, "http://www.w3.org/1999/xlink", "xlink");
	gf_sg_add_namespace(graph, "http://www.w3.org/2001/xml-events", "ev");
	gf_sg_set_scene_size_info(graph, 800, 600, GF_TRUE);

	/* modify the scene with an Inline/Animation pointing to the VTT Renderer */
	n = root = gf_node_new(graph, TAG_SVG_svg);
	gf_node_register(root, NULL);
	gf_sg_set_root_node(graph, root);
	gf_node_get_attribute_by_name(n, "xmlns", 0, GF_TRUE, GF_FALSE, &info);
	gf_svg_parse_attribute(n, &info, "http://www.w3.org/2000/svg", 0);
	VTT_UpdateSizeInfo(vttdec);
	gf_node_init(n);

	n = gf_node_new(graph, TAG_SVG_script);
	gf_node_register(n, root);
	gf_node_list_add_child(&((GF_ParentNode *)root)->children, n);
	path = gf_modules_get_option((GF_BaseInterface *)vttdec->module, "WebVTT", "RenderingScript");
	if (!path) {
		/* try to find the JS renderer in the default GPAC installation folder */
		const char *startuppath = gf_modules_get_option((GF_BaseInterface *)vttdec->module, "General", "StartupFile");
		path = gf_url_concatenate(startuppath, "webvtt-renderer.js");
		jsfile = gf_fopen(path, "rt");
		if (jsfile) {
			gf_modules_set_option((GF_BaseInterface *)vttdec->module, "WebVTT", "RenderingScript", path);
			gf_fclose(jsfile);
		} else {
			GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[WebVTT] Cannot find Rendering Script [WebVTT:RenderingScript] - check config file\n"));
			return;
		}
	}
	jsfile = gf_fopen(path, "rt");
	if (jsfile) {
		gf_fclose(jsfile);
		gf_node_get_attribute_by_tag(n, TAG_XLINK_ATT_href, GF_TRUE, GF_FALSE, &info);
		if (strstr(path, ":\\")) {
			gf_svg_parse_attribute(n, &info, (char *) path, 0);
		} else {
			char szPath[GF_MAX_PATH];
			strcpy(szPath, "file://");
			strcat(szPath, path);
			gf_svg_parse_attribute(n, &info, (char *) szPath, 0);
		}

		vttdec->has_rendering_script = GF_TRUE;
	} else {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[WebVTT] Cannot open Rendering Script - %s\n", path));
		return;
	}
	gf_node_init(n);

}
Exemple #4
0
void gf_svg_node_del(GF_Node *node)
{
	SVG_Element *p = (SVG_Element *)node;

	if (p->sgprivate->interact && p->sgprivate->interact->animations) {
		gf_smil_anim_delete_animations((GF_Node *)p);
	}
	if (p->sgprivate->tag==TAG_SVG_listener) {
		/*remove from target's listener list*/
		GF_DOMEventTarget *evt = node->sgprivate->UserPrivate;
		node->sgprivate->UserPrivate = NULL;
		if (evt) 
			gf_list_del_item(evt->evt_list, p);
#if 0
		if (evt && (gf_node_get_attribute_by_tag(p, TAG_XMLEV_ATT_event, 0, 0, &info) == GF_OK)) {
			u32 type = ((XMLEV_Event *)info.far_ptr)->type;
			gf_sg_unregister_event_type(p->sgprivate->scenegraph, gf_dom_event_get_category(type));
		}
#endif
	}
	/*if this is a handler with a UserPrivate, this is a handler with an implicit listener 
	(eg handler with ev:event=""). Destroy the associated listener*/
	if (p->sgprivate->tag==TAG_SVG_handler) {
		GF_Node *listener = p->sgprivate->UserPrivate;
		if (listener && (listener->sgprivate->tag==TAG_SVG_listener)) {
			gf_node_unregister(listener, NULL);
//			gf_svg_node_del(listener);
		}
	}
	/*remove this node from associated listeners*/
	if (node->sgprivate->interact && node->sgprivate->interact->dom_evt) {
		u32 i, count;
		count = gf_dom_listener_count(node);
		for (i=0; i<count; i++) {
			GF_Node *listener = gf_list_get(node->sgprivate->interact->dom_evt->evt_list, i);
			listener->sgprivate->UserPrivate = NULL;
		}
	}

	if (gf_svg_is_timing_tag(node->sgprivate->tag)) {
		SVGTimedAnimBaseElement *tap = (SVGTimedAnimBaseElement *)node;
		if (tap->animp) {
			gf_free(tap->animp);
			gf_smil_anim_remove_from_target((GF_Node *)tap, (GF_Node *)tap->xlinkp->href->target);
		}
		if (tap->timingp)		{
			gf_smil_timing_delete_runtime_info((GF_Node *)tap, tap->timingp->runtime);
			gf_free(tap->timingp);
		}	
		if (tap->xlinkp)	gf_free(tap->xlinkp);
	}

	gf_node_delete_attributes(node);
	gf_sg_parent_reset(node);
	gf_node_free(node);
}
Exemple #5
0
void gf_svg_node_del(GF_Node *node)
{
	SVG_Element *p = (SVG_Element *)node;

	if (p->sgprivate->interact && p->sgprivate->interact->animations) {
		gf_smil_anim_delete_animations((GF_Node *)p);
	}
	if (p->sgprivate->tag==TAG_SVG_listener) {
		/*remove from target's listener list*/
		gf_dom_event_remove_listener_from_parent((GF_DOMEventTarget *)node->sgprivate->UserPrivate, (GF_Node *)p);
	}
	/*if this is a handler with a UserPrivate, this is a handler with an implicit listener
	(eg handler with ev:event=""). Destroy the associated listener*/
	if (p->sgprivate->tag==TAG_SVG_handler) {
		GF_Node *listener = p->sgprivate->UserPrivate;
		if (listener && (listener->sgprivate->tag==TAG_SVG_listener)) {
			GF_FieldInfo info;
			if (gf_node_get_attribute_by_tag(listener, TAG_XMLEV_ATT_handler, 0, 0, &info) == GF_OK) {
				XMLRI *iri = (XMLRI *)info.far_ptr;
				if (iri->target) {
					assert(iri->target==p);
					iri->target = NULL;
				}
			}
			gf_node_unregister(listener, NULL);
//			gf_svg_node_del(listener);
		}
	}
	/*remove this node from associated listeners*/
	if (node->sgprivate->interact && node->sgprivate->interact->dom_evt) {
		u32 i, count;
		count = gf_dom_listener_count(node);
		for (i=0; i<count; i++) {
			GF_Node *listener = (GF_Node *)gf_list_get(node->sgprivate->interact->dom_evt->listeners, i);
			listener->sgprivate->UserPrivate = NULL;
		}
	}

	if (gf_svg_is_timing_tag(node->sgprivate->tag)) {
		SVGTimedAnimBaseElement *tap = (SVGTimedAnimBaseElement *)node;
		if (tap->animp) {
			gf_free(tap->animp);
			gf_smil_anim_remove_from_target((GF_Node *)tap, (GF_Node *)tap->xlinkp->href->target);
		}
		if (tap->timingp)		{
			gf_smil_timing_delete_runtime_info((GF_Node *)tap, tap->timingp->runtime);
			gf_free(tap->timingp);
		}
		if (tap->xlinkp)	gf_free(tap->xlinkp);
	}

	gf_node_delete_attributes(node);
	gf_sg_parent_reset(node);
	gf_node_free(node);
}
Exemple #6
0
GF_EXPORT
GF_Err gf_node_get_attribute_by_name(GF_Node *node, char *name, u32 xmlns_code, Bool create_if_not_found, Bool set_default, GF_FieldInfo *field)
{
	u32 attribute_tag = gf_xml_get_attribute_tag(node, name, xmlns_code);
	if (attribute_tag == TAG_DOM_ATT_any) {
		u32 len = 0;
		const char *ns = NULL;
		SVGAttribute *last_att = NULL;
		GF_DOMFullAttribute *att = (GF_DOMFullAttribute *) ((SVG_Element*)node)->attributes;
		if (xmlns_code) ns = gf_sg_get_namespace_qname(node->sgprivate->scenegraph, xmlns_code);
		if (ns) len = (u32) strlen(ns);

		while (att) {
			if (((u32) att->tag == TAG_DOM_ATT_any) && 
				((!ns && !strcmp(name, att->name)) || (ns && !strncmp(att->name, ns, len) && !strcmp(att->name+len+1, name)))
			) {
				field->fieldIndex = att->tag;
				field->fieldType = att->data_type;
				field->far_ptr = att->data;
				return GF_OK;
			}
			last_att = (SVGAttribute *) att;
			att = (GF_DOMFullAttribute *) att->next;
		}
		if (create_if_not_found) {
			GF_SAFEALLOC(att, GF_DOMFullAttribute);
			att->data_type = (u16) DOM_String_datatype;
			att->tag = (u16) TAG_DOM_ATT_any;
			att->data = gf_svg_create_attribute_value(att->data_type);

			att->name = gf_strdup(name);
			if (!xmlns_code)
				att->xmlns = gf_xml_get_element_namespace(node);
			else
				att->xmlns = xmlns_code;

			if (last_att) last_att->next = (SVGAttribute *)att;
			else ((SVG_Element*)node)->attributes = (SVGAttribute *)att;

			field->far_ptr = att->data;
			field->fieldType = att->data_type;
			field->fieldIndex = att->tag;
			return GF_OK;
		}
		return GF_NOT_SUPPORTED;
	}
	return gf_node_get_attribute_by_tag(node, attribute_tag, create_if_not_found, set_default, field);
}
Exemple #7
0
void VTT_UpdateSizeInfo(VTTDec *vttdec)
{
	u32 w, h;
	GF_FieldInfo info;
	char szVB[100];
	GF_Node *root = gf_sg_get_root_node(vttdec->sg);
	if (!root) return;
	w = vttdec->scene->root_od->term->compositor->display_width;
	h = vttdec->scene->root_od->term->compositor->display_height;

	w=1280;
	h=720;
	/*apply*/
	gf_sg_set_scene_size_info(vttdec->sg, w, h, GF_TRUE);

	sprintf(szVB, "0 0 %d %d", w, h);
	gf_node_get_attribute_by_tag(root, TAG_SVG_ATT_viewBox, GF_TRUE, GF_FALSE, &info);
	gf_svg_parse_attribute(root, &info, szVB, 0);

}
Exemple #8
0
GF_EXPORT
GF_Err gf_term_get_mfurl_from_xlink(GF_Node *node, MFURL *mfurl)
{
	u32 stream_id = 0;
	GF_Err e = GF_OK;
	SFURL *sfurl = NULL;
	GF_FieldInfo info;
	XMLRI *iri;
	GF_Scene *scene = gf_sg_get_private(gf_node_get_graph(node));
	if (!scene) return GF_BAD_PARAM;

	gf_sg_vrml_mf_reset(mfurl, GF_SG_VRML_MFURL);

	e = gf_node_get_attribute_by_tag(node, TAG_XLINK_ATT_href, 0, 0, &info);
	if (e) return e;

	iri = (XMLRI*)info.far_ptr;

	if (iri->type==XMLRI_STREAMID) {
		stream_id = iri->lsr_stream_id;
	} else if (!iri->string) return GF_OK;

	mfurl->count = 1;
	GF_SAFEALLOC(mfurl->vals, SFURL)
	sfurl = mfurl->vals;
	sfurl->OD_ID = stream_id;
	if (stream_id) return GF_OK;

	if (!strncmp(iri->string, "data:", 5)) {
		const char *cache_dir = gf_cfg_get_key(scene->root_od->term->user->config, "General", "CacheDirectory");
		e = gf_node_store_embedded_data(iri, cache_dir, "embedded_");
		if (e) return e;
		sfurl->url = gf_strdup(iri->string);
		return GF_OK;
	}
	sfurl->url = gf_term_resolve_xlink(node, iri->string);
	return e;
}
Exemple #9
0
char *gf_term_resolve_xlink(GF_Node *node, char *the_url)
{
	char *url;
	GF_Scene *scene = gf_sg_get_private(gf_node_get_graph(node));
	if (!scene) return NULL;

	url = gf_strdup(the_url);
	/*apply XML:base*/
	while (node) {
		GF_FieldInfo info;
		if (gf_node_get_attribute_by_tag(node, TAG_XML_ATT_base, 0, 0, &info)==GF_OK) {
			char *new_url = gf_url_concatenate( ((XMLRI*)info.far_ptr)->string, url);
			if (new_url) {
				gf_free(url);
				url = new_url;
			}
		}
		node = gf_node_get_parent(node, 0);
	}

	/*if this is a fragment and no XML:BASE was found, this is a fragment of the current document*/
	if (url[0]=='#') return url;

	if (scene) {
		char *the_url;
		if (scene->redirect_xml_base) {
			the_url = gf_url_concatenate(scene->redirect_xml_base, url);
		} else {
//			the_url = gf_url_concatenate(is->root_od->net_service->url, url);
			/*the root url of a document should be "." if not specified, so that the final URL resolve happens only once
			at the service level*/
			the_url = gf_strdup(url);
		}
		gf_free(url);
		return the_url;
	}
	return url;
}
Exemple #10
0
GF_EXPORT
GF_MediaObject *gf_mo_register(GF_Node *node, MFURL *url, Bool lock_timelines, Bool force_new_res)
{
	u32 obj_type;
#ifndef GPAC_DISABLE_SVG
	Bool post_pone;
	GF_FieldInfo info;
#endif
	GF_Scene *scene;
	GF_MediaObject *res, *syncRef;
	GF_SceneGraph *sg = gf_node_get_graph(node);
	if (!sg) return NULL;
	scene = (GF_Scene*)gf_sg_get_private(sg);
	if (!scene) return NULL;

	syncRef = NULL;

	/*keep track of the kind of object expected if URL is not using OD scheme*/
	switch (gf_node_get_tag(node)) {
#ifndef GPAC_DISABLE_VRML
	/*MPEG-4 / VRML / X3D only*/
	case TAG_MPEG4_AudioClip:
	case TAG_MPEG4_AudioSource:
#ifndef GPAC_DISABLE_X3D
	case TAG_X3D_AudioClip:
#endif
		obj_type = GF_MEDIA_OBJECT_AUDIO;
		break;
	case TAG_MPEG4_SBVCAnimation:
	case TAG_MPEG4_AnimationStream:
		obj_type = GF_MEDIA_OBJECT_UPDATES;
		break;
	case TAG_MPEG4_BitWrapper:
		obj_type = GF_MEDIA_OBJECT_SCENE;
		break;
	case TAG_MPEG4_InputSensor:
		obj_type = GF_MEDIA_OBJECT_INTERACT;
		break;
	case TAG_MPEG4_Background2D:
	case TAG_MPEG4_Background:
	case TAG_MPEG4_ImageTexture:
	case TAG_MPEG4_CacheTexture:
	case TAG_MPEG4_MovieTexture:
#ifndef GPAC_DISABLE_X3D
	case TAG_X3D_Background:
	case TAG_X3D_ImageTexture:
	case TAG_X3D_MovieTexture:
#endif
		obj_type = GF_MEDIA_OBJECT_VIDEO;
		break;
	case TAG_MPEG4_Inline:
#ifndef GPAC_DISABLE_X3D
	case TAG_X3D_Inline:
#endif
		obj_type = GF_MEDIA_OBJECT_SCENE;
		break;
#endif /*GPAC_DISABLE_VRML*/

		/*SVG*/
#ifndef GPAC_DISABLE_SVG
	case TAG_SVG_audio:
		obj_type = GF_MEDIA_OBJECT_AUDIO;
		if (gf_node_get_attribute_by_tag(node, TAG_SVG_ATT_syncReference, GF_FALSE, GF_FALSE, &info)==GF_OK) {
			syncRef = get_sync_reference(scene, (XMLRI *)info.far_ptr, GF_MEDIA_OBJECT_UNDEF, node, &post_pone);
			/*syncRef is specified but doesn't exist yet, post-pone*/
			if (post_pone) return NULL;
		}
		break;
	case TAG_SVG_video:
		obj_type = GF_MEDIA_OBJECT_VIDEO;
		if (gf_node_get_attribute_by_tag(node, TAG_SVG_ATT_syncReference, GF_FALSE, GF_FALSE, &info)==GF_OK) {
			syncRef = get_sync_reference(scene, (XMLRI *)info.far_ptr, GF_MEDIA_OBJECT_UNDEF, node, &post_pone);
			/*syncRef is specified but doesn't exist yet, post-pone*/
			if (post_pone) return NULL;
		}
		break;
	case TAG_SVG_image:
		obj_type = GF_MEDIA_OBJECT_VIDEO;
		break;
	case TAG_SVG_foreignObject:
	case TAG_SVG_animation:
		obj_type = GF_MEDIA_OBJECT_SCENE;
		break;
	case TAG_LSR_updates:
		obj_type = GF_MEDIA_OBJECT_UPDATES;
		break;
#endif

	default:
		obj_type = GF_MEDIA_OBJECT_UNDEF;
		break;
	}

	/*move to primary resource handler*/
	while (scene->secondary_resource && scene->root_od->parentscene)
		scene = scene->root_od->parentscene;

	res = gf_scene_get_media_object_ex(scene, url, obj_type, lock_timelines, syncRef, force_new_res, node);
	return res;
}
Exemple #11
0
/* Attributes from the timed elements are not easy to use during runtime, 
   the runtime info is a set of easy to use structures. 
   This function initializes them (intervals, status ...) 
   and registers the element with the scenegraph */
GF_EXPORT
void gf_smil_timing_init_runtime_info(GF_Node *timed_elt)
{
	GF_SceneGraph *sg;
	SMIL_Timing_RTI *rti;
	SMILTimingAttributesPointers *timingp = NULL;
	u32 tag = gf_node_get_tag(timed_elt);
	SVGAllAttributes all_atts;
	SVGTimedAnimBaseElement *e = (SVGTimedAnimBaseElement *)timed_elt;

	gf_svg_flatten_attributes((SVG_Element *)e, &all_atts);
	e->timingp = gf_malloc(sizeof(SMILTimingAttributesPointers));
	e->timingp->begin		= all_atts.begin;
	e->timingp->clipBegin	= all_atts.clipBegin;
	e->timingp->clipEnd		= all_atts.clipEnd;
	e->timingp->dur			= all_atts.dur;
	e->timingp->end			= all_atts.end;
	e->timingp->fill		= all_atts.smil_fill;
	e->timingp->max			= all_atts.max;
	e->timingp->min			= all_atts.min;
	e->timingp->repeatCount = all_atts.repeatCount;
	e->timingp->repeatDur	= all_atts.repeatDur;
	e->timingp->restart		= all_atts.restart;
	timingp = e->timingp;
	if (!timingp) return;

	if (tag == TAG_SVG_audio || tag == TAG_SVG_video) {
		/* if the dur attribute is not set, then it should be set to media 
		   as this is the default for media elements see 
		   http://www.w3.org/TR/2005/REC-SMIL2-20051213/smil-timing.html#Timing-DurValueSemantics
		   "For simple media elements that specify continuous media (i.e. media with an inherent notion of time), 
		   the implicit duration is the intrinsic duration of the media itself - e.g. video and audio files 
		   have a defined duration."
		TODO: Check if this should work with the animation element */
		if (!e->timingp->dur) {
			GF_FieldInfo info;
			gf_node_get_attribute_by_tag((GF_Node *)e, TAG_SVG_ATT_dur, 1, 0, &info);
			e->timingp->dur = (SMIL_Duration *)info.far_ptr;
			e->timingp->dur->type = SMIL_DURATION_MEDIA;
		}
	}

	GF_SAFEALLOC(rti, SMIL_Timing_RTI)
	timingp->runtime = rti;
	rti->timed_elt = timed_elt;
	GF_LOG(GF_LOG_DEBUG, GF_LOG_SMIL, ("[SMIL Timing   ] Time %f - Timed element %s - Initialization\n", gf_node_get_scene_time((GF_Node *)rti->timed_elt), gf_node_get_log_name((GF_Node *)rti->timed_elt)));

	rti->timingp = timingp;
	rti->status = SMIL_STATUS_WAITING_TO_BEGIN;
	rti->evaluate_status = SMIL_TIMING_EVAL_NONE;	
	rti->evaluate = gf_smil_timing_null_timed_function;
	rti->scene_time = -1;
	rti->force_reevaluation = 0;
	rti->media_duration = -1;

	GF_SAFEALLOC(rti->current_interval, SMIL_Interval);
	gf_smil_timing_get_first_interval(rti);
	GF_SAFEALLOC(rti->next_interval, SMIL_Interval);
	gf_smil_timing_get_next_interval(rti, 0, rti->next_interval, rti->current_interval->begin);

	/* Now that the runtime info for this timed element is initialized, we can tell the scene graph that it can start
	   notifying the scene time to this element. Because of the 'animation' element, we can have many scene graphs
	   sharing the same scene time, we therefore add this timed element to the rootmost scene graph. */
	sg = timed_elt->sgprivate->scenegraph;
	while (sg->parent_scene) sg = sg->parent_scene;
	gf_smil_timing_add_to_sg(sg, rti);
}
Exemple #12
0
static void svg_parse_animation(GF_SceneGraph *sg, SVG_DeferedAnimation *anim)
{
    GF_FieldInfo info;
    u32 tag;
    u8 anim_value_type = 0;

    if (anim->resolve_stage==0) {
        /* Stage 0: parsing the animation attribute values
        			for that we need to resolve the target first */
        if (!anim->target)
            anim->target = (SVG_Element *) gf_sg_find_node_by_name(sg, anim->target_id + 1);

        if (!anim->target) {
            /* the target is still not known stay in stage 0 */
            return;
        } else {
            XMLRI *iri;
            gf_node_get_attribute_by_tag((GF_Node *)anim->animation_elt, TAG_XLINK_ATT_href, 1, 0, &info);
            iri = (XMLRI *)info.far_ptr;
            iri->type = XMLRI_ELEMENTID;
            iri->target = anim->target;
            gf_node_register_iri(sg, iri);
        }

        tag = gf_node_get_tag((GF_Node *)anim->animation_elt);
        /* get the attribute name attribute if specified */
        if (anim->type && (tag== TAG_SVG_animateTransform) ) {
            gf_node_get_attribute_by_tag((GF_Node *)anim->animation_elt, TAG_SVG_ATT_transform_type, 1, 0, &info);
            gf_svg_parse_attribute((GF_Node *)anim->animation_elt, &info, anim->type, 0);
            switch(*(SVG_TransformType *) info.far_ptr) {
            case SVG_TRANSFORM_TRANSLATE:
                anim_value_type = SVG_Transform_Translate_datatype;
                break;
            case SVG_TRANSFORM_SCALE:
                anim_value_type = SVG_Transform_Scale_datatype;
                break;
            case SVG_TRANSFORM_ROTATE:
                anim_value_type = SVG_Transform_Rotate_datatype;
                break;
            case SVG_TRANSFORM_SKEWX:
                anim_value_type = SVG_Transform_SkewX_datatype;
                break;
            case SVG_TRANSFORM_SKEWY:
                anim_value_type = SVG_Transform_SkewY_datatype;
                break;
            case SVG_TRANSFORM_MATRIX:
                anim_value_type = SVG_Transform_datatype;
                break;
            default:
                fprintf(stdout, "unknown datatype for animate transform");
                return;
            }
        }
        else if (gf_node_get_attribute_by_tag((GF_Node *)anim->animation_elt, TAG_SVG_ATT_attributeName, 0, 0, &info) == GF_OK) {
            gf_node_get_attribute_by_name((GF_Node *)anim->target, ((SMIL_AttributeName *)info.far_ptr)->name, 0, 1, 1, &info);
            anim_value_type = info.fieldType;
        } else {
            if (tag == TAG_SVG_animateMotion) {
                anim_value_type = SVG_Motion_datatype;
            } else if (tag == TAG_SVG_discard) {
                /* there is no value to parse in discard, we can jump to the next stage */
                anim->resolve_stage = 1;
                svg_parse_animation(sg, anim);
                return;
            } else {
                fprintf(stdout, "Missing attributeName attribute on %s", gf_node_get_name((GF_Node *)anim->animation_elt));
                return;
            }
        }

        if (anim->to) {
            gf_node_get_attribute_by_tag((GF_Node *)anim->animation_elt, TAG_SVG_ATT_to, 1, 0, &info);
            gf_svg_parse_attribute((GF_Node *)anim->animation_elt, &info, anim->to, anim_value_type);
        }
        if (anim->from) {
            gf_node_get_attribute_by_tag((GF_Node *)anim->animation_elt, TAG_SVG_ATT_from, 1, 0, &info);
            gf_svg_parse_attribute((GF_Node *)anim->animation_elt, &info, anim->from, anim_value_type);
        }
        if (anim->by) {
            gf_node_get_attribute_by_tag((GF_Node *)anim->animation_elt, TAG_SVG_ATT_by, 1, 0, &info);
            gf_svg_parse_attribute((GF_Node *)anim->animation_elt, &info, anim->by, anim_value_type);
        }
        if (anim->values) {
            gf_node_get_attribute_by_tag((GF_Node *)anim->animation_elt, TAG_SVG_ATT_values, 1, 0, &info);
            gf_svg_parse_attribute((GF_Node *)anim->animation_elt, &info, anim->values, anim_value_type);
        }
        anim->resolve_stage = 1;
    }
}
Exemple #13
0
void gf_sc_get_nodes_bounds(GF_Node *self, GF_ChildNodeItem *children, GF_TraverseState *tr_state, s32 *child_idx)
{
	u32 i;
	SFVec2f size;
	GF_Rect rc;
	GF_Matrix2D cur_mx;

	if (tr_state->abort_bounds_traverse) {
		if (self == tr_state->for_node) {
			gf_mx2d_pre_multiply(&tr_state->mx_at_node, &tr_state->transform);
		}
		tr_state->abort_bounds_traverse=0;
		gf_sc_get_nodes_bounds(self, children, tr_state, child_idx);
		tr_state->abort_bounds_traverse=1;
		return;
	}
	if (!children) return;

	size.x = size.y = -FIX_ONE;
#ifndef GPAC_DISABLE_VRML
	switch (gf_node_get_tag(self)) {
	case TAG_MPEG4_Layer2D: size = ((M_Layer2D *)self)->size; break;
	case TAG_MPEG4_Layer3D: size = ((M_Layer3D *)self)->size; break;
	case TAG_MPEG4_Form: size = ((M_Form *)self)->size; break;
	}
#endif
	if ((size.x>=0) && (size.y>=0)) {
		tr_state->bounds = gf_rect_center(size.x, size.y);
		return;
	}

	gf_mx2d_copy(cur_mx, tr_state->transform);
	rc = gf_rect_center(0,0);

	i = 0;
	while (children) {
		if (child_idx && (i != (u32) *child_idx)) {
			children = children->next;
			continue;
		}
		gf_mx2d_init(tr_state->transform);
		tr_state->bounds = gf_rect_center(0,0);

		/*we hit the target node*/
		if (children->node == tr_state->for_node) 
			tr_state->abort_bounds_traverse = 1;

		gf_node_traverse(children->node, tr_state);

		if (tr_state->abort_bounds_traverse) {
			gf_mx2d_add_matrix(&tr_state->mx_at_node, &cur_mx);
			return;
		}

		gf_mx2d_apply_rect(&tr_state->transform, &tr_state->bounds);
		gf_rect_union(&rc, &tr_state->bounds);
		children = children->next;
		if (child_idx) 
			break;
	}

#ifndef GPAC_DISABLE_SVG
	if (gf_node_get_tag(self)==TAG_SVG_use) {
		GF_FieldInfo info;
		if (gf_node_get_attribute_by_tag(self, TAG_XLINK_ATT_href, 0, 0, &info)==GF_OK) {
			GF_Node *iri = ((XMLRI*)info.far_ptr)->target;
			if (iri) {
				gf_mx2d_init(tr_state->transform);
				tr_state->bounds = gf_rect_center(0,0);

				/*we hit the target node*/
				if (iri == tr_state->for_node) 
					tr_state->abort_bounds_traverse = 1;

				gf_node_traverse(iri, tr_state);

				if (tr_state->abort_bounds_traverse) {
					gf_mx2d_pre_multiply(&tr_state->mx_at_node, &cur_mx);
					return;
				}

				gf_mx2d_apply_rect(&tr_state->transform, &tr_state->bounds);
				gf_rect_union(&rc, &tr_state->bounds);
			}
		}
	}
#endif
	
	gf_mx2d_copy(tr_state->transform, cur_mx);
	if (self != tr_state->for_node) {
		gf_mx2d_apply_rect(&tr_state->transform, &rc);
	}
	tr_state->bounds = rc;
}
Exemple #14
0
GF_EXPORT
GF_Err gf_sg_command_apply(GF_SceneGraph *graph, GF_Command *com, Double time_offset)
{
	GF_Err e;
	GF_CommandField *inf;
#ifndef GPAC_DISABLE_VRML
	GF_FieldInfo field;
	void *slot_ptr;
	GF_Node *def;
#endif
	GF_Node *node;

	if (!com || !graph) return GF_BAD_PARAM;

	if (com->never_apply) return GF_OK;

	e = GF_OK;
	switch (com->tag) {
#ifndef GPAC_DISABLE_VRML
	case GF_SG_SCENE_REPLACE:
		/*unregister root*/
		gf_node_unregister(graph->RootNode, NULL);
		/*remove all protos and routes*/
		while (gf_list_count(graph->routes_to_activate)) 
			gf_list_rem(graph->routes_to_activate, 0);

		if (!com->aggregated) {
			/*destroy all routes*/
			while (gf_list_count(graph->Routes)) {
				GF_Route *r = (GF_Route *)gf_list_get(graph->Routes, 0);
				/*this will unregister the route from the graph, so don't delete the chain entry*/
				gf_sg_route_del(r);
			}
			/*destroy all proto*/
			while (gf_list_count(graph->protos)) {
				GF_Proto *p = (GF_Proto*)gf_list_get(graph->protos, 0);
				/*this will unregister the proto from the graph, so don't delete the chain entry*/
				gf_sg_proto_del(p);
			}
		}
		/*DO NOT TOUCH node registry*/
		/*DO NOT TOUCH UNREGISTERED PROTOS*/

		/*if no protos (previously aggregated command) create proto list*/
		if (!graph->protos) graph->protos = gf_list_new();

		/*move all protos in graph*/
		while (gf_list_count(com->new_proto_list)) {
			GF_Proto *p = (GF_Proto*)gf_list_get(com->new_proto_list, 0);
			gf_list_rem(com->new_proto_list, 0);
			gf_list_del_item(graph->unregistered_protos, p);
			gf_list_add(graph->protos, p);
		}
		/*assign new root (no need to register/unregister)*/
		graph->RootNode = com->node;
		com->node = NULL;
		break;

	case GF_SG_NODE_REPLACE:
		if (!gf_list_count(com->command_fields)) return GF_OK;
		inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
		e = gf_node_replace(com->node, inf->new_node, 0);
		if (inf->new_node) gf_node_register(inf->new_node, NULL);
		break;

	case GF_SG_MULTIPLE_REPLACE:
	case GF_SG_FIELD_REPLACE:
	{
		u32 j;
		GF_ChildNodeItem *list, *cur, *prev;
		j=0;
		while ((inf = (GF_CommandField*)gf_list_enum(com->command_fields, &j))) {
			e = gf_node_get_field(com->node, inf->fieldIndex, &field);
			if (e) return e;

			switch (field.fieldType) {
			case GF_SG_VRML_SFNODE:
			{
				node = *((GF_Node **) field.far_ptr);
				e = gf_node_unregister(node, com->node);
				*((GF_Node **) field.far_ptr) = inf->new_node;
				if (!e) gf_node_register(inf->new_node, com->node);
				break;
			}
			case GF_SG_VRML_MFNODE:
				gf_node_unregister_children(com->node, * ((GF_ChildNodeItem **) field.far_ptr));
				* ((GF_ChildNodeItem **) field.far_ptr) = NULL;

				list = * ((GF_ChildNodeItem **) inf->field_ptr);
				prev=NULL;
				while (list) {
					cur = gf_malloc(sizeof(GF_ChildNodeItem));
					cur->next = NULL;
					cur->node = list->node;
					if (prev) {
						prev->next = cur;
					} else {
						* ((GF_ChildNodeItem **) field.far_ptr) = cur;
					}
					gf_node_register(list->node, com->node);
					prev = cur;
					list = list->next;
				}
				break;
			case GF_SG_VRML_SFCOMMANDBUFFER:
			{
				u32 i, count;
				GF_SceneGraph *sg;
				SFCommandBuffer *cb_dst = (SFCommandBuffer *)field.far_ptr;
				SFCommandBuffer *cb_src = (SFCommandBuffer *)inf->field_ptr;

				/*reset dest*/
				if (!cb_dst->commandList) cb_dst->commandList = gf_list_new();

				while (gf_list_count(cb_dst->commandList)) {
					GF_Command *sub_com = (GF_Command *)gf_list_get(cb_dst->commandList, 0);
					gf_sg_command_del(sub_com);
					gf_list_rem(cb_dst->commandList, 0);
				}
				if (cb_dst->buffer) {
					gf_free(cb_dst->buffer);
					cb_dst->buffer = NULL;
				}

				/*clone command list*/
				sg = gf_node_get_graph(com->node);
				count = gf_list_count(cb_src->commandList);
				for (i=0; i<count;i++) {
					GF_Command *sub_com = (GF_Command *)gf_list_get(cb_src->commandList, i);
					GF_Command *new_com = gf_sg_vrml_command_clone(sub_com, sg, 0);
					gf_list_add(cb_dst->commandList, new_com);
				}
			}
				break;

			default:
				/*this is a regular field, reset it and clone - we cannot switch pointers since the
				original fields are NOT pointers*/
				if (!gf_sg_vrml_is_sf_field(field.fieldType)) {
					e = gf_sg_vrml_mf_reset(field.far_ptr, field.fieldType);
				}
				if (e) return e;
				gf_sg_vrml_field_copy(field.far_ptr, inf->field_ptr, field.fieldType);
				
				if ((field.fieldType==GF_SG_VRML_SFTIME) && !strstr(field.name, "media"))
					*(SFTime *)field.far_ptr = *(SFTime *)field.far_ptr + time_offset;
				break;
			}
			SG_CheckFieldChange(com->node, &field);
		}
		break;
	}

	case GF_SG_MULTIPLE_INDEXED_REPLACE:
	case GF_SG_INDEXED_REPLACE:
	{
		u32 sftype, i=0;
		while ((inf = (GF_CommandField*)gf_list_enum(com->command_fields, &i))) {
			e = gf_node_get_field(com->node, inf->fieldIndex, &field);
			if (e) return e;

			/*if MFNode remove the child and set new node*/
			if (field.fieldType == GF_SG_VRML_MFNODE) {
				/*we must remove the node before in case the new node uses the same ID (not forbidden) and this
				command removes the last instance of the node with the same ID*/
				gf_node_replace_child(com->node, (GF_ChildNodeItem**) field.far_ptr, inf->pos, inf->new_node);
				if (inf->new_node) gf_node_register(inf->new_node, NULL);
			}
			/*erase the field item*/
			else {
				if ((inf->pos < 0) || ((u32) inf->pos >= ((GenMFField *) field.far_ptr)->count) ) {
					inf->pos = ((GenMFField *)field.far_ptr)->count - 1;
					/*may happen with text and default value*/
					if (inf->pos < 0) {
						inf->pos = 0;
						gf_sg_vrml_mf_alloc(field.far_ptr, field.fieldType, 1);
					}
				}
				e = gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, & slot_ptr, inf->pos);
				if (e) return e;
				sftype = gf_sg_vrml_get_sf_type(field.fieldType);
				gf_sg_vrml_field_copy(slot_ptr, inf->field_ptr, sftype);
				/*note we don't add time offset, since there's no MFTime*/
			}
			SG_CheckFieldChange(com->node, &field);
		}
		break;
	}
	case GF_SG_ROUTE_REPLACE:
	{
		GF_Route *r;
		char *name;
		r = gf_sg_route_find(graph, com->RouteID);
		def = gf_sg_find_node(graph, com->fromNodeID);
		node = gf_sg_find_node(graph, com->toNodeID);
		if (!node || !def) return GF_SG_UNKNOWN_NODE;
		name = NULL;
		if (r) {
			name = r->name;
			r->name = NULL;
			gf_sg_route_del(r);
		}
		r = gf_sg_route_new(graph, def, com->fromFieldIndex, node, com->toFieldIndex);
		gf_sg_route_set_id(r, com->RouteID);
		if (name) {
			gf_sg_route_set_name(r, name);
			gf_free(name);
		}
		break;
	}
	case GF_SG_NODE_DELETE_EX:
	case GF_SG_NODE_DELETE:
	{
		if (com->node) gf_node_replace(com->node, NULL, (com->tag==GF_SG_NODE_DELETE_EX) ? 1 : 0);
		break;
	}
	case GF_SG_ROUTE_DELETE:
	{
		return gf_sg_route_del_by_id(graph, com->RouteID);
	}
	case GF_SG_INDEXED_DELETE:
	{
		if (!gf_list_count(com->command_fields)) return GF_OK;
		inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);

		e = gf_node_get_field(com->node, inf->fieldIndex, &field);
		if (e) return e;
		if (gf_sg_vrml_is_sf_field(field.fieldType)) return GF_NON_COMPLIANT_BITSTREAM;

		/*then we need special handling in case of a node*/
		if (gf_sg_vrml_get_sf_type(field.fieldType) == GF_SG_VRML_SFNODE) {
			e = gf_node_replace_child(com->node, (GF_ChildNodeItem **) field.far_ptr, inf->pos, NULL);
		} else {
			if ((inf->pos < 0) || ((u32) inf->pos >= ((GenMFField *) field.far_ptr)->count) ) {
				inf->pos = ((GenMFField *)field.far_ptr)->count - 1;
			}
			/*this is a regular MFField, just remove the item (gf_realloc)*/
			e = gf_sg_vrml_mf_remove(field.far_ptr, field.fieldType, inf->pos);
		}
		/*deletion -> node has changed*/
		if (!e) SG_CheckFieldChange(com->node, &field);
		break;
	}
	case GF_SG_NODE_INSERT:
	{
		if (!gf_list_count(com->command_fields)) return GF_OK;
		inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);

		e = gf_node_insert_child(com->node, inf->new_node, inf->pos);
		if (!e) gf_node_register(inf->new_node, com->node);
		if (!e) gf_node_event_out(com->node, inf->fieldIndex);
		if (!e) gf_node_changed(com->node, NULL);
		break;
	}
	case GF_SG_ROUTE_INSERT:
	{
		GF_Route *r;
		def = gf_sg_find_node(graph, com->fromNodeID);
		node = gf_sg_find_node(graph, com->toNodeID);
		if (!node || !def) return GF_SG_UNKNOWN_NODE;
		r = gf_sg_route_new(graph, def, com->fromFieldIndex, node, com->toFieldIndex);
		if (com->RouteID) gf_sg_route_set_id(r, com->RouteID);
		if (com->def_name) {
			gf_sg_route_set_name(r, com->def_name);
			gf_free(com->def_name);
			com->def_name = NULL;
		}
		break;
	}
	case GF_SG_INDEXED_INSERT:
	{
		u32 sftype;
		if (!gf_list_count(com->command_fields)) return GF_OK;
		inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
		e = gf_node_get_field(com->node, inf->fieldIndex, &field);
		if (e) return e;

		/*rescale the MFField and parse the SFField*/
		if (field.fieldType != GF_SG_VRML_MFNODE) {
			if (inf->pos == -1) {
				e = gf_sg_vrml_mf_append(field.far_ptr, field.fieldType, & slot_ptr);
			} else {
				e = gf_sg_vrml_mf_insert(field.far_ptr, field.fieldType, & slot_ptr, inf->pos);
			}
			if (e) return e;
			sftype = gf_sg_vrml_get_sf_type(field.fieldType);
			gf_sg_vrml_field_copy(slot_ptr, inf->field_ptr, sftype);
		} else {
			if (inf->new_node) {
				if (inf->pos == -1) {
					gf_node_list_add_child( (GF_ChildNodeItem **) field.far_ptr, inf->new_node);
				} else {
					gf_node_list_insert_child((GF_ChildNodeItem **) field.far_ptr, inf->new_node, inf->pos);
				}
				gf_node_register(inf->new_node, com->node);
			}
		}
		if (!e) SG_CheckFieldChange(com->node, &field);
		break;
	}
	case GF_SG_PROTO_INSERT:
		/*destroy all proto*/
		while (gf_list_count(com->new_proto_list)) {
			GF_Proto *p = (GF_Proto*)gf_list_get(com->new_proto_list, 0);
			gf_list_rem(com->new_proto_list, 0);
			gf_list_del_item(graph->unregistered_protos, p);
			gf_list_add(graph->protos, p);
		}
		return GF_OK;
	case GF_SG_PROTO_DELETE:
		{
			u32 i;
			for (i=0; i<com->del_proto_list_size; i++) {
				/*note this will check for unregistered protos, but since IDs are unique we are sure we will 
				not destroy an unregistered one*/
				GF_Proto *proto = gf_sg_find_proto(graph, com->del_proto_list[i], NULL);
				if (proto) gf_sg_proto_del(proto);
			}
		}
		return GF_OK;
	case GF_SG_PROTO_DELETE_ALL:
		/*destroy all proto*/
		while (gf_list_count(graph->protos)) {
			GF_Proto *p = (GF_Proto*)gf_list_get(graph->protos, 0);
			gf_list_rem(graph->protos, 0);
			/*this will unregister the proto from the graph, so don't delete the chain entry*/
			gf_sg_proto_del(p);
		}
		/*DO NOT TOUCH UNREGISTERED PROTOS*/
		return GF_OK;
	case GF_SG_XREPLACE:
	{
		s32 pos = -2; 
		GF_Node *target = NULL;
		GF_ChildNodeItem *list, *cur, *prev;
		GF_FieldInfo value;
		inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
		if (!inf) return GF_SG_UNKNOWN_NODE;

		e = gf_node_get_field(com->node, inf->fieldIndex, &field);
		if (e) return e;
		target = com->node;

		if (!gf_sg_vrml_is_sf_field(field.fieldType)) {
			GF_FieldInfo idxField;
			if ((inf->pos != -2) || com->toNodeID) {
				if (com->toNodeID) {
					GF_Node *idxNode = gf_sg_find_node(graph, com->toNodeID);
					if (!idxNode) return GF_SG_UNKNOWN_NODE;
				
					if (gf_node_get_field(idxNode, com->toFieldIndex, &idxField) != GF_OK) return GF_OK;
					pos = 0;
					switch (idxField.fieldType) {
					case GF_SG_VRML_SFBOOL:
						if (*(SFBool*)idxField.far_ptr) pos = 1;
						break;
					case GF_SG_VRML_SFINT32:
						if (*(SFInt32*)idxField.far_ptr >=0) pos = *(SFInt32*)idxField.far_ptr;
						break;
					case GF_SG_VRML_SFFLOAT:
						if ( (*(SFFloat *)idxField.far_ptr) >=0) pos = (s32) floor( FIX2FLT(*(SFFloat*)idxField.far_ptr) );
						break;
					case GF_SG_VRML_SFTIME:
						if ( (*(SFTime *)idxField.far_ptr) >=0) pos = (s32) floor( (*(SFTime *)idxField.far_ptr) );
						break;
					}
				} else {
					pos = inf->pos;
				}
			}
		}
		/*override target node*/
		if ((field.fieldType==GF_SG_VRML_MFNODE) && (pos>=-1) && com->ChildNodeTag) {
			target = gf_node_list_get_child(*(GF_ChildNodeItem **)field.far_ptr, pos);
			if (!target) return GF_SG_UNKNOWN_NODE;
			if (gf_node_get_field(target, com->child_field, &field) != GF_OK) return GF_SG_UNKNOWN_NODE;
			pos=-2;
		}

		if (com->fromNodeID) {
			GF_Node *fromNode = gf_sg_find_node(graph, com->fromNodeID);
			if (!fromNode) return GF_SG_UNKNOWN_NODE;
			e = gf_node_get_field(fromNode, com->fromFieldIndex, &value);
			if (e) return e;
		} else {
			value.far_ptr = inf->field_ptr;
			value.fieldType = inf->fieldType;
		}
		/*indexed replacement*/
		if (pos>=-1) {
			/*if MFNode remove the child and set new node*/
			if (field.fieldType == GF_SG_VRML_MFNODE) {
				GF_Node *nn = *(GF_Node**)value.far_ptr;
				gf_node_replace_child(target, (GF_ChildNodeItem**) field.far_ptr, pos, nn);
				if (nn) gf_node_register(nn, NULL);
			}
			/*erase the field item*/
			else {
				u32 sftype;
				if ((pos < 0) || ((u32) pos >= ((GenMFField *) field.far_ptr)->count) ) {
					pos = ((GenMFField *)field.far_ptr)->count - 1;
					/*may happen with text and default value*/
					if (pos < 0) {
						pos = 0;
						gf_sg_vrml_mf_alloc(field.far_ptr, field.fieldType, 1);
					}
				}
				e = gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, & slot_ptr, pos);
				if (e) return e;
				sftype = gf_sg_vrml_get_sf_type(field.fieldType);
				gf_sg_vrml_field_copy(slot_ptr, value.far_ptr, sftype);
				/*note we don't add time offset, since there's no MFTime*/
			}
		} else {
			switch (field.fieldType) {
			case GF_SG_VRML_SFNODE:
			{
				node = *((GF_Node **) field.far_ptr);
				e = gf_node_unregister(node, target);
				*((GF_Node **) field.far_ptr) = *((GF_Node **) value.far_ptr) ;
				if (!e) gf_node_register(*(GF_Node **) value.far_ptr, target);
				break;
			}
			case GF_SG_VRML_MFNODE:
				gf_node_unregister_children(target, * ((GF_ChildNodeItem **) field.far_ptr));
				* ((GF_ChildNodeItem **) field.far_ptr) = NULL;

				list = * ((GF_ChildNodeItem **) value.far_ptr);
				prev=NULL;
				while (list) {
					cur = gf_malloc(sizeof(GF_ChildNodeItem));
					cur->next = NULL;
					cur->node = list->node;
					if (prev) {
						prev->next = cur;
					} else {
						* ((GF_ChildNodeItem **) field.far_ptr) = cur;
					}
					gf_node_register(list->node, target);
					prev = cur;
					list = list->next;
				}
				break;

			default:
				if (!gf_sg_vrml_is_sf_field(field.fieldType)) {
					e = gf_sg_vrml_mf_reset(field.far_ptr, field.fieldType);
				}
				if (e) return e;
				gf_sg_vrml_field_clone(field.far_ptr, value.far_ptr, field.fieldType, graph);
				
				if ((field.fieldType==GF_SG_VRML_SFTIME) && !strstr(field.name, "media"))
					*(SFTime *)field.far_ptr = *(SFTime *)field.far_ptr + time_offset;
				break;
			}
		}
		SG_CheckFieldChange(target, &field);
	}
		return GF_OK;
	/*only used by BIFS*/
	case GF_SG_GLOBAL_QUANTIZER:
		return GF_OK;

#endif /*GPAC_DISABLE_VRML*/


#ifndef GPAC_DISABLE_SVG
	/*laser commands*/
	case GF_SG_LSR_NEW_SCENE:
		/*DO NOT TOUCH node registry*/

		/*assign new root (no need to register/unregister)*/
		graph->RootNode = com->node;
		com->node = NULL;
		break;
	case GF_SG_LSR_DELETE:
		if (!com->node) return GF_NON_COMPLIANT_BITSTREAM;
		if (!gf_list_count(com->command_fields)) {
			gf_node_replace(com->node, NULL, 0);
			gf_node_deactivate(com->node);
			return GF_OK;
		}
		inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
		node = gf_node_list_get_child(((SVG_Element *)com->node)->children, inf->pos);
		if (node) {
			e = gf_node_replace_child(com->node, &((SVG_Element *)com->node)->children, inf->pos, NULL);
			gf_node_deactivate(node);
		}
		break;
	case GF_SG_LSR_INSERT:
		inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
		if (!com->node || !inf) return GF_NON_COMPLIANT_BITSTREAM;
		if (inf->new_node) {
			if (inf->pos<0) 
				gf_node_list_add_child(& ((SVG_Element *)com->node)->children, inf->new_node);
			else
				gf_node_list_insert_child(& ((SVG_Element *)com->node)->children, inf->new_node, inf->pos);

			gf_node_register(inf->new_node, com->node);
			gf_node_activate(inf->new_node);
			gf_node_changed(com->node, NULL);
		} else {
			/*NOT SUPPORTED*/
			GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[LASeR] VALUE INSERTION NOT SUPPORTED\n"));
		}
		break;
	case GF_SG_LSR_ADD:
	case GF_SG_LSR_REPLACE:
		inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
		if (!com->node || !inf) return GF_NON_COMPLIANT_BITSTREAM;
		if (inf->new_node) {
			if (inf->pos<0) {
				/*if fieldIndex (eg attributeName) is set, this is children replacement*/
				if (inf->fieldIndex>0) {
					gf_node_unregister_children_deactivate(com->node, ((SVG_Element *)com->node)->children);
					((SVG_Element *)com->node)->children = NULL;
					gf_node_list_add_child(& ((SVG_Element *)com->node)->children, inf->new_node);
					gf_node_register(inf->new_node, com->node);
					gf_node_activate(inf->new_node);
				} else {
					e = gf_node_replace(com->node, inf->new_node, 0);
					gf_node_activate(inf->new_node);
				}
			} else {
				node = gf_node_list_get_child( ((SVG_Element *)com->node)->children, inf->pos);
				gf_node_replace_child(com->node, & ((SVG_Element *)com->node)->children, inf->pos, inf->new_node);
				gf_node_register(inf->new_node, com->node);
				if (node) gf_node_deactivate(node);
				gf_node_activate(inf->new_node);
			}
			/*signal node modif*/
			gf_node_changed(com->node, NULL);
			return e;
		} else if (inf->node_list) {
			GF_ChildNodeItem *child, *cur, *prev;
			gf_node_unregister_children_deactivate(com->node, ((SVG_Element *)com->node)->children);
			((SVG_Element *)com->node)->children = NULL;

			prev = NULL;
			child = inf->node_list;
			while (child) {
				cur = (GF_ChildNodeItem*)gf_malloc(sizeof(GF_ChildNodeItem));
				cur->next = NULL;
				cur->node = child->node;
				gf_node_register(child->node, com->node);
				gf_node_activate(child->node);
				if (prev) prev->next = cur;
				else ((SVG_Element *)com->node)->children = cur;
				prev = cur;
				child = child->next;
			}
			/*signal node modif*/
			gf_node_changed(com->node, NULL);
			return GF_OK;
		}
		/*attribute modif*/
		else if (inf->field_ptr) {
			GF_FieldInfo a, b;
			if (inf->fieldIndex==(u32) -2) {
				GF_Point2D scale, translate;
				Fixed rotate;
				GF_Matrix2D *dest;
				gf_node_get_field_by_name(com->node, "transform", &a);
				dest = (GF_Matrix2D*)a.far_ptr;
				
				if (com->tag==GF_SG_LSR_REPLACE) {
					if (gf_mx2d_decompose(dest, &scale, &rotate, &translate)) {
						gf_mx2d_init(*dest);
						if (inf->fieldType==SVG_TRANSFORM_SCALE) scale = *(GF_Point2D *)inf->field_ptr;
						else if (inf->fieldType==SVG_TRANSFORM_TRANSLATE) translate = *(GF_Point2D *)inf->field_ptr;
						else if (inf->fieldType==SVG_TRANSFORM_ROTATE) rotate = ((SVG_Point_Angle*)inf->field_ptr)->angle;

						gf_mx2d_add_scale(dest, scale.x, scale.y);
						gf_mx2d_add_rotation(dest, 0, 0, rotate);
						gf_mx2d_add_translation(dest, translate.x, translate.y);
					}
				} else {
					GF_Point2D *pt = (GF_Point2D *)inf->field_ptr;
					if (inf->fieldType==SVG_TRANSFORM_SCALE) gf_mx2d_add_scale(dest, pt->x, pt->y);
					else if (inf->fieldType==SVG_TRANSFORM_TRANSLATE) gf_mx2d_add_translation(dest, pt->x, pt->y);
					else if (inf->fieldType == SVG_TRANSFORM_ROTATE) gf_mx2d_add_rotation(dest, 0, 0, ((SVG_Point_Angle*)inf->field_ptr)->angle);
				}
				/*signal node modif*/
				gf_node_changed(com->node, &a);
			} else {
				if ((inf->fieldIndex==(u32) -1) && (inf->fieldType==DOM_String_datatype)) {
					char *str = *(SVG_String*)inf->field_ptr;

					if (com->tag == GF_SG_LSR_REPLACE) {
						GF_DOMText *t = ((SVG_Element*)com->node)->children ? (GF_DOMText*) ((SVG_Element*)com->node)->children->node :NULL; 
						if (t && (t->sgprivate->tag==TAG_DOMText)) {
							if (t->textContent) gf_free(t->textContent);
							t->textContent = NULL;
							if (str) t->textContent = gf_strdup(str);
						}
					} else {
						if (str) gf_dom_add_text_node(com->node, gf_strdup(str));
					}
					/*signal node modif*/
					gf_node_changed(com->node, NULL);
				}
				else if ((inf->fieldIndex==TAG_LSR_ATT_scale) 
					|| (inf->fieldIndex==TAG_LSR_ATT_translation)
					|| (inf->fieldIndex==TAG_LSR_ATT_rotation)
				) {
					SVG_Transform *mx;
					gf_node_get_attribute_by_tag(com->node, TAG_SVG_ATT_transform, 1, 0, &a);
					mx = a.far_ptr;
					if (com->tag == GF_SG_LSR_REPLACE) {
						GF_Point2D scale, translate;
						SVG_Point_Angle rotate;
						if (gf_mx2d_decompose(&mx->mat, &scale, &rotate.angle, &translate)) {
							gf_mx2d_init(mx->mat);
							if (inf->fieldIndex==TAG_LSR_ATT_scale) scale = *(GF_Point2D *)inf->field_ptr;
							else if (inf->fieldIndex==TAG_LSR_ATT_translation) translate = *(GF_Point2D *)inf->field_ptr;
							else if (inf->fieldIndex==TAG_LSR_ATT_rotation) rotate = *(SVG_Point_Angle*)inf->field_ptr;

							gf_mx2d_add_scale(&mx->mat, scale.x, scale.y);
							gf_mx2d_add_rotation(&mx->mat, 0, 0, rotate.angle);
							gf_mx2d_add_translation(&mx->mat, translate.x, translate.y);
						}
					} else {
						if (inf->fieldIndex==TAG_LSR_ATT_scale) gf_mx2d_add_scale(&mx->mat, ((GF_Point2D*)inf->field_ptr)->x, ((GF_Point2D*)inf->field_ptr)->y);
						if (inf->fieldIndex==TAG_LSR_ATT_translation) gf_mx2d_add_translation(&mx->mat, ((GF_Point2D*)inf->field_ptr)->x, ((GF_Point2D*)inf->field_ptr)->y);
						if (inf->fieldIndex==TAG_LSR_ATT_rotation) gf_mx2d_add_rotation(&mx->mat, 0, 0, ((SVG_Point_Angle*)inf->field_ptr)->angle);
					}
					/*signal node modif*/
					gf_node_changed(com->node, &a);
				}
				else if (gf_node_get_attribute_by_tag(com->node, inf->fieldIndex, 1, 0, &a) == GF_OK) {
					b = a;
					b.far_ptr = inf->field_ptr;
					if (com->tag == GF_SG_LSR_REPLACE) {
						gf_svg_attributes_copy(&a, &b, 0);
					} else {
						gf_svg_attributes_add(&a, &b, &a, 0);
					}
					if (a.fieldType==XMLRI_datatype) {
						gf_node_dirty_set(com->node, GF_SG_SVG_XLINK_HREF_DIRTY, 0);
					}
					/*signal node modif*/
					gf_node_changed(com->node, &a);
				}
			}
		} else if (com->fromNodeID) {
			GF_FieldInfo a, b;
			GF_Node *fromNode = gf_sg_find_node(graph, com->fromNodeID);
			if (!fromNode) return GF_NON_COMPLIANT_BITSTREAM;
			if (gf_node_get_field(fromNode, com->fromFieldIndex, &b) != GF_OK) return GF_NON_COMPLIANT_BITSTREAM;

			if ((inf->fieldIndex==(u32) -1) && (inf->fieldType==DOM_String_datatype)) {
				char *str = *(SVG_String*)inf->field_ptr;

				if (com->tag == GF_SG_LSR_REPLACE) {
					GF_DOMText *t = ((SVG_Element*)com->node)->children ? (GF_DOMText*) ((SVG_Element*)com->node)->children->node :NULL; 
					if (t && (t->sgprivate->tag==TAG_DOMText)) {
						if (t->textContent) gf_free(t->textContent);
						t->textContent = NULL;
						if (str) t->textContent = gf_strdup(str);
					}
				} else {
					if (str) gf_dom_add_text_node(com->node, gf_strdup(str));
				}
			} else {
				gf_node_get_field(com->node, inf->fieldIndex, &a);
				if (com->tag == GF_SG_LSR_REPLACE) {
					e = gf_svg_attributes_copy(&a, &b, 0);
				} else {
					e = gf_svg_attributes_add(&a, &b, &a, 0);
				}
			}
			gf_node_changed(com->node, &a);
			return e;
		} else {
			return GF_NON_COMPLIANT_BITSTREAM;
		}
		break;
	case GF_SG_LSR_ACTIVATE:
		gf_node_activate(com->node);
		break;
	case GF_SG_LSR_DEACTIVATE:
		gf_node_deactivate(com->node);
		gf_node_changed(com->node, NULL);
		break;
	case GF_SG_LSR_SEND_EVENT:
	{
		GF_DOM_Event evt;
		memset(&evt, 0, sizeof(GF_DOM_Event));
		evt.type = com->send_event_name;
		evt.detail = com->send_event_integer;
		evt.clientX = com->send_event_x;
		evt.clientY = com->send_event_y;
		gf_dom_event_fire(com->node, &evt);
	}
		break;
#endif

	default:
		return GF_NOT_SUPPORTED;
	}
	if (e) return e;

#ifndef GPAC_DISABLE_VRML
	if (com->scripts_to_load) {
		while (gf_list_count(com->scripts_to_load)) {
			GF_Node *script = (GF_Node *)gf_list_get(com->scripts_to_load, 0);
			gf_list_rem(com->scripts_to_load, 0);
			gf_sg_script_load(script);
		}
		gf_list_del(com->scripts_to_load);
		com->scripts_to_load = NULL;
	}
#endif

	return GF_OK;
}
Exemple #15
0
static void SVG_Update_video(GF_TextureHandler *txh)
{
	GF_FieldInfo init_vis_info;
	SVG_video_stack *stack = (SVG_video_stack *) gf_node_get_private(txh->owner);
	
	if (!txh->is_open) {
		SVG_InitialVisibility init_vis;
		if (stack->first_frame_fetched) return;

		init_vis = SVG_INITIALVISIBILTY_WHENSTARTED;

		if (gf_node_get_attribute_by_tag(txh->owner, TAG_SVG_ATT_initialVisibility, GF_FALSE, GF_FALSE, &init_vis_info) == GF_OK) {
			init_vis = *(SVG_InitialVisibility *)init_vis_info.far_ptr;
		}

		/*opens stream only at first access to fetch first frame if needed*/
		if (init_vis == SVG_INITIALVISIBILTY_ALWAYS) {
			svg_play_texture((SVG_video_stack*)stack, NULL);
			gf_sc_invalidate(txh->compositor, NULL);
		}
		return;
	} 

	/*when fetching the first frame disable resync*/
	gf_sc_texture_update_frame(txh, GF_FALSE);

	/* only when needs_refresh = 1, first frame is fetched */
	if (!stack->first_frame_fetched) {
		if (txh->needs_refresh) {
			stack->first_frame_fetched = GF_TRUE;
			/*stop stream if needed*/
			if (!gf_smil_timing_is_active(txh->owner)) {
				gf_sc_texture_stop(txh);
				//make sure the refresh flag is not cleared
				txh->needs_refresh = GF_TRUE;
			}
		}
	}

	if (!stack->audio && stack->audio_dirty) {
		u32 res = gf_mo_has_audio(stack->txh.stream);
		if (res != 2) {
			stack->audio_dirty = GF_FALSE;
			if (res) {
				GF_FieldInfo att_vid, att_aud;
				stack->audio = gf_node_new(gf_node_get_graph(stack->txh.owner), TAG_SVG_audio);
				gf_node_register(stack->audio, NULL);
				if (gf_node_get_attribute_by_tag(stack->txh.owner, TAG_XLINK_ATT_href, GF_FALSE, GF_FALSE, &att_vid)==GF_OK) {
					gf_node_get_attribute_by_tag(stack->audio, TAG_XLINK_ATT_href, GF_TRUE, GF_FALSE, &att_aud);
					gf_svg_attributes_copy(&att_aud, &att_vid, GF_FALSE);
				}
				/*BYPASS SMIL TIMING MODULE!!*/
				compositor_init_svg_audio(stack->txh.compositor, stack->audio, GF_TRUE);
			}
		}
	}
	
	/*we have no choice but retraversing the graph until we're inactive since the movie framerate and
	the compositor framerate are likely to be different */
	if (!txh->stream_finished) 
	if (txh->needs_refresh)
		gf_sc_invalidate(txh->compositor, NULL);

	if (stack->stop_requested) {
		stack->stop_requested = GF_FALSE;
		gf_sc_texture_stop(&stack->txh);
	}
}