home *** CD-ROM | disk | FTP | other *** search
- /*
- ZynAddSubFX - a software synthesizer
-
- Bank.h - Instrument Bank
- Copyright (C) 2002-2004 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(){
- if (dirname!=NULL) {
- sprintf(config.cfg.currentBankDir,"%s",dirname);
- };
- 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);
- snprintf(ins[ninstrument].filename,1000,"%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);
-
- };
-
-
- /*
- * Load a bank from a file and makes it current
- */
- 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))){
- #ifndef OS_WINDOWS
- if (fn->d_type!=DT_REG) continue;
- #endif
- 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);
- 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);
-
- return(strcasecmp(bank1->name,bank2->name));
- };
-
- /*
- * 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]);
-
- qsort(banks,MAX_NUM_BANKS,sizeof(bankstruct),Bank_compar);
- };
-
-
-
- // 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))){
- #ifndef OS_WINDOWS
- if (fn->d_type!=DT_DIR) continue;//this is not a directory
- #endif
- 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))){
- #ifndef OS_WINDOWS
- if (fname->d_type!=DT_REG) continue;//this is not a regular file
- #endif
- 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+1];
- 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);
-
- };
-
-