static void xmt_parse_command()

in src/scene_manager/loader_xmt.c [1989:2491]


static void xmt_parse_command(GF_XMTParser *parser, const char *name, const GF_XMLAttribute *attributes, u32 nb_attributes)
{
	GF_Err e;
	GF_FieldInfo info;
	GF_CommandField *field;
	u32 i;
	if (!strcmp(name, "Scene")) {
		parser->state = XMT_STATE_ELEMENTS;
		return;
	}
	if (!parser->in_com)
		parser->stream_id = parser->load->force_es_id;

	if (!strcmp(name, "par")) {
		parser->in_com = 1;
		for (i=0; i<nb_attributes; i++) {
			GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
			if (!att->value || !strlen(att->value)) continue;
			if (!strcmp(att->name, "begin")) parser->au_time = atof(att->value);
			else if (!strcmp(att->name, "isRAP")) parser->au_is_rap = !strcmp(att->value, "yes") ? 1 : 0;
			else if (!strcmp(att->name, "atES_ID")) {
				parser->stream_id = xmt_locate_stream(parser, att->value);
				if (!parser->stream_id) xmt_report(parser, GF_OK, "Warning: Cannot locate command's target stream %s", att->value);
			}
		}
		return;
	}
	/*ROUTE insert/replace*/
	if (!strcmp(name, "ROUTE")) {
		if (!parser->command || ((parser->command->tag!=GF_SG_ROUTE_REPLACE) && (parser->command->tag!=GF_SG_ROUTE_INSERT))) {
			xmt_report(parser, GF_BAD_PARAM, "ROUTE declared outside command scope");
			return;
		}
		if (parser->command->tag==GF_SG_ROUTE_INSERT) {
			xmt_parse_route(parser, attributes, nb_attributes, 1, parser->command);
			gf_list_add(parser->inserted_routes, parser->command);
		} else {
			xmt_parse_route(parser, attributes, nb_attributes, 0, parser->command);
			if (!parser->command->RouteID) {
				parser->command->unresolved = 1;
				if (gf_list_find(parser->unresolved_routes, parser->command)<0)
					gf_list_add(parser->unresolved_routes, parser->command);
			}
		}
		return;
	}
	/*multiple replace*/
	if (!strcmp(name, "repField")) {
		char *fieldName = NULL;
		char *fieldValue = NULL;
		assert(parser->command);
		if (!parser->command->node) return;
		for (i=0; i<nb_attributes; i++) {
			GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
			if (!att->value || !strlen(att->value)) continue;
			if (!strcmp(att->name, "atField")) fieldName = att->value;
			else if (!strcmp(att->name, "value")) fieldValue = att->value;
		}
		if (!fieldName) {
			parser->state = XMT_STATE_ELEMENTS;
			return;
		}
		e = gf_node_get_field_by_name(parser->command->node, fieldName, &info);
		if (e) {
			xmt_report(parser, GF_BAD_PARAM, "Warning: Field %s not a member of node %s ", fieldName, gf_node_get_class_name(parser->command->node) );
			return;
		}
		if (gf_sg_vrml_get_sf_type(info.fieldType) == GF_SG_VRML_SFNODE) {
			parser->state = XMT_STATE_ELEMENTS;
			return;
		}
		if (!fieldValue) return;

		field = gf_sg_command_field_new(parser->command);
		field->fieldIndex = info.fieldIndex;
		field->fieldType = info.fieldType;
		if (fieldValue) {
			field->field_ptr = gf_sg_vrml_field_pointer_new(info.fieldType);
			info.far_ptr = field->field_ptr;
			if (gf_sg_vrml_is_sf_field(info.fieldType)) {
				xmt_parse_sf_field(parser, &info, parser->command->node, fieldValue);
			} else {
				xmt_parse_mf_field(parser, &info, parser->command->node, fieldValue);
			}
		} else {
			parser->state = XMT_STATE_ELEMENTS;
		}
		return;
	}
	/*multiple index replace*/
	if (!strcmp(name, "repValue")) {
		s32 position = -1;
		char *fieldValue = NULL;
		assert(parser->command);
		if (!parser->command->node) return;
		for (i=0; i<nb_attributes; i++) {
			GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
			if (!att->value || !strlen(att->value)) continue;
			if (!strcmp(att->name, "position")) {
				if (!strcmp(att->value, "BEGIN")) position = 0;
				else if (!strcmp(att->value, "END")) position = -1;
				else position = atoi(att->value);
			}
			else if (!strcmp(att->name, "value")) fieldValue = att->value;
		}
		gf_node_get_field(parser->command->node, parser->command->fromFieldIndex, &info);
		if (info.fieldType == GF_SG_VRML_MFNODE) {
			field = gf_sg_command_field_new(parser->command);
			field->fieldIndex = info.fieldIndex;
			field->fieldType = GF_SG_VRML_SFNODE;
			field->pos = position;
			parser->state = XMT_STATE_ELEMENTS;
		} else if (fieldValue) {
			field = gf_sg_command_field_new(parser->command);
			field->fieldIndex = info.fieldIndex;
			field->fieldType = info.fieldType = gf_sg_vrml_get_sf_type(info.fieldType);
			field->field_ptr = gf_sg_vrml_field_pointer_new(info.fieldType);
			field->pos = position;
			info.far_ptr = field->field_ptr;
			xmt_parse_sf_field(parser, &info, parser->command->node, fieldValue);
		}
		return;
	}


	/*BIFS command*/
	if (!strcmp(name, "Replace") || !strcmp(name, "Insert") || !strcmp(name, "Delete")) {
		GF_Node *atNode;
		u8 tag = GF_SG_UNDEFINED;
		u32 stream_id;
		Double au_time = parser->au_time;
		Bool au_is_rap = parser->au_is_rap;
		char *nodeName = NULL;
		char *fieldName = NULL;
		char *fieldValue = NULL;
		char *routeName = NULL;
		char *extended = NULL;
		char *idxNode = NULL;
		char *idxField = NULL;
		char *childField = NULL;
		char *fromNode = NULL;
		char *fromField = NULL;

		s32 position = -2;

		if (!parser->stream_id) parser->stream_id = parser->base_scene_id;
		stream_id = parser->stream_id;

		for (i=0; i<nb_attributes; i++) {
			GF_XMLAttribute *att = (GF_XMLAttribute *)&attributes[i];
			if (!att->value || !strlen(att->value)) continue;
			if (!strcmp(att->name, "begin")) au_time = atoi(att->value);
			else if (!strcmp(att->name, "isRAP")) au_is_rap = !strcmp(att->value, "yes") ? 1 : 0;
			else if (!strcmp(att->name, "atES_ID")) {
				stream_id = xmt_locate_stream(parser, att->value);
				if (!stream_id) {
					xmt_report(parser, GF_OK, "Warning: Cannot locate command's target stream %s", att->value);
					stream_id = parser->stream_id;
				}
			}
			else if (!strcmp(att->name, "atNode")) nodeName = att->value;
			else if (!strcmp(att->name, "atField")) fieldName = att->value;
			else if (!strcmp(att->name, "value")) fieldValue = att->value;
			else if (!strcmp(att->name, "atRoute")) routeName = att->value;
			else if (!strcmp(att->name, "extended")) extended = att->value;
			else if (!strcmp(att->name, "atIndexNode")) idxNode = att->value;
			else if (!strcmp(att->name, "atIndexField")) idxField = att->value;
			else if (!strcmp(att->name, "atChildField")) childField = att->value;
			else if (!strcmp(att->name, "fromNode")) fromNode = att->value;
			else if (!strcmp(att->name, "fromField")) fromField = att->value;
			else if (!strcmp(att->name, "position")) {
				if (!strcmp(att->value, "BEGIN")) position = 0;
				else if (!strcmp(att->value, "END")) position = -1;
				else position = atoi(att->value);
			}
		}

		/*if we are parsing in an already loaded context and no time is given, force a time != 0 to create a new command*/
		if (!au_time && (parser->load->flags&GF_SM_LOAD_CONTEXT_READY))
			au_time = 0.001;

		atNode = NULL;
		if (nodeName) {
			if (fieldName) {
				if (position>-2) {
					if (!strcmp(name, "Replace")) tag = GF_SG_INDEXED_REPLACE;
					else if (!strcmp(name, "Insert")) tag = GF_SG_INDEXED_INSERT;
					else if (!strcmp(name, "Delete")) tag = GF_SG_INDEXED_DELETE;
				} else {
					if (!strcmp(name, "Replace")) {
						if ((idxNode && idxField) || childField || (fromNode && fromField)) {
							tag = GF_SG_XREPLACE;
						} else {
							tag = GF_SG_FIELD_REPLACE;
						}
					}
				}
			} else {
				if (!strcmp(name, "Replace")) {
					tag = GF_SG_NODE_REPLACE;
					parser->state = XMT_STATE_ELEMENTS;
				}
				else if (!strcmp(name, "Insert")) {
					tag = GF_SG_NODE_INSERT;
					parser->state = XMT_STATE_ELEMENTS;
				}
				else if (!strcmp(name, "Delete")) tag = GF_SG_NODE_DELETE;
			}

			atNode = xmt_find_node(parser, nodeName);
			if (!atNode) {
				xmt_report(parser, GF_BAD_PARAM, "Warning: Cannot locate node %s for command %s", nodeName, name);
				return;
			}
			if (fieldName) {
				e = gf_node_get_field_by_name(atNode, fieldName, &info);
				if (e) {
					xmt_report(parser, GF_BAD_PARAM, "Warning: Field %s not a member of node %s ", fieldName, nodeName);
					return;
				}
			}
		}
		else if (routeName) {
			if (!strcmp(name, "Replace")) tag = GF_SG_ROUTE_REPLACE;
			else if (!strcmp(name, "Delete")) tag = GF_SG_ROUTE_DELETE;
		}
		else if (!strcmp(name, "Replace")) {
			tag = GF_SG_SCENE_REPLACE;
			au_is_rap = 1;
			gf_list_reset(parser->def_nodes);
		}
		else if (!strcmp(name, "Insert"))
			tag = GF_SG_ROUTE_INSERT;

		if (extended) {
			if (!strcmp(extended, "globalQuant")) {
				tag = GF_SG_GLOBAL_QUANTIZER;
				parser->state = XMT_STATE_ELEMENTS;
			}
			else if (!strcmp(extended, "fields")) {
				tag = GF_SG_MULTIPLE_REPLACE;
				parser->state = XMT_STATE_COMMANDS;
			}
			else if (!strcmp(extended, "indices")) {
				tag = GF_SG_MULTIPLE_INDEXED_REPLACE;
				parser->state = XMT_STATE_COMMANDS;
			}
			else if (!strcmp(extended, "deleteOrder")) tag = GF_SG_NODE_DELETE_EX;
			else if (!strcmp(extended, "allProtos")) tag = GF_SG_PROTO_DELETE_ALL;
			else if (!strcmp(extended, "proto") || !strcmp(extended, "protos")) {
				if (!strcmp(name, "Insert")) {
					parser->state = XMT_STATE_ELEMENTS;
					tag = GF_SG_PROTO_INSERT;
				}
				else if (!strcmp(name, "Delete")) tag = GF_SG_PROTO_DELETE;
			}
			else {
				xmt_report(parser, GF_BAD_PARAM, "Warning: Unknown extended command %s", extended);
				return;
			}

		}

		if (tag == GF_SG_UNDEFINED) {
			xmt_report(parser, GF_BAD_PARAM, "Warning: Unknown scene command %s", name);
			return;
		}

		parser->command = gf_sg_command_new(parser->load->scene_graph, tag);
		if (parser->command_buffer) {
			gf_list_add(parser->command_buffer->commandList, parser->command);
			parser->command_buffer->bufferSize++;
		} else {
			GF_StreamContext *stream = gf_sm_stream_find(parser->load->ctx, (u16) stream_id);
			if (!stream || (stream->streamType!=GF_STREAM_SCENE)) stream_id = parser->base_scene_id;

			parser->scene_es = gf_sm_stream_new(parser->load->ctx, (u16) stream_id, GF_STREAM_SCENE, GPAC_OTI_SCENE_BIFS);
			parser->scene_au = gf_sm_stream_au_new(parser->scene_es, 0, au_time, au_is_rap);
			gf_list_add(parser->scene_au->commands, parser->command);
		}

		if (atNode) {
			parser->command->node = atNode;
			gf_node_register(atNode, NULL);
			if (tag == GF_SG_MULTIPLE_INDEXED_REPLACE) {
				parser->command->fromFieldIndex = info.fieldIndex;
				return;
			}
			if (fieldName) {
				field = gf_sg_command_field_new(parser->command);
				field->fieldIndex = info.fieldIndex;

				if (idxNode && idxField) {
					GF_Node *iNode = xmt_find_node(parser, idxNode);
					if (iNode) {
						GF_FieldInfo idxF;
						parser->command->toNodeID = gf_node_get_id(iNode);
						gf_node_get_field_by_name(iNode, idxField, &idxF);
						parser->command->toFieldIndex = idxF.fieldIndex;
						position = 0;
						switch (idxF.fieldType) {
						case GF_SG_VRML_SFBOOL:
							if (*(SFBool*)idxF.far_ptr) position = 1;
							break;
						case GF_SG_VRML_SFINT32:
							if (*(SFInt32*)idxF.far_ptr >=0) position = *(SFInt32*)idxF.far_ptr;
							break;
						case GF_SG_VRML_SFFLOAT:
							if ( (*(SFFloat *)idxF.far_ptr) >=0) position = (s32) floor( FIX2FLT(*(SFFloat*)idxF.far_ptr) );
							break;
						case GF_SG_VRML_SFTIME:
							if ( (*(SFTime *)idxF.far_ptr) >=0) position = (s32) floor( (*(SFTime *)idxF.far_ptr) );
							break;
						}
					}
				}
				if (childField) {
					GF_Node *child = gf_node_list_get_child( ((GF_ParentNode*)atNode)->children, position);
					if (child) {
						parser->command->ChildNodeTag = gf_node_get_tag(child);
						if (parser->command->ChildNodeTag == TAG_ProtoNode) {
							s32 p_id = gf_sg_proto_get_id(gf_node_get_proto(child));
							parser->command->ChildNodeTag = -p_id;
						}
						/*get field in the info struct for later parsing*/
						gf_node_get_field_by_name(child, childField, &info);
						parser->command->child_field = info.fieldIndex;
					}
				}
				/*do not keep position info if index node is used*/
				if (idxNode && idxField) position = -2;

				if (fromNode && fromField) {
					GF_Node *fNode = xmt_find_node(parser, fromNode);
					if (fNode) {
						GF_FieldInfo fField;
						parser->command->fromNodeID = gf_node_get_id(fNode);
						gf_node_get_field_by_name(fNode, fromField, &fField);
						parser->command->fromFieldIndex = fField.fieldIndex;
					}
				}
				if (!fromNode && !fromField) {
					if (gf_sg_vrml_get_sf_type(info.fieldType) != GF_SG_VRML_SFNODE) {
						if (position==-2) {
							field->fieldType = info.fieldType;
							field->field_ptr = gf_sg_vrml_field_pointer_new(info.fieldType);
							info.far_ptr = field->field_ptr;
							if (gf_sg_vrml_is_sf_field(info.fieldType)) {
								xmt_parse_sf_field(parser, &info, atNode, fieldValue);
							} else {
								xmt_parse_mf_field(parser, &info, atNode, fieldValue);
							}
						} else {
							field->fieldType = info.fieldType = gf_sg_vrml_get_sf_type(info.fieldType);
							field->pos = position;
							if (tag != GF_SG_INDEXED_DELETE) {
								field->field_ptr = gf_sg_vrml_field_pointer_new(info.fieldType);
								info.far_ptr = field->field_ptr;
								xmt_parse_sf_field(parser, &info, atNode, fieldValue);
							}
						}
					} else {
						field->pos = position;
						if ((position==-2) && (info.fieldType==GF_SG_VRML_MFNODE)) {
							field->fieldType = GF_SG_VRML_MFNODE;
						} else {
							field->fieldType = GF_SG_VRML_SFNODE;
						}
						parser->state = XMT_STATE_ELEMENTS;
					}
				}
			} else if (tag==GF_SG_NODE_INSERT) {
				field = gf_sg_command_field_new(parser->command);
				field->fieldType = GF_SG_VRML_SFNODE;
				field->pos = position;
				parser->state = XMT_STATE_ELEMENTS;
			}
		}
		else if (routeName) {
			u32 rID = xmt_get_route(parser, routeName, 0);
			if (!rID) {
				parser->command->unres_name = gf_strdup(routeName);
				parser->command->unresolved = 1;
				gf_list_add(parser->unresolved_routes, parser->command);
			} else {
				parser->command->RouteID = rID;
				/*for bt<->xmt conversions*/
				parser->command->def_name = gf_strdup(routeName);
			}
		}
		else if (tag == GF_SG_PROTO_DELETE) {
			char *sep;
			while (fieldValue) {
				GF_Proto *p;
				sep = strchr(fieldValue, ' ');
				if (sep) sep[0] = 0;
				p = gf_sg_find_proto(parser->load->scene_graph, 0, fieldValue);
				if (!p) p = gf_sg_find_proto(parser->load->scene_graph, atoi(fieldValue), NULL);

				if (!p) xmt_report(parser, GF_OK, "Warning: Cannot locate proto %s - skipping", fieldValue);
				else {
					parser->command->del_proto_list = (u32*)gf_realloc(parser->command->del_proto_list, sizeof(u32) * (parser->command->del_proto_list_size+1));
					parser->command->del_proto_list[parser->command->del_proto_list_size] = p->ID;
					parser->command->del_proto_list_size++;
				}
				if (!sep) break;
				sep[0] = ' ';
				fieldValue = sep+1;
			}
		}

		return;
	}

	/*OD commands*/
	if (!strcmp(name, "ObjectDescriptorUpdate") || !strcmp(name, "ObjectDescriptorRemove")
	        || !strcmp(name, "ES_DescriptorUpdate") || !strcmp(name, "ES_DescriptorRemove")
	        || !strcmp(name, "IPMP_DescriptorUpdate") || !strcmp(name, "IPMP_DescriptorRemove") ) {
		u32 stream_id;
		u8 tag = 0;
		GF_StreamContext *stream;
		char *od_ids = NULL;
		char *es_ids = NULL;
		Double au_time = parser->au_time;
		Bool au_is_rap = parser->au_is_rap;

		if (!parser->stream_id) parser->stream_id = parser->base_od_id;
		stream_id = parser->stream_id;

		for (i=0; i<nb_attributes; i++) {
			GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
			if (!att->value || !strlen(att->value)) continue;
			if (!strcmp(att->name, "begin")) au_time = atoi(att->value);
			else if (!strcmp(att->name, "isRAP")) au_is_rap = !strcmp(att->value, "yes") ? 1 : 0;
			else if (!stricmp(att->name, "objectDescriptorId")) od_ids = att->value;
			else if (!strcmp(att->name, "ES_ID")) es_ids = att->value;
		}

		/*if we are parsing in an already loaded context and no time is given, force a time != 0 to create a new command*/
		if (!au_time && (parser->load->flags&GF_SM_LOAD_CONTEXT_READY))
			au_time = 0.001;

		if (!strcmp(name, "ObjectDescriptorUpdate")) tag = GF_ODF_OD_UPDATE_TAG;
		else if (!strcmp(name, "ES_DescriptorUpdate")) tag = GF_ODF_ESD_UPDATE_TAG;
		else if (!strcmp(name, "IPMP_DescriptorUpdate")) tag = GF_ODF_IPMP_UPDATE_TAG;
		else if (!strcmp(name, "ObjectDescriptorRemove")) {
			if (!od_ids) return;
			tag = GF_ODF_OD_REMOVE_TAG;
		}
		else if (!strcmp(name, "ES_DescriptorRemove")) {
			if (!od_ids || !es_ids) return;
			tag = GF_ODF_ESD_REMOVE_TAG;
		}
		else if (!strcmp(name, "IPMP_DescriptorRemove")) tag = GF_ODF_IPMP_REMOVE_TAG;

		stream = gf_sm_stream_find(parser->load->ctx, (u16) stream_id);
		if (stream && (stream->streamType!=GF_STREAM_OD)) stream_id = parser->base_od_id;
		parser->od_es = gf_sm_stream_new(parser->load->ctx, (u16) stream_id, GF_STREAM_OD, 0);
		parser->od_au = gf_sm_stream_au_new(parser->od_es, 0, au_time, au_is_rap);
		parser->od_command = gf_odf_com_new(tag);
		gf_list_add(parser->od_au->commands, parser->od_command);

		if (tag == GF_ODF_ESD_REMOVE_TAG) {
			char *sep;
			GF_ESDRemove *esdR = (GF_ESDRemove *) parser->od_command ;
			esdR->ODID = xmt_get_od_id(parser, od_ids);
			while (es_ids) {
				u32 es_id;
				sep = strchr(es_ids, ' ');
				if (sep) sep[0] = 0;
				es_id = xmt_get_esd_id(parser, es_ids);
				if (!es_id) xmt_report(parser, GF_OK, "Warning: Cannot find ES Descriptor %s - skipping", es_ids);
				else {
					esdR->ES_ID = (u16*)gf_realloc(esdR->ES_ID, sizeof(u16) * (esdR->NbESDs+1));
					esdR->ES_ID[esdR->NbESDs] = es_id;
					esdR->NbESDs++;
				}
				if (!sep) break;
				sep[0] = ' ';
				es_ids = sep+1;
			}
		}
		else if (tag == GF_ODF_OD_REMOVE_TAG) {
			char *sep;
			GF_ODRemove *odR = (GF_ODRemove *) parser->od_command ;
			while (od_ids) {
				u32 od_id;
				sep = strchr(od_ids, ' ');
				if (sep) sep[0] = 0;
				od_id = xmt_get_od_id(parser, od_ids);
				if (!od_id) xmt_report(parser, GF_OK, "Warning: Cannot find Object Descriptor %s - skipping", od_ids);
				else {
					odR->OD_ID = (u16*)gf_realloc(odR->OD_ID, sizeof(u16) * (odR->NbODs+1));
					odR->OD_ID[odR->NbODs] = od_id;
					odR->NbODs++;
				}
				if (!sep) break;
				sep[0] = ' ';
				es_ids = sep+1;
			}
		}
	}
}