1 /*
2     Bank.h - Instrument Bank
3 
4     Original ZynAddSubFX author Nasca Octavian Paul
5     Copyright (C) 2002-2005 Nasca Octavian Paul
6     Copyright 2009-2010, Alan Calvert
7     Copyright 2014-2021 Will Godfrey & others
8 
9     This file is part of yoshimi, which is free software: you can redistribute
10     it and/or modify it under the terms of the GNU Library General Public
11     License as published by the Free Software Foundation; either version 2 of
12     the License, or (at your option) any later version.
13 
14     yoshimi is distributed in the hope that it will be useful, but WITHOUT ANY
15     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16     FOR A PARTICULAR PURPOSE.   See the GNU General Public License (version 2 or
17     later) for more details.
18 
19     You should have received a copy of the GNU General Public License along with
20     yoshimi; if not, write to the Free Software Foundation, Inc., 51 Franklin
21     Street, Fifth Floor, Boston, MA  02110-1301, USA.
22 
23     This file is a derivative of a ZynAddSubFX original.
24 
25 */
26 
27 #ifndef BANK_H
28 #define BANK_H
29 
30 #include "Misc/Part.h"
31 #include "Misc/FormatFuncs.h"
32 
33 #include <string>
34 #include <map>
35 
36 using std::string;
37 using std::map;
38 
39 typedef struct _InstrumentEntry
40 {
41     string name;
42     string filename;
43     int type;
44     bool used;
45     unsigned char PADsynth_used;
46     unsigned char ADDsynth_used;
47     unsigned char SUBsynth_used;
48     bool yoshiType;
49     _InstrumentEntry()
50         :name(""),
51          filename(""),
52          type(-1),
53          used(false),
54          PADsynth_used(0),
55          ADDsynth_used(0),
56          SUBsynth_used(0),
57          yoshiType(false)
58     {
59 
60     }
61     void clear()
62     {
63         used = false;
64         name.clear();
65         filename.clear();
66         PADsynth_used = 0;
67         ADDsynth_used = 0;
68         SUBsynth_used = 0;
69         yoshiType = false;
70     }
71 } InstrumentEntry; // Contains the leafname of the instrument.
72 
73 typedef map<int, InstrumentEntry> InstrumentEntryMap; // Maps instrument id to instrument entry.
74 
75 typedef struct _BankEntry
76 {
77     string dirname;
78     InstrumentEntryMap instruments;
79 } BankEntry; // Contains the bank directory name and the instrument map of the bank.
80 
81 typedef map<size_t, BankEntry> BankEntryMap; // Maps bank id to bank entry.
82 
83 
84 typedef struct _RootEntry
85 {
86     string path;
87     BankEntryMap banks;
88     size_t bankIdStep;
89     _RootEntry(): bankIdStep(1)
90     {}
91 } RootEntry; // Contains the root path and the bank map of the root.
92 
93 typedef map<size_t, RootEntry> RootEntryMap; // Maps root id to root entry.
94 
95 class SynthEngine;
96 
97 class Bank
98 {
99     friend class SynthEngine;
100 
101     public:
102         Bank(SynthEngine *_synth);
103         int getType(unsigned int ninstrument, size_t bank, size_t root);
104         string getname(unsigned int ninstrument, size_t bank, size_t root);
105         string getnamenumbered(unsigned int ninstrument, size_t bank, size_t root);
106         int setInstrumentName(const string& name, int slot, size_t bank, size_t root);
107         bool moveInstrument(unsigned int ninstrument, const string& newname, int newslot, size_t oldBank, size_t newBank, size_t oldRoot, size_t newRoot);
108              // if newslot==-1 then this is ignored, else it will be put on that slot
109 
110         int engines_used(size_t rootID, size_t bankID, unsigned int ninstrument);
111         bool emptyslot(size_t rootID, size_t bankID, unsigned int ninstrument);
112         string clearslot(unsigned int ninstrument, size_t rootID, size_t bankID);
113         bool savetoslot(size_t rootID, size_t bankID, int ninstrument, int npart);
114         string swapslot(unsigned int n1, unsigned int n2, size_t bank1, size_t bank2, size_t root1, size_t root2);
115         string swapbanks(unsigned int firstID, unsigned int secondID, size_t firstRoot, size_t secondRoot);
116         string getBankName(int bankID, size_t rootID);
117         bool isDuplicateBankName(size_t rootID, const string& name);
118         int getBankSize(int bankID, size_t rootID);
119         int changeBankName(size_t rootID, size_t bankID, const string& newName);
120         void checkbank(size_t rootID, size_t banknum);
121         bool loadbank(size_t rootID, size_t banknum);
122         string exportBank(const string& exportdir, size_t rootID, unsigned int bankID);
123         string importBank(string importdir, size_t rootID, unsigned int bankID);
124         bool isDuplicate(size_t rootID, size_t bankID, int pos, const string filename);
125         bool newIDbank(const string& newbankdir, unsigned int bankID, size_t rootID = 0xff);
126         bool newbankfile(const string& newbankdir, size_t rootID);
127         string removebank(unsigned int bankID, size_t rootID = 0xff);
128         bool removeRoot(size_t rootID);
129         bool changeRootID(size_t oldID, size_t newID);
130 
131         bool setCurrentRootID(size_t newRootID);
132         unsigned int findFirstBank(size_t newRootID);
133         bool setCurrentBankID(size_t newBankID, bool ignoreMissing = true);
134         size_t addRootDir(const string& newRootDir);
135         bool parseBanksFile(XMLwrapper *xml);
136         bool installRoots();
137         bool installNewRoot(size_t rootID, string rootdir, bool reload = false);
138         void saveToConfigFile(XMLwrapper *xml);
139 
140         string getBankPath(size_t rootID, size_t bankID);
141         string getRootPath(size_t rootID);
142         string getFullPath(size_t rootID, size_t bankID, size_t ninstrument);
143 
144         const BankEntryMap &getBanks(size_t rootID);
145         const RootEntryMap &getRoots();
146         const BankEntry &getBank(size_t bankID, size_t rootID = UNUSED);
147 
148         string getBankFileTitle(size_t root, size_t bank);
149         string getRootFileTitle(size_t root);
150         int InstrumentsInBanks;
151         int BanksInRoots;
152         int readVersion(void)
153             {return BanksVersion;}
154         void writeVersion(int version)
155             {BanksVersion = version;}
156         int BanksVersion;
157         void checkLocalBanks(void);
158         size_t generateSingleRoot(const string& newRoot, bool clear = true);
159 
160     private:
161 
162         inline void splitNumFromName(int &num, string &name)
163         {
164             int chk = func::findSplitPoint(name);
165             if (chk > 0)
166             {
167                 num = func::string2int(name.substr(0, chk)) - 1;
168 
169                 // remove "NNNN-" from instrument name
170                 name = name.substr(chk + 1);
171             }
172         }
173 
174         bool addtobank(size_t rootID, size_t bankID, int pos, const string filename, const string name);
175              // add an instrument to the bank, if pos is -1 try to find a position
176              // returns true if the instrument was added
177 
178         void deletefrombank(size_t rootID, size_t bankID, unsigned int pos);
179         bool isValidBank(string chkdir);
180 
181         const string defaultinsname;
182         SynthEngine *synth;
183 
184         RootEntryMap  roots;
185 
186         InstrumentEntry &getInstrumentReference(size_t rootID, size_t bankID, size_t ninstrument );
187         void updateShare(string bankdirs[], string baseDir, string shareID);
188         void checkShare(string sourceDir, string destinationDir);
189         bool transferDefaultDirs(string bankdirs[]);
190         bool transferOneDir(string bankdirs[], int baseNumber, int listNumber);
191 
192         void addDefaultRootDirs(string bankdirs[]);
193 
194         size_t getNewRootIndex();
195         size_t getNewBankIndex(size_t rootID);
196         string foundLocal;
197 };
198 
199 #endif /*BANK_H*/
200