diff options
Diffstat (limited to 'muse/synti/zynaddsubfx/Misc/XMLwrapper.C')
-rw-r--r-- | muse/synti/zynaddsubfx/Misc/XMLwrapper.C | 533 |
1 files changed, 533 insertions, 0 deletions
diff --git a/muse/synti/zynaddsubfx/Misc/XMLwrapper.C b/muse/synti/zynaddsubfx/Misc/XMLwrapper.C new file mode 100644 index 00000000..0f35faf2 --- /dev/null +++ b/muse/synti/zynaddsubfx/Misc/XMLwrapper.C @@ -0,0 +1,533 @@ +/* + 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 <stdio.h> +#include <stdlib.h> +#include <zlib.h> + +#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<xml_k;i++) tabs[i]='\t'; + tabs[0]='\n';tabs[i+1]='\0'; + if (where==MXML_WS_BEFORE_OPEN) return(tabs); + else return("\n"); +*/ + return("\n"); + }; + + return(0); +}; + + +XMLwrapper::XMLwrapper(){ + ZERO(&parentstack,(int)sizeof(parentstack)); + ZERO(&values,(int)sizeof(values)); + + minimal=true; + stackpos=0; + + information.PADsynth_used=false; + + tree=mxmlNewElement(MXML_NO_PARENT,"?xml version=\"1.0\" encoding=\"UTF-8\"?"); +/* for mxml 2.1 (and older) + tree=mxmlNewElement(MXML_NO_PARENT,"?xml"); + mxmlElementSetAttr(tree,"version","1.0"); + mxmlElementSetAttr(tree,"encoding","UTF-8"); +*/ + + mxml_node_t *doctype=mxmlNewElement(tree,"!DOCTYPE"); + mxmlElementSetAttr(doctype,"ZynAddSubFX-data",NULL); + + node=root=mxmlNewElement(tree,"ZynAddSubFX-data"); + + mxmlElementSetAttr(root,"version-major","1"); + mxmlElementSetAttr(root,"version-minor","1"); + mxmlElementSetAttr(root,"ZynAddSubFX-author","Nasca Octavian Paul"); + + //make the empty branch that will contain the information parameters + info=addparams0("INFORMATION"); + + //save zynaddsubfx specifications + beginbranch("BASE_PARAMETERS"); + addpar("max_midi_parts",NUM_MIDI_PARTS); + addpar("max_kit_items_per_instrument",NUM_KIT_ITEMS); + + addpar("max_system_effects",NUM_SYS_EFX); + addpar("max_insertion_effects",NUM_INS_EFX); + addpar("max_instrument_effects",NUM_PART_EFX); + + addpar("max_addsynth_voices",NUM_VOICES); + endbranch(); + +}; + +XMLwrapper::~XMLwrapper(){ + if (tree!=NULL) mxmlDelete(tree); +}; + +bool XMLwrapper::checkfileinformation(char *filename){ + stackpos=0; + ZERO(&parentstack,(int)sizeof(parentstack)); + information.PADsynth_used=false; + + if (tree!=NULL) mxmlDelete(tree);tree=NULL; + char *xmldata=doloadfile(filename); + if (xmldata==NULL) return(-1);//the file could not be loaded or uncompressed + + + char *start=strstr(xmldata,"<INFORMATION>"); + char *end=strstr(xmldata,"</INFORMATION>"); + + if ((start==NULL)||(end==NULL)||(start>end)) { + delete(xmldata); + return(false); + }; + end+=strlen("</INFORMATION>"); + 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 (id<min) id=min; + else if (id>max) 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 (val<min) val=min; + else if (val>max) 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 (result<min) result=min; + else if (result>max) 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]); +}; + + + |