main.c

来自「gaca源码」· C语言 代码 · 共 1,280 行 · 第 1/3 页

C
1,280
字号
/*
 *			GPAC - Multimedia Framework C SDK
 *
 *			Copyright (c) Jean Le Feuvre 2000-2005
 *					All rights reserved
 *
 *  This file is part of GPAC / X3D Scene Graph Generator sub-project
 *
 *  GPAC is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *   
 *  GPAC is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *   
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <gpac/list.h>
#include <time.h>

#define COPYRIGHT "/*\n *			GPAC - Multimedia Framework C SDK\n *\n *			Copyright (c) Jean Le Feuvre 2000-2005\n *					All rights reserved\n *\n *  This file is part of GPAC / X3D Scene Graph sub-project\n *\n *  GPAC is free software; you can redistribute it and/or modify\n *  it under the terms of the GNU Lesser General Public License as published by\n *  the Free Software Foundation; either version 2, or (at your option)\n *  any later version.\n *\n *  GPAC is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU Lesser General Public License for more details.	\n *\n *  You should have received a copy of the GNU Lesser General Public\n *  License along with this library; see the file COPYING.  If not, write to\n *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\n *\n */\n"

static char *CurrentLine;

void PrintUsage()
{
	printf("X3DGen [skip_file]\n"
			"\nGPAC X3D Scene Graph generator\n"
			"\n"
			"\nskip_file: txt file with list of nodes to leave unimplemented"
			"Generated Files are directly updated in the GPAC distribution - do NOT try to change this\n\n"
			"Written by Jean Le Feuvre - (c) 2000-2005\n"
			);
}

//a node field
typedef struct
{
	char type[50];
	//SFxxx, MFxxx
	char familly[50];
	//name
	char name[1000];
	//default value
	char def[100];
	//bounds
	u32 hasBounds;
	char b_min[20];
	char b_max[20];
} X3DField;

//NDTs

//a BIFS node
typedef struct
{
	char name[1000];
	//NDT info. NDT are created in alphabetical order
	GF_List *NDT;
	GF_List *Fields;
	u8 hasDefault;
	char Child_NDT_Name[1000];
	u8 skip_impl;

} X3DNode;


void skip_sep(char *sep)
{
	//skip separaors
	while (*CurrentLine && strchr(sep, *CurrentLine)) {
		CurrentLine = CurrentLine + 1;
		//end of line - no token
		if (*CurrentLine == '\n') return;
	}
}

//note that we increment the line no matter what
u32 GetNextToken(char *token, char *sep)
{
	u32 i , j = 0;

	strcpy(token, "");
	
	//skip separaors
	while (*CurrentLine && strchr(sep, *CurrentLine)) {
		CurrentLine = CurrentLine + 1;
		j ++;
		//end of line - no token
		if (*CurrentLine == '\n') return 0;
	}

	//copy token untill next blank
	i=0;
	while (1) {
		//bad line
		if (! *CurrentLine) {
			token[i] = 0;
			return 0;
		}
		//end of token or end of line
		if (strchr(sep, *CurrentLine) || (*CurrentLine == '\n') ) {
			token[i] = 0;
			CurrentLine = CurrentLine + 1;
			return i;
		} else {
			token[i] = *CurrentLine;
		}
		CurrentLine = CurrentLine + 1;
		i++;
		j++;
	}
	return 1;
}

X3DField *BlankField()
{
	X3DField *n = malloc(sizeof(X3DField));
	memset(n, 0, sizeof(X3DField));
	return n;
}


X3DNode *BlankNode()
{
	X3DNode *n = malloc(sizeof(X3DNode));
	memset(n, 0, sizeof(X3DNode));
	n->NDT = gf_list_new();
	n->Fields = gf_list_new();
	return n;
}

u8 IsNDT(GF_List *NDTs, char *famName)
{
	u32 i;
	char *ndtName;
	for (i=0; i<gf_list_count(NDTs); i++) {
		ndtName = gf_list_get(NDTs, i);
		//remove SF / MF as we don't need that
		if (!strcmp(ndtName+2, famName+2)) return 1;
	}
	return 0;
}

void CheckInTable(char *token, GF_List *NDTs)
{
	u32 i;
	char *p;
	for (i=0; i<gf_list_count(NDTs); i++) {
		p = gf_list_get(NDTs, i);
		if (!strcmp(p, token)) return;
	}
	p = malloc(strlen(token)+1);
	strcpy(p, token);
	gf_list_add(NDTs, p);
}

/*type: 0: header, 1: source*/
FILE *BeginFile(u32 type)
{
	FILE *f;

	char sPath[GF_MAX_PATH];

	if (!type) {
		sprintf(sPath, "..%c..%c..%cinclude%cgpac%cnodes_x3d.h", GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR);
	} else {
		sprintf(sPath, "..%c..%c..%csrc%cscenegraph%cx3d_nodes.c", GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR, GF_PATH_SEPARATOR);
	}
	
	f = fopen(sPath, "wt");
	fprintf(f, "%s\n", COPYRIGHT);

	{
		time_t rawtime;
		time(&rawtime);
		fprintf(f, "\n/*\n\tDO NOT MOFIFY - File generated on GMT %s\n\tBY X3DGen for GPAC Version %s\n*/\n\n", asctime(gmtime(&rawtime)), GPAC_VERSION);
	}

	if (!type) {
		fprintf(f, "#ifndef _GF_X3D_NODES_H\n");
		fprintf(f, "#define _GF_X3D_NODES_H\n\n");
		fprintf(f, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n");
	}
	return f;
}

void EndFile(FILE *f, u32 type)
{
	if (!type) {
		fprintf(f, "#ifdef __cplusplus\n}\n#endif\n\n");
		fprintf(f, "\n\n#endif\t\t/*_GF_X3D_NODES_H*/\n\n");
	}
	fclose(f);
}

void TranslateToken(char *token)
{
	if (!strcmp(token, "+I") || !strcmp(token, "I")) {
		strcpy(token, "GF_MAX_FLOAT");
	}
	else if (!strcmp(token, "-I")) {
		strcpy(token, "GF_MIN_FLOAT");
	}
}



void WriteNodesFile(GF_List *BNodes, GF_List *NDTs)
{
	FILE *f;
	u32 i, j;
	X3DNode *n;
	X3DField *bf;
	f = BeginFile(0);

	fprintf(f, "#include <gpac/scenegraph_vrml.h>\n\n");

	//write all tags
	fprintf(f, "\n\nenum {\n");
	
	for (i=0; i<gf_list_count(BNodes); i++) {
		n = gf_list_get(BNodes, i);
		if (i)
			fprintf(f, ",\n\tTAG_X3D_%s", n->name);
		else
			fprintf(f, "\tTAG_X3D_%s = GF_NODE_RANGE_FIRST_X3D", n->name);
	}
	fprintf(f, ",\n\tTAG_LastImplementedX3D\n};\n\n");

	for (i=0; i<gf_list_count(BNodes); i++) {
		n = gf_list_get(BNodes, i);
		if (n->skip_impl) continue;
		fprintf(f, "typedef struct _tagX3D%s\n{\n", n->name);
		fprintf(f, "\tBASE_NODE\n");

		/*write children field*/
		for (j=0; j<gf_list_count(n->Fields); j++) {
			bf = gf_list_get(n->Fields, j);
			if (!stricmp(bf->name, "addChildren") || !strcmp(bf->name, "removeChildren")) continue;
			if (strcmp(bf->type, "eventOut") && !strcmp(bf->name, "children")) {
				fprintf(f, "\tVRML_CHILDREN\n");
				break;
			}
		}
		for (j=0; j<gf_list_count(n->Fields); j++) {
			bf = gf_list_get(n->Fields, j);
			
			if (!strcmp(bf->name, "addChildren") || !strcmp(bf->name, "removeChildren")) continue;
			if (strcmp(bf->type, "eventOut") && !strcmp(bf->name, "children")) continue;

			if (strstr(bf->familly, "Node")) {		
				//this is a POINTER to a node 
				if (strstr(bf->familly, "SF")) {
					fprintf(f, "\tGF_Node *%s;\t/*%s*/\n", bf->name, bf->type);
				} else {
					//this is a POINTER to a chain
					fprintf(f, "\tGF_List *%s;\t/*%s*/\n", bf->name, bf->type);
				}
			} else {
				fprintf(f, "\t%s %s;\t/*%s*/\n", bf->familly, bf->name, bf->type);
			}
			if (!strcmp(bf->type, "eventIn")) 
				fprintf(f, "\tvoid (*on_%s)(GF_Node *pThis);\t/*eventInHandler*/\n", bf->name);
		}
		fprintf(f, "} X_%s;\n\n\n", n->name);
	}

	EndFile(f, 0);

}

void WriteNodeFields(FILE *f, X3DNode *n)
{
	u32 i;
	X3DField *bf;

	fprintf(f, "\nstatic u32 %s_get_field_count(GF_Node *node, u8 dummy)\n{\n\treturn %d;\n}\n\n", n->name, gf_list_count(n->Fields));
	fprintf(f, "static GF_Err %s_get_field(GF_Node *node, GF_FieldInfo *info)\n{\n\tswitch (info->fieldIndex) {\n", n->name);
	for (i=0;i<gf_list_count(n->Fields); i++) {
		bf = gf_list_get(n->Fields, i);

		fprintf(f, "\tcase %d:\n", i);
		
		fprintf(f, "\t\tinfo->name = \"%s\";\n", bf->name);

		//skip all eventIn
		if (!strcmp(bf->type, "eventIn")) {
			fprintf(f, "\t\tinfo->eventType = GF_SG_EVENT_IN;\n");
			fprintf(f, "\t\tinfo->on_event_in = ((X_%s *)node)->on_%s;\n", n->name, bf->name);
		}
		else if (!strcmp(bf->type, "eventOut")) {
			fprintf(f, "\t\tinfo->eventType = GF_SG_EVENT_OUT;\n");
		}
		else if (!strcmp(bf->type, "field")) {
			fprintf(f, "\t\tinfo->eventType = GF_SG_EVENT_FIELD;\n");
		}
		else {
			fprintf(f, "\t\tinfo->eventType = GF_SG_EVENT_EXPOSED_FIELD;\n");
		}

		if (strstr(bf->familly, "Node")) {
			if (strstr(bf->familly, "MF")) {
				fprintf(f, "\t\tinfo->fieldType = GF_SG_VRML_MFNODE;\n");
			} else {
				fprintf(f, "\t\tinfo->fieldType = GF_SG_VRML_SFNODE;\n");
			}
			//always remove the SF or MF, as all NDTs are SFXXX
			fprintf(f, "\t\tinfo->NDTtype = NDT_SF%s;\n", bf->familly+2);
			fprintf(f, "\t\tinfo->far_ptr = & ((X_%s *)node)->%s;\n", n->name, bf->name);
		} else {
			char szName[20];
			strcpy(szName, bf->familly);
			strupr(szName);
			//no ext type
			fprintf(f, "\t\tinfo->fieldType = GF_SG_VRML_%s;\n", szName);
			fprintf(f, "\t\tinfo->far_ptr = & ((X_%s *) node)->%s;\n", n->name, bf->name);
		}
		fprintf(f, "\t\treturn GF_OK;\n");
	}
	fprintf(f, "\tdefault:\n\t\treturn GF_BAD_PARAM;\n\t}\n}\n\n");

}

void WriteNodeCode(GF_List *BNodes, FILE *vrml_code)
{
	char token[20], tok[20];
	char *store;
	u32 i, j, k, go;
	X3DField *bf;
	X3DNode *n;

	fprintf(vrml_code, "\n#include <gpac/nodes_x3d.h>\n");
	fprintf(vrml_code, "\n#include <gpac/internal/scenegraph_dev.h>\n");
	fprintf(vrml_code, "\n/*for NDT tag definitions*/\n#include <gpac/nodes_mpeg4.h>\n");

	for (k=0; k<gf_list_count(BNodes); k++) {
		n = gf_list_get(BNodes, k);
		if (n->skip_impl) continue;
		fprintf(vrml_code, "\n/*\n\t%s Node deletion\n*/\n\n", n->name);
		fprintf(vrml_code, "static void %s_Del(GF_Node *node)\n{\n\tX_%s *p = (X_%s *) node;\n", n->name, n->name, n->name);

		for (i=0; i<gf_list_count(n->Fields); i++) {
			bf = gf_list_get(n->Fields, i);
			//nothing on child events
			if (!strcmp(bf->name, "addChildren")) continue;
			if (!strcmp(bf->name, "removeChildren")) continue;
			
			//delete all children node
			if (strcmp(bf->type, "eventOut") && !strcmp(bf->name, "children")) {
				fprintf(vrml_code, "\tgf_sg_vrml_parent_reset(node);\t\n");
				continue;
			}

			//delete ALL fields that must be deleted: this includes eventIn and out since 
			//all fields are defined in the node
			if (!strcmp(bf->familly, "MFInt")
				|| !strcmp(bf->familly, "MFFloat")
				|| !strcmp(bf->familly, "MFDouble")
				|| !strcmp(bf->familly, "MFBool")
				|| !strcmp(bf->familly, "MFInt32")
				|| !strcmp(bf->familly, "MFColor")
				|| !strcmp(bf->familly, "MFRotation")
				|| !strcmp(bf->familly, "MFString")
				|| !strcmp(bf->familly, "MFTime")
				|| !strcmp(bf->familly, "MFVec2f")
				|| !strcmp(bf->familly, "MFVec3f")
				|| !strcmp(bf->familly, "MFVec4f")
				|| !strcmp(bf->familly, "MFVec2d")
				|| !strcmp(bf->familly, "MFVec3d")
				|| !strcmp(bf->familly, "MFURL")
				|| !strcmp(bf->familly, "MFScript")
				|| !strcmp(bf->familly, "SFString")
				|| !strcmp(bf->familly, "SFURL")
				|| !strcmp(bf->familly, "SFImage")
				
				) {
				char szName[500];
				strcpy(szName, bf->familly);
				strlwr(szName);
				fprintf(vrml_code, "\tgf_sg_%s_del(p->%s);\n", szName, bf->name);
			} else if (strstr(bf->familly, "Node")) {		
				//this is a POINTER to a node 
				if (strstr(bf->familly, "SF")) {
					fprintf(vrml_code, "\tgf_node_unregister((GF_Node *) p->%s, node);\t\n", bf->name);
				} else {
					//this is a POINTER to a chain
					fprintf(vrml_code, "\tgf_node_list_del((GF_List *) p->%s, node);\t\n", bf->name);
				}
			}
		}
		/*avoids gcc warnings in case no field to delete*/
		fprintf(vrml_code, "\tgf_node_free((GF_Node *)p);\n}\n\n");

		//node fields
		WriteNodeFields(vrml_code, n);

		//
		//		Constructor
		//

		fprintf(vrml_code, "\n\nstatic GF_Node *%s_Create()\n{\n\tX_%s *p;\n\tGF_SAFEALLOC(p, sizeof(X_%s));\n", n->name, n->name, n->name);
		fprintf(vrml_code, "\tif(!p) return NULL;\n");
		fprintf(vrml_code, "\tgf_node_setup((GF_Node *)p, TAG_X3D_%s);\n", n->name);

		for (i=0; i<gf_list_count(n->Fields); i++) {
			bf = gf_list_get(n->Fields, i);
			//setup all children node
			if (strcmp(bf->type, "eventOut") && !strcmp(bf->name, "children")) {
				fprintf(vrml_code, "\tgf_sg_vrml_parent_setup((GF_Node *) p);\n");
				break;
			}
			else if ( strstr(bf->familly, "Node") && strncmp(bf->type, "event", 5) ) {		
				//this is a POINTER to a node 
				if (strstr(bf->familly, "MF")) {
					//this is a POINTER to a chain

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?