/* ZynAddSubFX - a software synthesizer XMLwrapper.C - XML wrapper Copyright (C) 2003-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program 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 General Public License (version 2) for more details. You should have received a copy of the GNU General Public License (version 2) along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "XMLwrapper.h" #include #include #include #include "../globals.h" #include "Util.h" int xml_k=0; char tabs[STACKSIZE+2]; const char *XMLwrapper_whitespace_callback(mxml_node_t *node,int where){ const char *name=node->value.element.name; if ((where==MXML_WS_BEFORE_OPEN)&&(!strcmp(name,"?xml"))) return(NULL); if ((where==MXML_WS_BEFORE_CLOSE)&&(!strcmp(name,"string"))) return(NULL); if ((where==MXML_WS_BEFORE_OPEN)||(where==MXML_WS_BEFORE_CLOSE)) { /* const char *tmp=node->value.element.name; if (tmp!=NULL) { if ((strstr(tmp,"par")!=tmp)&&(strstr(tmp,"string")!=tmp)) { printf("%s ",tmp); if (where==MXML_WS_BEFORE_OPEN) xml_k++; if (where==MXML_WS_BEFORE_CLOSE) xml_k--; if (xml_k>=STACKSIZE) xml_k=STACKSIZE-1; if (xml_k<0) xml_k=0; printf("%d\n",xml_k); printf("\n"); }; }; int i=0; for (i=1;i"); char *end=strstr(xmldata,""); if ((start==NULL)||(end==NULL)||(start>end)) { delete(xmldata); return(false); }; end+=strlen(""); end[0]='\0'; tree=mxmlNewElement(MXML_NO_PARENT,"?xml"); node=root=mxmlLoadString(tree,xmldata,MXML_OPAQUE_CALLBACK); if (root==NULL) { delete(xmldata); mxmlDelete(tree); node=root=tree=NULL; return(false); }; root=mxmlFindElement(tree,tree,"INFORMATION",NULL,NULL,MXML_DESCEND); push(root); if (root==NULL){ delete(xmldata); mxmlDelete(tree); node=root=tree=NULL; return(false); }; information.PADsynth_used=getparbool("PADsynth_used",false); exitbranch(); if (tree!=NULL) mxmlDelete(tree); delete(xmldata); node=root=tree=NULL; return(true); }; /* SAVE XML members */ int XMLwrapper::saveXMLfile(char *filename){ char *xmldata=getXMLdata(); if (xmldata==NULL) return(-2); int compression=config.cfg.GzipCompression; int fnsize=strlen(filename)+100; char *filenamenew=new char [fnsize]; snprintf(filenamenew,fnsize,"%s",filename); int result=dosavefile(filenamenew,compression,xmldata); delete(filenamenew); delete(xmldata); return(result); }; char *XMLwrapper::getXMLdata(){ xml_k=0; ZERO(tabs,STACKSIZE+2); mxml_node_t *oldnode=node; node=info; //Info storing addparbool("PADsynth_used",information.PADsynth_used); node=oldnode; char *xmldata=mxmlSaveAllocString(tree,XMLwrapper_whitespace_callback); return(xmldata); }; int XMLwrapper::dosavefile(char *filename,int compression,char *xmldata){ if (compression==0){ FILE *file; file=fopen(filename,"w"); if (file==NULL) return(-1); fputs(xmldata,file); fclose(file); } else { if (compression>9) compression=9; if (compression<1) compression=1; char options[10]; snprintf(options,10,"wb%d",compression); gzFile gzfile; gzfile=gzopen(filename,options); if (gzfile==NULL) return(-1); gzputs(gzfile,xmldata); gzclose(gzfile); }; return(0); }; void XMLwrapper::addpar(char *name,int val){ addparams2("par","name",name,"value",int2str(val)); }; void XMLwrapper::addparreal(char *name,REALTYPE val){ addparams2("par_real","name",name,"value",real2str(val)); }; void XMLwrapper::addparbool(char *name,int val){ if (val!=0) addparams2("par_bool","name",name,"value","yes"); else addparams2("par_bool","name",name,"value","no"); }; void XMLwrapper::addparstr(char *name,char *val){ mxml_node_t *element=mxmlNewElement(node,"string"); mxmlElementSetAttr(element,"name",name); mxmlNewText(element,0,val); }; void XMLwrapper::beginbranch(char *name){ push(node); node=addparams0(name); }; void XMLwrapper::beginbranch(char *name,int id){ push(node); node=addparams1(name,"id",int2str(id)); }; void XMLwrapper::endbranch(){ node=pop(); }; /* LOAD XML members */ int XMLwrapper::loadXMLfile(const char *filename){ if (tree!=NULL) mxmlDelete(tree); tree=NULL; ZERO(&parentstack,(int)sizeof(parentstack)); ZERO(&values,(int)sizeof(values)); stackpos=0; char *xmldata=doloadfile(filename); if (xmldata==NULL) return(-1);//the file could not be loaded or uncompressed root=tree=mxmlLoadString(NULL,xmldata,MXML_OPAQUE_CALLBACK); delete(xmldata); if (tree==NULL) return(-2);//this is not XML node=root=mxmlFindElement(tree,tree,"ZynAddSubFX-data",NULL,NULL,MXML_DESCEND); if (root==NULL) return(-3);//the XML doesnt embbed zynaddsubfx data push(root); values.xml_version.major=str2int(mxmlElementGetAttr(root,"version-major")); values.xml_version.minor=str2int(mxmlElementGetAttr(root,"version-minor")); return(0); }; char *XMLwrapper::doloadfile(const char *filename){ char *xmldata=NULL; int filesize=-1; //try get filesize as gzip data (first) gzFile gzfile=gzopen(filename,"rb"); if (gzfile!=NULL){//this is a gzip file // first check it's size while(!gzeof(gzfile)) { gzseek (gzfile,1024*1024,SEEK_CUR); if (gztell(gzfile)>10000000) { gzclose(gzfile); goto notgzip;//the file is too big }; }; filesize=gztell(gzfile); //rewind the file and load the data xmldata=new char[filesize+1]; ZERO(xmldata,filesize+1); gzrewind(gzfile); gzread(gzfile,xmldata,filesize); gzclose(gzfile); return (xmldata); } else {//this is not a gzip file notgzip: FILE *file=fopen(filename,"rb"); if (file==NULL) return(NULL); fseek(file,0,SEEK_END); filesize=ftell(file); xmldata=new char [filesize+1]; ZERO(xmldata,filesize+1); rewind(file); fread(xmldata,filesize,1,file); fclose(file); return(xmldata); }; }; bool XMLwrapper::putXMLdata(char *xmldata){ if (tree!=NULL) mxmlDelete(tree); tree=NULL; ZERO(&parentstack,(int)sizeof(parentstack)); ZERO(&values,(int)sizeof(values)); stackpos=0; if (xmldata==NULL) return (false); root=tree=mxmlLoadString(NULL,xmldata,MXML_OPAQUE_CALLBACK); if (tree==NULL) return(false); node=root=mxmlFindElement(tree,tree,"ZynAddSubFX-data",NULL,NULL,MXML_DESCEND); if (root==NULL) return (false);; push(root); return(true); }; int XMLwrapper::enterbranch(char *name){ node=mxmlFindElement(peek(),peek(),name,NULL,NULL,MXML_DESCEND_FIRST); if (node==NULL) return(0); push(node); return(1); }; int XMLwrapper::enterbranch(char *name,int id){ snprintf(tmpstr,TMPSTR_SIZE,"%d",id); node=mxmlFindElement(peek(),peek(),name,"id",tmpstr,MXML_DESCEND_FIRST); if (node==NULL) return(0); push(node); return(1); }; void XMLwrapper::exitbranch(){ pop(); }; int XMLwrapper::getbranchid(int min, int max){ int id=str2int(mxmlElementGetAttr(node,"id")); if ((min==0)&&(max==0)) return(id); if (idmax) id=max; return(id); }; int XMLwrapper::getpar(char *name,int defaultpar,int min,int max){ node=mxmlFindElement(peek(),peek(),"par","name",name,MXML_DESCEND_FIRST); if (node==NULL) return(defaultpar); const char *strval=mxmlElementGetAttr(node,"value"); if (strval==NULL) return(defaultpar); int val=str2int(strval); if (valmax) val=max; return(val); }; int XMLwrapper::getpar127(char *name,int defaultpar){ return(getpar(name,defaultpar,0,127)); }; int XMLwrapper::getparbool(char *name,int defaultpar){ node=mxmlFindElement(peek(),peek(),"par_bool","name",name,MXML_DESCEND_FIRST); if (node==NULL) return(defaultpar); const char *strval=mxmlElementGetAttr(node,"value"); if (strval==NULL) return(defaultpar); if ((strval[0]=='Y')||(strval[0]=='y')) return(1); else return(0); }; void XMLwrapper::getparstr(char *name,char *par,int maxstrlen){ ZERO(par,maxstrlen); node=mxmlFindElement(peek(),peek(),"string","name",name,MXML_DESCEND_FIRST); if (node==NULL) return; if (node->child==NULL) return; if (node->child->type!=MXML_OPAQUE) return; snprintf(par,maxstrlen,"%s",node->child->value.element.name); }; REALTYPE XMLwrapper::getparreal(char *name,REALTYPE defaultpar){ node=mxmlFindElement(peek(),peek(),"par_real","name",name,MXML_DESCEND_FIRST); if (node==NULL) return(defaultpar); const char *strval=mxmlElementGetAttr(node,"value"); if (strval==NULL) return(defaultpar); return(str2real(strval)); }; REALTYPE XMLwrapper::getparreal(char *name,REALTYPE defaultpar,REALTYPE min,REALTYPE max){ REALTYPE result=getparreal(name,defaultpar); if (resultmax) result=max; return(result); }; /** Private members **/ char *XMLwrapper::int2str(int x){ snprintf(tmpstr,TMPSTR_SIZE,"%d",x); return(tmpstr); }; char *XMLwrapper::real2str(REALTYPE x){ snprintf(tmpstr,TMPSTR_SIZE,"%g",x); return(tmpstr); }; int XMLwrapper::str2int(const char *str){ if (str==NULL) return(0); int result=strtol(str,NULL,10); return(result); }; REALTYPE XMLwrapper::str2real(const char *str){ if (str==NULL) return(0.0); REALTYPE result=strtod(str,NULL); return(result); }; mxml_node_t *XMLwrapper::addparams0(char *name){ mxml_node_t *element=mxmlNewElement(node,name); return(element); }; mxml_node_t *XMLwrapper::addparams1(char *name,char *par1,char *val1){ mxml_node_t *element=mxmlNewElement(node,name); mxmlElementSetAttr(element,par1,val1); return(element); }; mxml_node_t *XMLwrapper::addparams2(char *name,char *par1,char *val1,char *par2, char *val2){ mxml_node_t *element=mxmlNewElement(node,name); mxmlElementSetAttr(element,par1,val1); mxmlElementSetAttr(element,par2,val2); return(element); }; void XMLwrapper::push(mxml_node_t *node){ if (stackpos>=STACKSIZE-1) { printf("BUG!: XMLwrapper::push() - full parentstack\n"); return; }; stackpos++; parentstack[stackpos]=node; // printf("push %d - %s\n",stackpos,node->value.element.name); }; mxml_node_t *XMLwrapper::pop(){ if (stackpos<=0) { printf("BUG!: XMLwrapper::pop() - empty parentstack\n"); return (root); }; mxml_node_t *node=parentstack[stackpos]; parentstack[stackpos]=NULL; // printf("pop %d - %s\n",stackpos,node->value.element.name); stackpos--; return(node); }; mxml_node_t *XMLwrapper::peek(){ if (stackpos<=0) { printf("BUG!: XMLwrapper::peek() - empty parentstack\n"); return (root); }; return(parentstack[stackpos]); };