#include <stdio.h>
#include <stdlib.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <string.h>

char *filehighlight;
char *fileselect;
char base[1024];
int xoffset;
int yoffset;
int bnum=0;
int xsize=720;
int ysize=480;
FILE *fpxml;

int chapter[1024],ctrans[1024],chapid[1024];
int menuid[10];
int ncha=0;

char *feature_src;
char *splash_src;
int feature_frames;
int splash_frames;
struct {
	char *src,*base;
	char action[100];
	int frame[100];
	int bnum;
	struct {
		char *label;
		int x0,y0,x1,y1;
		int left,right,up,down;
		int bid;
		int overlayid;
	} b[100];
	int vnum;
} m[10];
int mnum=-1;

int docmd(char *s){
	printf("$ %s\n",s);
	return system(s);
}

void getlrud(int k,int i){
	m[k].b[i].left=
		getleft(k,m[k].b[i].x0-1,(m[k].b[i].y0+m[k].b[i].y1)/2);
	m[k].b[i].right=
		getright(k,m[k].b[i].x1+1,(m[k].b[i].y0+m[k].b[i].y1)/2);
	m[k].b[i].up=
		getup(k,(m[k].b[i].x0+m[k].b[i].x1)/2,m[k].b[i].y0-1);
	m[k].b[i].down=
		getdown(k,(m[k].b[i].x0+m[k].b[i].x1)/2,m[k].b[i].y1+1);
}

int getdown(int k,int x,int y){
	int i,j;
	if(x>=720 || y>=480 || x<0 || y<0) return -1;
	for(i=0;i<720;i++){
		if(x+i<720) for(j=y;j<ysize;j++){
			int r=xywhicb(k,x+i,j);
			if(r!=-1) return r;
		}
		if(x-i>=0) for(j=y;j<ysize;j++){
			int r=xywhicb(k,x-i,j);
			if(r!=-1) return r;
		}
	}
	return -1;
}

int getup(int k,int x,int y){
	int i,j;
	if(x>=720 || y>=480 || x<0 || y<0) return -1;
	for(i=0;i<720;i++){
		if(x+i<720) for(j=y;j>=0;j--){
			int r=xywhicb(k,x+i,j);
			if(r!=-1) return r;
		}
		if(x-i>=0) for(j=y;j>=0;j--){
			int r=xywhicb(k,x-i,j);
			if(r!=-1) return r;
		}
	}
	return -1;
}

int getright(int k,int x,int y){
	int i,j;
	if(x>=720 || y>=480 || x<0 || y<0) return -1;
	for(j=0;j<480;j++){
		if(y+j<480) for(i=x;i<xsize;i++){
			int r=xywhicb(k,i,y+j);
			if(r!=-1) return r;
		}
		if(y-j>=0) for(i=x;i<xsize;i++){
			int r=xywhicb(k,i,y-j);
			if(r!=-1) return r;
		}
	}
	return -1;
}

int getleft(int k,int x,int y){
	int i,j;
	if(x>=720 || y>=480 || x<0 || y<0) return -1;
	for(j=0;j<480;j++){
		if(y+j<480) for(i=x;i>=0;i--){
			int r=xywhicb(k,i,y+j);
			if(r!=-1) return r;
		}
		if(y-j>=0) for(i=x;i>=0;i--){
			int r=xywhicb(k,i,y-j);
			if(r!=-1) return r;
		}
	}
	return -1;
}

int xywhicb(int k,int x, int y){
	int i;
	if(!bnum){
		fputs("Failed to initialize button array!\n",stderr);
		exit(5);
	}
	for(i=0;i<bnum;i++){
		if(m[k].b[i].x0<=x && x<=m[k].b[i].x1 &&
		   m[k].b[i].y0<=y && y<=m[k].b[i].y1) return i;
	}
	return -1;
}

static void
get_sub_xml(int k,xmlNode * a_node)
{
    xmlNode *cur_node;
    for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
        if (cur_node->type == XML_ELEMENT_NODE) {
			if(!strcasecmp(cur_node->name,"button")){
				char *p;
				p=xmlGetProp(cur_node,"label");
				m[k].b[bnum].label=p;
				p=xmlGetProp(cur_node,"x0");
				m[k].b[bnum].x0=atoi(p);
				p=xmlGetProp(cur_node,"y0");
				m[k].b[bnum].y0=atoi(p);
				p=xmlGetProp(cur_node,"x1");
				m[k].b[bnum].x1=atoi(p);
				p=xmlGetProp(cur_node,"y1");
				m[k].b[bnum].y1=atoi(p);
				bnum++;
			} else if(!strcasecmp(cur_node->name,"spu")){
				char *p;
				p=xmlGetProp(cur_node,"highlight");
				filehighlight=p;
				p=xmlGetProp(cur_node,"select");
				fileselect=p;
				p=xmlGetProp(cur_node,"xoffset");
				xoffset=atoi(p);
				p=xmlGetProp(cur_node,"yoffset");
				yoffset=atoi(p);
			}
        }
        get_sub_xml(k,cur_node->children);
    }
}

void parse_disk_xml(xmlNode *node){
	xmlNode *a;
	for(a=node;a;a=a->next){
		if(a->type==XML_ELEMENT_NODE){
			if(!strcasecmp(a->name,"feature")){
				char *p;
				p=xmlGetProp(a,"src");
				feature_src=p;
			} else if(!strcasecmp(a->name,"splash")){
				char *p;
				p=xmlGetProp(a,"src");
				splash_src=p;
			} else if(!strcasecmp(a->name,"disk")){
			} else if(!strcasecmp(a->name,"chapter")){
				char *p;
				p=xmlGetProp(a,"frame");
				chapter[ncha++]=atoi(p);
			} else if(!strcasecmp(a->name,"menu")){
				char *p;
				p=xmlGetProp(a,"src");
				m[++mnum].src=p;
				m[mnum].bnum=0;
			} else if(!strcasecmp(a->name,"button")){
				char *p;
				p=xmlGetProp(a,"action");
				if(p && (p[0]=='g' || p[0]=='G')){
					m[mnum].action[m[mnum].bnum]='g';
					p=xmlGetProp(a,"menu");
					m[mnum].frame[m[mnum].bnum++]=atoi(p);
				} else if(p && (p[0]=='p' || p[0]=='P')){
					m[mnum].action[m[mnum].bnum]='p';
					p=xmlGetProp(a,"frame");
					m[mnum].frame[m[mnum].bnum++]=atoi(p);
				} else {
					printf("Action missing in button %d in menu %s\n",
						m[mnum].bnum,m[mnum].src);
					exit(12);
				}
			} else {
				fprintf(stderr,"Unknown tag: %s\n",a->name);
				exit(31);
			}
		}
		parse_disk_xml(a->children);
	}
}

void makebmp(int k,int i){
	char buf[1024];
	sprintf(buf,"convert -crop %dx%d+%d+%d %s %s-%02d.png",
		m[k].b[i].x1-m[k].b[i].x0,
		m[k].b[i].y1-m[k].b[i].y0,
		m[k].b[i].x0-xoffset,
		m[k].b[i].y0-yoffset,
		filehighlight,base,i);
	docmd(buf);
	sprintf(buf,"cp white.png %sw-%02d.png",base,i);
	docmd(buf);
	sprintf(buf,
		"mogrify -draw \"image Over %d,%d %d,%d %s-%02d.png\" %sw-%02d.png",
		m[k].b[i].x0,m[k].b[i].y0,
		m[k].b[i].x1-m[k].b[i].x0,m[k].b[i].y1-m[k].b[i].y0,
		base,i,base,i);
	docmd(buf);
	sprintf(buf,"pngtopnm <%sw-%02d.png |\n"
		"  pnmscale -height=400 -width=720 |\n"
		"  ppmquant 4 |\n"
		"  ppmtobmp -bpp 4 >%sw-%02d.bmp",
		base,i,base,i);
	docmd(buf);
}

int obj=0;

static int cmpint(const void *x, const void *y){
	return *(int *)x-*(int *)y;
}

int getmoid(int k, int i){
	int j;
	if(m[k].action[i]=='p'){
		for(j=0;j<ncha;j++){
			if(m[k].frame[i]==chapter[j]) return chapid[j];
		}
		fprintf(stderr,"Unknown (k,i)=(%d,%d) frame at %d\n",
			k,i,m[k].frame[i]);
	} else if(m[k].action[i]=='g'){ 
		if(m[k].frame[i]>=1 && m[k].frame[i]<=mnum){
			return menuid[m[k].frame[i]-1];
		}
		fprintf(stderr,"Unknown (k,i)=(%d,%d) menu %d\n",
			k,i,m[k].frame[i]);
	} else {
		fprintf(stderr,"Unknown (k,i)=(%d,%d) action %c\n",
			k,i,m[k].action[i]);
	}
	exit(32);
}

void outnav(char *fmt,int k,int n){
	if(n==-1) return;
	fprintf(fpxml,fmt,m[k].b[n].bid);
}

void writexml(){
	int i,k,source,splashnum,featnum,mstart;
	int splashnumv,splashnuma,eaction,featid,englishid;
	if(!(fpxml=fopen("video.xml","w"))){
		fputs("Can't open video.xml for output!",stderr);
		exit(7);
	}
	fprintf(fpxml,"<DivXMediaManager objectID=\"%d\"\n"
		"\tmenuVersion=\"1\"\n"
		"\tdefaultMenuLanguage=\"en\"\n"
		"\tversion=\"1.0\">\n",obj++);
	fprintf(fpxml,"\t<TranslationTable objectID=\"%d\">\n",obj++);
	fprintf(fpxml,"\t\t<TranslationLookup objectID=\"%d\">\n",
		featnum=obj++);
	fprintf(fpxml,"\t\t\t<Translation objectID=\"%d\"\n"
		"\t\t\t\tlanguageCode=\"en\"\n"
		"\t\t\t\tvalue=\"Main Feature\" />\n",obj++);
	fprintf(fpxml,"\t\t</TranslationLookup>\n");
	fprintf(fpxml,"\t\t<TranslationLookup objectID=\"%d\">\n",
		splashnum=obj++);
	fprintf(fpxml,"\t\t\t<Translation objectID=\"%d\"\n"
		"\t\t\t\tlanguageCode=\"en\"\n"
		"\t\t\t\tvalue=\"Splash\" />\n",obj++);
	fprintf(fpxml,"\t\t</TranslationLookup>\n");
	for(k=0;k<ncha;k++){
		fprintf(fpxml,"\t\t<TranslationLookup objectID=\"%d\">\n",
			ctrans[k]=obj++);
		fprintf(fpxml,"\t\t\t<Translation objectID=\"%d\"\n"
			"\t\t\t\tlanguageCode=\"en\"\n"
			"\t\t\t\tvalue=\"Chapter %d\" />\n",
			obj++,k+1);
		fprintf(fpxml,"\t\t</TranslationLookup>\n");
	}
	fprintf(fpxml,"\t\t<TranslationLookup objectID=\"%d\">\n",
		englishid=obj++);
	fprintf(fpxml,"\t\t\t<Translation objectID=\"%d\"\n"
		"\t\t\t\tlanguageCode=\"en\"\n"
		"\t\t\t\tvalue=\"English\" />\n",obj++);
	fprintf(fpxml,"\t\t</TranslationLookup>\n");
	fprintf(fpxml,"\t</TranslationTable>\n");
	fprintf(fpxml,"\t<Media objectID=\"%d\">\n",obj++);
	fprintf(fpxml,"\t\t<MenuTracks objectID=\"%d\">\n",obj++);
	fprintf(fpxml,"\t\t\t<MediaSource objectID=\"%d\"\n"
		"\t\t\t\tmediaType=\"menuAvi\"\n"
		"\t\t\t\tlocation=\"%s\" />\n",
		source=obj++,splash_src);
	fprintf(fpxml,"\t\t\t<MediaTrack objectID=\"%d\"\n"
		"\t\t\t\tmediaSourceID=\"%d\"\n"
		"\t\t\t\tsourceTrackID=\"none\"\n"
		"\t\t\t\ttrackID=\"00dc\"\n"
		"\t\t\t\tstartFrame=\"0\"\n"
		"\t\t\t\tendFrame=\"%d\"\n"
		"\t\t\t\ttype=\"video\" />\n",
		splashnumv=obj++,source,splash_frames);
	fprintf(fpxml,"\t\t\t<MediaTrack objectID=\"%d\"\n"
		"\t\t\t\tmediaSourceID=\"%d\"\n"
		"\t\t\t\tsourceTrackID=\"none\"\n"
		"\t\t\t\ttrackID=\"01wb\"\n"
		"\t\t\t\tlanguageCode=\"en\"\n"
		"\t\t\t\ttranslationLookupID=\"%d\"\n"
		"\t\t\t\ttype=\"audio\"\n"
		"\t\t\t\tstrn=\"Audio - en-US;02\" />\n",
		splashnuma=obj++,source,splashnum);
	for(k=0;k<mnum;k++){
		fprintf(fpxml,"\t\t\t<MediaSource objectID=\"%d\"\n"
			"\t\t\t\tmediaType=\"menuAvi\"\n"
			"\t\t\t\tlocation=\"_%s.divx\" />\n",
			source=obj++,m[k].base);
		fprintf(fpxml,"\t\t\t<MediaTrack objectID=\"%d\"\n"
			"\t\t\t\tmediaSourceID=\"%d\"\n"
			"\t\t\t\tsourceTrackID=\"none\"\n"
			"\t\t\t\ttrackID=\"00dc\"\n"
			"\t\t\t\tstartFrame=\"0\"\n"
			"\t\t\t\tendFrame=\"151\"\n"
			"\t\t\t\ttype=\"video\" />\n",m[k].vnum=obj++,source);
		for(i=0;i<m[k].bnum;i++){
			fprintf(fpxml,"\t\t\t<MediaTrack objectId=\"%d\"\n"
				"\t\t\t\tmediaSourceID=\"%d\"\n"
				"\t\t\t\tsourceTrackID=\"none\"\n"
				"\t\t\t\ttrackID=\"01sb\"\n"
				"\t\t\t\tstartFrame=\"%d\"\n"
				"\t\t\t\tendFrame=\"%d\"\n"
				"\t\t\t\ttype=\"subtitle\" />\n",
				m[k].b[i].overlayid=obj++,source,i,i);
			m[k].b[i].bid=obj++;
		}
	}
	fprintf(fpxml,"\t\t</MenuTracks>\n");
	fprintf(fpxml,"\t\t<Title objectID=\"%d\"\n"
		"\t\t\ttranslationLookupID=\"%d\"\n"
		"\t\t\tdefaultAudioTrack=\"01wb\"\n"
		"\t\t\tdefaultSubtitleTrack=\"none\">\n",
		featid=obj++,featnum);
	fprintf(fpxml,"\t\t\t<MediaSource objectID=\"%d\"\n"
		"\t\t\t\tmediaType=\"featureAvi\"\n"
		"\t\t\t\tlocation=\"%s\" />\n",
		source=obj++,feature_src);
	for(k=0;k<ncha;k++){
		fprintf(fpxml,"\t\t\t<Chapter objectID=\"%d\"\n"
			"\t\t\t\ttranslationLookupID=\"%d\">\n",
			chapid[k]=obj++,ctrans[k]);
		fprintf(fpxml,"\t\t\t\t<MediaTrack objectID=\"%d\"\n"
			"\t\t\t\t\tmediaSourceID=\"%d\"\n"
			"\t\t\t\t\tsourceTrackID=\"none\"\n"
			"\t\t\t\t\ttrackID=\"00dc\"\n"
			"\t\t\t\t\tstartFrame=\"%d\"\n"
			"\t\t\t\t\tendFrame=\"%d\"\n"
			"\t\t\t\t\ttype=\"video\" />\n",
			obj++,source,chapter[k],chapter[k+1]-1);
		fprintf(fpxml,"\t\t\t\t<MediaTrack objectID=\"%d\"\n"
			"\t\t\t\t\tmediaSourceID=\"%d\"\n"
			"\t\t\t\t\tsourceTrackID=\"none\"\n"
			"\t\t\t\t\ttrackID=\"01wb\"\n"
			"\t\t\t\t\tlanguageCode=\"en\"\n"
			"\t\t\t\t\ttranslationLookupID=\"%d\"\n"
			"\t\t\t\t\ttype=\"audio\"\n"
			"\t\t\t\t\tstrn=\"Audio - en-US;02\" />\n",
			obj++,source,englishid);

		fprintf(fpxml,"\t\t\t</Chapter>\n");
	}
	fprintf(fpxml,"\t\t</Title>\n");
	fprintf(fpxml,"\t</Media>\n");
	for(k=0;k<mnum;k++) menuid[k]=obj++;
	fprintf(fpxml,"\t<LanguageMenus objectID=\"%d\"\n"
		"\t\tlanguageCode=\"en\"\n"
		"\t\tstartingMenuID=\"%d\"\n"
		"\t\trootMenuID=\"%d\">\n",
		obj++,mstart=obj++,menuid[0]);
	fprintf(fpxml,"\t\t<DivXMediaMenu objectID=\"%d\"\n"
		"\t\t\tbackgroundVideoID=\"%d\"\n"
		"\t\t\tbackgroundAudioID=\"%d\"\n"
		"\t\t\texitAction=\"\%d\"\n"
		"\t\t\tmenuType=\"other\">\n",
		mstart,splashnumv,splashnuma,eaction=obj++);
	fprintf(fpxml,"\t\t\t<Action objectID=\"%d\">\n",eaction);
	fprintf(fpxml,"\t\t\t\t<MenuTransitionAction objectID=\"%d\"\n"
		"\t\t\t\t\tmenuID=\"%d\" />\n",obj++,menuid[0]);
	fprintf(fpxml,"\t\t\t</Action>\n");

	fprintf(fpxml,"\t\t</DivXMediaMenu>\n");
	for(k=0;k<mnum;k++){
		fprintf(fpxml,"\t\t<DivXMediaMenu objectID=\"%d\"\n"
		"\t\t\tbackgroundVideoID=\"%d\"\n"
		"\t\t\tbackgroundAudioID=\"none\"\n"
		"\t\t\tstartingMenuItemID=\"%d\"\n"
		"\t\t\texitAction=\"\%d\"\n"
		"\t\t\tmenuType=\"title\">\n",
		menuid[k],m[k].vnum,m[k].b[0].bid,eaction=obj++);
		for(i=0;i<m[k].bnum;i++){
			int baction;
			fprintf(fpxml,"\t\t\t<ButtonMenu objectID=\"%d\"\n"
				"\t\t\t\toverlayID=\"%d\"\n"
				"\t\t\t\tselectAction=\"%d\"",
				m[k].b[i].bid,m[k].b[i].overlayid,baction=obj++);
			outnav("\n\t\t\t\trightAction=\"%d\"",k,m[k].b[i].right);
			outnav("\n\t\t\t\tleftAction=\"%d\"",k,m[k].b[i].left);
			outnav("\n\t\t\t\tupAction=\"%d\"",k,m[k].b[i].up);
			outnav("\n\t\t\t\tdownAction=\"%d\"",k,m[k].b[i].down);
			fprintf(fpxml,">\n");
			fprintf(fpxml,"\t\t\t\t<MenuRectangle objectID=\"%d\"\n"
				"\t\t\t\t\tleft=\"%d\"\n"
				"\t\t\t\t\ttop=\"%d\"\n"
				"\t\t\t\t\twidth=\"%d\"\n"
				"\t\t\t\t\theight=\"%d\" />\n",
				obj++,m[k].b[i].x0,(m[k].b[i].y0*5)/6,
				m[k].b[i].x1-m[k].b[i].x0,
				((m[k].b[i].y1-m[k].b[i].y0)*5)/6);
			fprintf(fpxml,"\t\t\t\t<Action objectID=\"%d\">\n",
				baction);
			if(m[k].action[i]=='p'){
				fprintf(fpxml,"\t\t\t\t\t<PlayAction objectID=\"%d\"\n"
					"\t\t\t\t\t\ttitleID=\"%d\"\n"
					"\t\t\t\t\t\tmediaObjectID=\"%d\" />\n",
					obj++,featid,getmoid(k,i));
			} else {
				fprintf(fpxml,
					"\t\t\t\t\t<MenuTransitionAction objectID=\"%d\"\n"
					"\t\t\t\t\t\tmenuID=\"%d\" />\n",
					obj++,getmoid(k,i));
			}
			fprintf(fpxml,"\t\t\t\t</Action>\n");
			fprintf(fpxml,"\t\t\t</ButtonMenu>\n");
		}
		fprintf(fpxml,"\t\t\t<Action objectID=\"%d\">\n",eaction);
		fprintf(fpxml,"\t\t\t\t<MenuTransitionAction objectID=\"%d\"\n"
			"\t\t\t\t\tmenuID=\"%d\" />\n",obj++,menuid[k]);
		fprintf(fpxml,"\t\t\t</Action>\n");
		fprintf(fpxml,"\t\t</DivXMediaMenu>\n");
	}
	fprintf(fpxml,"\t</LanguageMenus>\n");
	fprintf(fpxml,"</DivXMediaManager>\n");
	fclose(fpxml);
}

void fixctlc(char *infn, char *outfn){
	FILE *infp, *outfp;
	if(!(infp=fopen(infn,"r"))){
		fprintf(stderr,"fixctlc: can't open %s for input!\n",infn);
		exit(31);
	}
	if(!(outfp=fopen(outfn,"w"))){
		fprintf(stderr,"fixctlc: can't open %s for output!\n",outfn);
		exit(32);
	}
	{
		int c,cl;
		while(EOF!=(c=fgetc(infp))){
			if(c!=3&&cl!=3) fputc(c,outfp);
			cl=c;
		}
	}
	if(fclose(infp)){
		fprintf(stderr,"fixctlc: error closing %s!\n",infn);
		exit(33);
	}
	if(fclose(outfp)){
		fprintf(stderr,"fixctlc: error closing %s!\n",outfn);
		exit(34);
	}
}
		
void domenu(int k){
	xmlDoc *doc;
	xmlNode *node;
	char *filename,*fbase,infile[1024];
	char *p;
	int i;
	bnum=0;
	filename=m[k].src;
	p=rindex(filename,'.');
	if(!p){
		fprintf(stderr,"File %s has no extension!\n",filename);
		exit(13);
	}
	fbase=malloc(p-filename+16);
	if(!fbase){
		fprintf(stderr,"Error allocating %d bytes for fbase.\n",
			p-filename+16);
		exit(14);
	}
	strncpy(fbase,filename,p-filename);
	fbase[p-filename]=0;
	m[k].base=fbase;
	printf("m[%d].base filename is %s\n",k,m[k].base);
	{
		char cmd[1024],infn[512],outfn[512];
		sprintf(infn,"%s.xml",fbase);
		sprintf(outfn,"%s-fix.xml",fbase);
		sprintf(cmd,"spuunmux %s.mpg -o %s\n",fbase,fbase);
		docmd(cmd);
		fixctlc(infn,outfn);
	}
	sprintf(infile,"%s-fix.xml",fbase);
	sprintf(base,"%sb",fbase);
    doc = xmlReadFile(infile, NULL, 0);
    if(!doc){
        fprintf(stderr, "Failed to parse %s\n", infile);
		exit(2);
    }
    node = xmlDocGetRootElement(doc);
	if(!node || strcasecmp(node->name,"subpictures")){
		fputs("Not a subpictures xml file!\n",stderr);
		exit(3);
	}
    get_sub_xml(k,node);
	printf("highlight=%s ",filehighlight);
	printf("select=%s ",fileselect);
	printf("xoffset=%d ",xoffset);
	printf("yoffset=%d\n",yoffset);
	docmd("convert -size 720x480 xc:black white.png");
	for(i=0;i<bnum;i++){
		getlrud(k,i);
		makebmp(k,i);
	}
	for(i=0;i<bnum;i++){
		printf("m[%d].b[%d]: label=%s x0=%d y0=%d x1=%d y1=%d\n",
			k,i,m[k].b[i].label,
			m[k].b[i].x0,m[k].b[i].y0,
			m[k].b[i].x1,m[k].b[i].y1);
		printf("    left=%d right=%d up=%d down=%d\n",
			m[k].b[i].left,m[k].b[i].right,
			m[k].b[i].up,m[k].b[i].down);
	}
    xmlFreeDoc(doc);
    xmlCleanupParser();
	if(bnum!=m[k].bnum){
		printf("Number of buttons or %s inconsistent:\n",m[k].src);
		printf("   Image had %d buttons xml file had %d buttons.\n",
			bnum,m[k].bnum);
		exit(2);
	}

	{
		char cmd[1024];
		sprintf(cmd,"./palette %sw-00.bmp | head -4 >%s.txt",
			base,fbase);
		docmd(cmd);
	}
	{
		char filetxt[1024];
		FILE *txtp;
		sprintf(filetxt,"%s.txt",fbase);
		txtp=fopen(filetxt,"a");
		if(!txtp){
			printf("Error open %s for append!\n",filetxt);
			exit(14);
		}
		fprintf(txtp,"\nSUBPALETTE (");
		for(i=0;i<bnum;i++){
			fprintf(txtp,"%d ",i);
		}
		fprintf(txtp,")\n");
		for(i=0;i<bnum;i++){
			fprintf(txtp,"00:00:%02d.000    00:00:%02d.000"
				"   \"%sw-%02d.bmp\" (0 0 719 399)\n",i,i,base,i);
		}
		fclose(txtp);
	}
	
    xmlMemoryDump();
    return;
}

int main(int argc, char **argv) {
	char *filename;
	int i,k;
	xmlDoc *doc = 0;
	xmlNode *node= 0;
    LIBXML_TEST_VERSION
	puts("genxmux -- create a DivXMux xml specification!\n"
		"Version 2 June 2008 by Eric Olson GNU License.\n");
    if (argc != 2) {
		fprintf(stderr,"Need an xml <disk> description file!\n");
        exit(1);
	}
	filename=argv[1];
    doc = xmlReadFile(filename, NULL, 0);
    if(!doc){
        fprintf(stderr, "Failed to parse %s\n", filename);
		exit(2);
    }
    node = xmlDocGetRootElement(doc);

	if(!node || strcasecmp(node->name,"disk")){
		fputs("Note a disk xml file!\n",stderr);
		exit(11);
	}
	parse_disk_xml(node);	mnum++;
	printf("The feature presentation is %s\n",feature_src);
	for(i=0;i<mnum;i++){
		int j;
		printf("menu %d is %s\n",i,m[i].src);
		for(j=0;j<m[i].bnum;j++){
			printf("\tbutton[%d] is type %c to frame %d\n",
				j,m[i].action[j],m[i].frame[j]);
		}
	}
	xmlFreeDoc(doc);
    xmlCleanupParser();

	printf("processsing...\n");
	for(i=0;i<mnum;i++) domenu(i);

	printf("recoding and muxing menues...\n");
	for(i=0;i<mnum;i++){
		char cmd[2048];
		sprintf(cmd,
			"ffmpeg -i %s -vframes 1 -f yuv4mpegpipe -y /dev/stdout |\n"
			"  y4mscaler -O chromass=444 |\n"
			"  y4mtoppm |\n"
			"  ppmtoy4m -F 5:1 -n 152 -r -Ip -S420jpeg |\n"
			"  ffmpeg -f yuv4mpegpipe -i /dev/stdin -interlace 0 \\\n"
			"    -r 5/1 -aspect 720:400 -s 720x400 \\\n"
			"    -vcodec mpeg4 -vtag xvid \\\n"
			"    -qmin 4 -b 1800000 -y %s.avi\n",
			m[i].src,m[i].base);
		docmd(cmd);
		sprintf(cmd,
			"ffmpeg -i %s -vframes 1 -f yuv4mpegpipe -y /dev/stdout |\n"
			"  y4mscaler -O chromass=444 |\n"
			"  y4mtoppm |\n"
			"  pnmtopng > %s.png\n",
			m[i].src,m[i].base);
		docmd(cmd);
		sprintf(cmd,
			"wine /usr/local/exe/DivXMux.exe -s %s.txt "
			"-m -v %s.avi -o _%s.divx",
			m[i].base,m[i].base,m[i].base);
		docmd(cmd);
	}
	printf("Main feature:\n");
	{
		char cmd[1024];
		FILE *fp;
		sprintf(cmd,"yes n |\n"
			"  avidemux2_cli --load %s --info 2>/dev/null |\n"
			"  grep Number |\n"
			"  sed \"s/^.*: //;s/ .*//\" >feature.txt",
			feature_src);
		docmd(cmd);
		fp=fopen("feature.txt","r");
		if(!fp){
			fprintf(stderr,"Error--can't find # frames in %s.\n",
				feature_src);
			exit(27);
		}
		fscanf(fp,"%d",&feature_frames);
		printf("There are %d frames in %s.\n",
			feature_frames,feature_src);
	}
	printf("Splash:\n");
	{
		char cmd[1024];
		FILE *fp;
		sprintf(cmd,"yes n |\n"
			"  avidemux2_cli --load %s --info 2>/dev/null |\n"
			"  grep Number |\n"
			"  sed \"s/^.*: //;s/ .*//\" >splash.txt",
			splash_src);
		docmd(cmd);
		fp=fopen("splash.txt","r");
		if(!fp){
			fprintf(stderr,"Error--can't find # frames in %s.\n",
				splash_src);
			exit(27);
		}
		fscanf(fp,"%d",&splash_frames);
		printf("There are %d frames in %s.\n",
			splash_frames,splash_src);
	}
	for(k=0;k<mnum;k++) for(i=0;i<m[k].bnum;i++) if(m[k].action[i]=='p'){
		printf("chapter[%d]=m[%d].frame[%d]=%d\n",
		ncha,k,i,m[k].frame[i]);
		chapter[ncha++]=m[k].frame[i];
	}
	qsort(chapter,ncha,sizeof(int),cmpint);
	i=1;
	for(k=1;k<ncha;k++){
		if(chapter[i-1]!=chapter[k]) chapter[i++]=chapter[k];
	}
	ncha=i;
	chapter[ncha]=feature_frames;
	if(chapter[ncha-1]>=chapter[ncha]){
		fprintf(stderr,"Chapters are greater than total frames.\n");
		exit(28);
	}
	printf("Sorted chapters...");
	for(k=0;k<=ncha;k++){
		printf(" %d",chapter[k]);
	}
	printf("\n");

	writexml();
	printf("\nTo Mux your file use the command:\n\n"
		"wine /usr/local/exe/DivXMux.exe "
		"-x video.xml -t /tmp -o video.avi\n");
	exit(0);
}
