summaryrefslogtreecommitdiff
path: root/muse_qt4_evolution/synti/zynaddsubfx/Misc/Bank.C
diff options
context:
space:
mode:
Diffstat (limited to 'muse_qt4_evolution/synti/zynaddsubfx/Misc/Bank.C')
-rw-r--r--muse_qt4_evolution/synti/zynaddsubfx/Misc/Bank.C565
1 files changed, 565 insertions, 0 deletions
diff --git a/muse_qt4_evolution/synti/zynaddsubfx/Misc/Bank.C b/muse_qt4_evolution/synti/zynaddsubfx/Misc/Bank.C
new file mode 100644
index 00000000..9b2e8f75
--- /dev/null
+++ b/muse_qt4_evolution/synti/zynaddsubfx/Misc/Bank.C
@@ -0,0 +1,565 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ Bank.h - Instrument Bank
+ Copyright (C) 2002-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 "Bank.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <sys/stat.h>
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "Config.h"
+
+#define INSTRUMENT_EXTENSION ".xiz"
+
+//if this file exists into a directory, this make the directory to be considered as a bank, even if it not contains a instrument file
+#define FORCE_BANK_DIR_FILE ".bankdir"
+
+Bank::Bank(){
+
+
+ ZERO(defaultinsname,PART_MAX_NAME_LEN);
+ snprintf(defaultinsname,PART_MAX_NAME_LEN,"%s"," ");
+
+ for (int i=0;i<BANK_SIZE;i++){
+ ins[i].used=false;
+ ins[i].filename=NULL;
+ ins[i].info.PADsynth_used=false;
+ };
+ dirname=NULL;
+ clearbank();
+
+
+
+ for (int i=0;i<MAX_NUM_BANKS;i++){
+ banks[i].dir=NULL;
+ banks[i].name=NULL;
+ };
+
+ bankfiletitle=dirname;
+
+ loadbank(config.cfg.currentBankDir);
+
+};
+
+Bank::~Bank(){
+ for (int i=0;i<MAX_NUM_BANKS;i++){
+ if (banks[i].dir!=NULL) delete (banks[i].dir);
+ if (banks[i].name!=NULL) delete (banks[i].name);
+ };
+
+ clearbank();
+};
+
+/*
+ * Get the name of an instrument from the bank
+ */
+char *Bank::getname (unsigned int ninstrument){
+ if (emptyslot(ninstrument)) return (defaultinsname);
+ return (ins[ninstrument].name);
+};
+
+/*
+ * Get the numbered name of an instrument from the bank
+ */
+char *Bank::getnamenumbered (unsigned int ninstrument){
+ if (emptyslot(ninstrument)) return (defaultinsname);
+ snprintf(tmpinsname[ninstrument],PART_MAX_NAME_LEN+15,"%d. %s",ninstrument+1,getname(ninstrument));
+ return(tmpinsname[ninstrument]);
+};
+
+/*
+ * Changes the name of an instrument (and the filename)
+ */
+void Bank::setname(unsigned int ninstrument,const char *newname,int newslot){
+ if (emptyslot(ninstrument)) return;
+
+ char newfilename[1000+1],tmpfilename[100+1];
+
+ ZERO(newfilename,1001);
+ ZERO(tmpfilename,101);
+ if (newslot>=0) snprintf(tmpfilename,100,"%4d-%s",newslot+1,newname);
+ else snprintf(tmpfilename,100,"%4d-%s",ninstrument+1,newname);
+
+ //add the zeroes at the start of filename
+ for (int i=0;i<4;i++) if (tmpfilename[i]==' ') tmpfilename[i]='0';
+
+ //make the filenames legal
+ for (int i=0;i<(int) strlen(tmpfilename);i++) {
+ char c=tmpfilename[i];
+ if ((c>='0')&&(c<='9')) continue;
+ if ((c>='A')&&(c<='Z')) continue;
+ if ((c>='a')&&(c<='z')) continue;
+ if ((c=='-')||(c==' ')) continue;
+
+ tmpfilename[i]='_';
+ };
+
+ snprintf(newfilename,1000,"%s/%s.xiz",dirname,tmpfilename);
+
+// printf("rename %s -> %s\n",ins[ninstrument].filename,newfilename);//////////////
+
+ rename(ins[ninstrument].filename,newfilename);
+ if (ins[ninstrument].filename) delete(ins[ninstrument].filename);
+ ins[ninstrument].filename=new char[strlen(newfilename)+5];
+ snprintf(ins[ninstrument].filename,strlen(newfilename)+1,"%s",newfilename);
+ snprintf(ins[ninstrument].name,PART_MAX_NAME_LEN,"%s",&tmpfilename[5]);
+
+};
+
+/*
+ * Check if there is no instrument on a slot from the bank
+ */
+int Bank::emptyslot(unsigned int ninstrument){
+ if (ninstrument>=BANK_SIZE) return (1);
+ if (ins[ninstrument].filename==NULL) return(1);
+
+ if (ins[ninstrument].used) return (0);
+ else return(1);
+};
+
+/*
+ * Removes the instrument from the bank
+ */
+void Bank::clearslot(unsigned int ninstrument){
+ if (emptyslot(ninstrument)) return;
+
+// printf("remove %s \n",ins[ninstrument].filename);////////////////////////
+
+
+ remove(ins[ninstrument].filename);
+ deletefrombank(ninstrument);
+};
+
+/*
+ * Save the instrument to a slot
+ */
+void Bank::savetoslot(unsigned int ninstrument,Part *part){
+ clearslot(ninstrument);
+
+ const int maxfilename=200;
+ char tmpfilename[maxfilename+20];
+ ZERO(tmpfilename,maxfilename+20);
+
+ snprintf(tmpfilename,maxfilename,"%4d-%s",ninstrument+1,(char *)part->Pname);
+
+ //add the zeroes at the start of filename
+ for (int i=0;i<4;i++) if (tmpfilename[i]==' ') tmpfilename[i]='0';
+
+ //make the filenames legal
+ for (int i=0;i<(int)strlen(tmpfilename);i++) {
+ char c=tmpfilename[i];
+ if ((c>='0')&&(c<='9')) continue;
+ if ((c>='A')&&(c<='Z')) continue;
+ if ((c>='a')&&(c<='z')) continue;
+ if ((c=='-')||(c==' ')) continue;
+
+ tmpfilename[i]='_';
+ };
+
+ strncat(tmpfilename,".xiz",maxfilename+10);
+
+ int fnsize=strlen(dirname)+strlen(tmpfilename)+10;
+ char *filename=new char[fnsize+4];
+ ZERO(filename,fnsize+2);
+
+ snprintf(filename,fnsize,"%s/%s",dirname,tmpfilename);
+
+ remove(filename);
+ part->saveXML(filename);
+ addtobank(ninstrument,tmpfilename,(char *) part->Pname);
+
+ delete(filename);
+};
+
+/*
+ * Loads the instrument from the bank
+ */
+void Bank::loadfromslot(unsigned int ninstrument,Part *part){
+ if (emptyslot(ninstrument)) return;
+
+ part->defaultsinstrument();
+
+// printf("load: %s\n",ins[ninstrument].filename);
+
+ part->loadXMLinstrument(ins[ninstrument].filename);
+
+};
+
+
+/*
+ * Makes current a bank directory
+ */
+int Bank::loadbank(const char *bankdirname)
+ {
+ DIR *dir = opendir(bankdirname);
+ clearbank();
+
+ if (dir==NULL)
+ return -1;
+
+ if (dirname!=NULL)
+ delete(dirname);
+ dirname = new char[strlen(bankdirname)+1];
+ snprintf(dirname, strlen(bankdirname)+1, "%s",bankdirname);
+
+ bankfiletitle=dirname;
+
+ // printf("loadbank %s/\n",bankdirname);
+ struct dirent *fn;
+
+ while ((fn=readdir(dir))){
+ const char *filename= fn->d_name;
+
+ //sa verific daca e si extensia dorita
+ if (strstr(filename,INSTRUMENT_EXTENSION)==NULL) continue;
+
+ //verify if the name is like this NNNN-name (where N is a digit)
+ int no=0;
+ unsigned int startname=0;
+
+ for (unsigned int i=0;i<4;i++) {
+ if (strlen(filename)<=i) break;
+
+ if ((filename[i]>='0')&&(filename[i]<='9')) {
+ no=no*10+(filename[i]-'0');
+ startname++;
+ };
+ };
+
+
+ if ((startname+1)<strlen(filename)) startname++;//to take out the "-"
+
+ char name[PART_MAX_NAME_LEN+1];
+ ZERO(name,PART_MAX_NAME_LEN+1);
+ snprintf(name,PART_MAX_NAME_LEN,"%s",filename);
+
+ //remove the file extension
+ for (int i=strlen(name)-1;i>=2;i--){
+ if (name[i]=='.') {
+ name[i]='\0';
+ break;
+ };
+ };
+
+ if (no!=0){//the instrument position in the bank is found
+ addtobank(no-1,filename,&name[startname]);
+ } else {
+ addtobank(-1,filename,name);
+ };
+
+ };
+
+
+ closedir(dir);
+
+ if (dirname!=NULL) {
+ sprintf(config.cfg.currentBankDir,"%s",dirname);
+ };
+
+ return(0);
+};
+
+/*
+ * Makes a new bank, put it on a file and makes it current bank
+ */
+int Bank::newbank(const char *newbankdirname){
+ int result;
+ char tmpfilename[MAX_STRING_SIZE];
+ char bankdir[MAX_STRING_SIZE];
+ snprintf(bankdir,MAX_STRING_SIZE,"%s",config.cfg.bankRootDirList[0]);
+
+ if (((bankdir[strlen(bankdir)-1])!='/')&&((bankdir[strlen(bankdir)-1])!='\\')){
+ strncat(bankdir,"/",MAX_STRING_SIZE);
+ };
+ strncat(bankdir,newbankdirname,MAX_STRING_SIZE);
+#ifdef OS_WINDOWS
+ result=mkdir(bankdir);
+#else
+ result=mkdir(bankdir,S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+#endif
+ if (result<0) return(-1);
+
+ snprintf(tmpfilename,MAX_STRING_SIZE,"%s/%s",bankdir,FORCE_BANK_DIR_FILE);
+// printf("%s\n",tmpfilename);
+ FILE *tmpfile=fopen(tmpfilename,"w+");
+ fclose(tmpfile);
+
+ return(loadbank(bankdir));
+};
+
+/*
+ * Check if the bank is locked (i.e. the file opened was readonly)
+ */
+int Bank::locked(){
+ return(dirname==NULL);
+};
+
+/*
+ * Swaps a slot with another
+ */
+void Bank::swapslot(unsigned int n1, unsigned int n2){
+ if ((n1==n2)||(locked())) return;
+ if (emptyslot(n1)&&(emptyslot(n2))) return;
+ if (emptyslot(n1)){//change n1 to n2 in order to make
+ int tmp=n2;n2=n1;n1=tmp;
+ };
+
+ if (emptyslot(n2)){//this is just a movement from slot1 to slot2
+ setname(n1,getname(n1),n2);
+ ins[n2]=ins[n1];
+ ins[n1].used=false;
+ ins[n1].name[0]='\0';
+ ins[n1].filename=NULL;
+ ins[n1].info.PADsynth_used=0;
+ } else {//if both slots are used
+ if (strcmp(ins[n1].name,ins[n2].name)==0){//change the name of the second instrument if the name are equal
+ strncat(ins[n2].name,"2",PART_MAX_NAME_LEN);
+ };
+ setname(n1,getname(n1),n2);
+ setname(n2,getname(n2),n1);
+ ins_t tmp;
+ tmp.used=true;
+ strcpy(tmp.name,ins[n2].name);
+ char *tmpfilename=ins[n2].filename;
+ bool padsynth_used=ins[n2].info.PADsynth_used;
+
+ ins[n2]=ins[n1];
+ strcpy(ins[n1].name,tmp.name);
+ ins[n1].filename=tmpfilename;
+ ins[n1].info.PADsynth_used=padsynth_used;
+ };
+
+};
+
+
+//a helper function that compares 2 banks[] arrays
+int Bank_compar(const void *a,const void *b){
+ struct Bank::bankstruct *bank1= (Bank::bankstruct *)a;
+ struct Bank::bankstruct *bank2= (Bank::bankstruct *)b;
+ if (((bank1->name)==NULL)||((bank2->name)==NULL)) return(0);
+
+ int result=strcasecmp(bank1->name,bank2->name);
+ return(result<0);
+};
+
+
+/*
+ * Re-scan for directories containing instrument banks
+ */
+
+void Bank::rescanforbanks(){
+ for (int i=0;i<MAX_NUM_BANKS;i++){
+ if (banks[i].dir!=NULL) delete (banks[i].dir);
+ if (banks[i].name!=NULL) delete (banks[i].name);
+ banks[i].dir=NULL;
+ banks[i].name=NULL;
+ };
+
+ for (int i=0;i<MAX_BANK_ROOT_DIRS;i++) if (config.cfg.bankRootDirList[i]!=NULL) scanrootdir(config.cfg.bankRootDirList[i]);
+
+ //sort the banks
+ for (int j=0;j<MAX_NUM_BANKS-1;j++){
+ for (int i=j+1;i<MAX_NUM_BANKS;i++){
+ if (Bank_compar(&banks[i],&banks[j])) {
+ char *tmpname=banks[i].name;
+ char *tmpdir=banks[i].dir;
+
+ banks[i].name=banks[j].name;
+ banks[i].dir=banks[j].dir;
+
+ banks[j].name=tmpname;
+ banks[j].dir=tmpdir;
+
+ };
+ };
+ };
+
+ //remove duplicate bank names
+ int dupl=0;
+ for (int j=0;j<MAX_NUM_BANKS-1;j++){
+ for (int i=j+1;i<MAX_NUM_BANKS;i++){
+ if ((banks[i].name==NULL)||(banks[j].name==NULL)) continue;
+ if (strcmp(banks[i].name,banks[j].name)==0) {//add a [1] to the first bankname and [n] to others
+ char *tmpname=banks[i].name;
+ banks[i].name=new char[strlen(tmpname)+100];
+ sprintf(banks[i].name,"%s[%d]",tmpname,dupl+2);
+ delete(tmpname);
+
+ if (dupl==0){
+ char *tmpname=banks[j].name;
+ banks[j].name=new char[strlen(tmpname)+100];
+ sprintf(banks[j].name,"%s[1]",tmpname);
+ delete(tmpname);
+ };
+
+ dupl++;
+ } else dupl=0;
+ };
+ };
+
+};
+
+
+
+// private stuff
+
+void Bank::scanrootdir(char *rootdir){
+// printf("Scanning root dir:%s\n",rootdir);
+ DIR *dir=opendir(rootdir);
+ if (dir==NULL) return;
+
+ const int maxdirsize=1000;
+ struct {
+ char dir[maxdirsize];
+ char name[maxdirsize];
+ }bank;
+
+ char *separator="/";
+ if (strlen(rootdir)) {
+ char tmp=rootdir[strlen(rootdir)-1];
+ if ((tmp=='/') || (tmp=='\\')) separator="";
+ };
+
+ struct dirent *fn;
+ while ((fn=readdir(dir))){
+ const char *dirname=fn->d_name;
+ if (dirname[0]=='.') continue;
+
+ snprintf(bank.dir,maxdirsize,"%s%s%s/",rootdir,separator,dirname);
+ snprintf(bank.name,maxdirsize,"%s",dirname);
+ //find out if the directory contains at least 1 instrument
+ bool isbank=false;
+
+ DIR *d=opendir(bank.dir);
+ if (d==NULL) continue;
+
+ struct dirent *fname;
+
+ while((fname=readdir(d))){
+ if ((strstr(fname->d_name,INSTRUMENT_EXTENSION)!=NULL)||
+ (strstr(fname->d_name,FORCE_BANK_DIR_FILE)!=NULL)){
+ isbank=true;
+ break;//aici as putea pune in loc de break un update la un counter care imi arata nr. de instrumente din bank
+ };
+ };
+
+ closedir(d);
+
+ if (isbank) {
+ int pos=-1;
+ for (int i=1;i<MAX_NUM_BANKS;i++){ //banks[0] e liber intotdeauna
+ if (banks[i].name==NULL) {
+ pos=i;
+ break;
+ };
+ };
+
+ if (pos>=0) {
+ banks[pos].name=new char[maxdirsize];
+ banks[pos].dir=new char[maxdirsize];
+ snprintf(banks[pos].name,maxdirsize,"%s",bank.name);
+ snprintf(banks[pos].dir,maxdirsize,"%s",bank.dir);
+ };
+
+ };
+
+ };
+
+ closedir(dir);
+
+};
+
+void Bank::clearbank(){
+ for (int i=0;i<BANK_SIZE;i++) deletefrombank(i);
+ if (dirname!=NULL) delete(dirname);
+ bankfiletitle=NULL;
+ dirname=NULL;
+};
+
+int Bank::addtobank(int pos, const char *filename, const char* name){
+ if ((pos>=0)&&(pos<BANK_SIZE)){
+ if (ins[pos].used) pos=-1;//force it to find a new free position
+ } else if (pos>=BANK_SIZE) pos=-1;
+
+
+ if (pos<0) {//find a free position
+ for (int i=BANK_SIZE-1;i>=0;i--)
+ if (!ins[i].used) {
+ pos=i;
+ break;
+ };
+
+ };
+
+ if (pos<0) return (-1);//the bank is full
+
+ // printf("%s %d\n",filename,pos);
+
+ deletefrombank(pos);
+
+ ins[pos].used=true;
+ snprintf(ins[pos].name,PART_MAX_NAME_LEN,"%s",name);
+
+ snprintf(tmpinsname[pos],PART_MAX_NAME_LEN+10," ");
+
+ int len=strlen(filename)+1+strlen(dirname);
+ ins[pos].filename=new char[len+2];
+ ins[pos].filename[len+1]=0;
+ snprintf(ins[pos].filename,len+1,"%s/%s",dirname,filename);
+
+ //see if PADsynth is used
+ if (config.cfg.CheckPADsynth){
+ XMLwrapper *xml=new XMLwrapper();
+ xml->checkfileinformation(ins[pos].filename);
+
+ ins[pos].info.PADsynth_used=xml->information.PADsynth_used;
+ delete(xml);
+ } else ins[pos].info.PADsynth_used=false;
+
+ return(0);
+};
+
+bool Bank::isPADsynth_used(unsigned int ninstrument){
+ if (config.cfg.CheckPADsynth==0) return(0);
+ else return(ins[ninstrument].info.PADsynth_used);
+};
+
+
+void Bank::deletefrombank(int pos){
+ if ((pos<0)||(pos>=BANK_SIZE)) return;
+ ins[pos].used=false;
+ ZERO(ins[pos].name,PART_MAX_NAME_LEN+1);
+ if (ins[pos].filename!=NULL) {
+ delete (ins[pos].filename);
+ ins[pos].filename=NULL;
+ };
+
+ ZERO(tmpinsname[pos],PART_MAX_NAME_LEN+20);
+
+};
+