LMMS
Loading...
Searching...
No Matches
BankDb.cpp
Go to the documentation of this file.
1#include "BankDb.h"
2#include "XMLwrapper.h"
3#include "Util.h"
4#include "../globals.h"
5#include <cstring>
6#include <dirent.h>
7#include <sys/stat.h>
8
9namespace zyncarla {
10
11static const char* INSTRUMENT_EXTENSION = ".xiz";
12
13using std::string;
16
18 :id(0), add(false), pad(false), sub(false), time(0)
19{}
20
21bool platform_strcasestr(const char *hay, const char *needle)
22{
23 int n = strlen(hay);
24 int m = strlen(needle);
25 for(int i=0; i<n; i++) {
26 int good = 1;
27 for(int j=0; j<m; ++j) {
28 if(toupper(hay[i+j]) != toupper(needle[j])) {
29 good = 0;
30 break;
31 }
32
33 }
34 if(good)
35 return 1;
36 }
37 return 0;
38
39}
40
41bool sfind(std::string hay, std::string needle)
42{
43 //return strcasestr(hay.c_str(), needle.c_str());
44 return platform_strcasestr(hay.c_str(), needle.c_str());
45 return false;
46}
47
48bool BankEntry::match(string s) const
49{
50 if(s == "#pad")
51 return pad;
52 else if(s == "#sub")
53 return sub;
54 else if(s == "#add")
55 return add;
56 return sfind(file,s) || sfind(name,s) || sfind(bank, s) ||
58}
59
61{
62 return (this->bank+this->file) < (b.bank+b.file);
63}
64
65static svec split(string s)
66{
67 svec vec;
68 string ss;
69 for(char c:s) {
70 if(isspace(c) && !ss.empty()) {
71 vec.push_back(ss);
72 ss.clear();
73 } else if(!isspace(c)) {
74 ss.push_back(c);
75 }
76 }
77 if(!ss.empty())
78 vec.push_back(ss);
79
80 return vec;
81}
82
83//static string line(string s)
84//{
85// string ss;
86// for(char c:s) {
87// if(c != '\n')
88// ss.push_back(c);
89// else
90// return ss;
91// }
92// return ss;
93//}
94
95bvec BankDb::search(std::string ss) const
96{
97 bvec vec;
98 const svec sterm = split(ss);
99 for(auto field:fields) {
100 bool match = true;
101 for(auto s:sterm)
102 match &= field.match(s);
103 if(match)
104 vec.push_back(field);
105 }
106
107 std::sort(vec.begin(), vec.end());
108
109 return vec;
110}
111
112void BankDb::addBankDir(std::string bnk)
113{
114 bool repeat = false;
115 for(auto b:banks)
116 repeat |= b == bnk;
117
118 if(!repeat)
119 banks.push_back(bnk);
120}
121
123{
124 banks.clear();
125 fields.clear();
126}
127
128static std::string getCacheName(void)
129{
130 char name[512] = {0};
131 snprintf(name, sizeof(name), "%s%s", getenv("HOME"),
132 "/.zynaddsubfx-bank-cache.xml");
133 return name;
134}
135
136static bvec loadCache(void)
137{
138 bvec cache;
139 XMLwrapper xml;
141 if(xml.enterbranch("bank-cache")) {
142 auto nodes = xml.getBranch();
143
144 for(auto node:nodes) {
145 BankEntry be;
146#define bind(x,y) if(node.has(#x)) {be.x = y(node[#x].c_str());}
147 bind(file, string);
148 bind(bank, string);
149 bind(name, string);
150 bind(comments, string);
151 bind(author, string);
152 bind(type, atoi);
153 bind(id, atoi);
154 bind(add, atoi);
155 bind(pad, atoi);
156 bind(sub, atoi);
157 bind(time, atoi);
158#undef bind
159 cache.push_back(be);
160 }
161 }
162 return cache;
163}
164
165static void saveCache(bvec vec)
166{
167 XMLwrapper xml;
168 xml.beginbranch("bank-cache");
169 for(auto value:vec) {
170 XmlNode binding("instrument-entry");
171#define bind(x) binding[#x] = to_s(value.x);
172 bind(file);
173 bind(bank);
174 bind(name);
175 bind(comments);
176 bind(author);
177 bind(type);
178 bind(id);
179 bind(add);
180 bind(pad);
181 bind(sub);
182 bind(time);
183#undef bind
184 xml.add(binding);
185 }
186 xml.endbranch();
187 xml.saveXMLfile(getCacheName(), 0);
188}
189
191{
192 fields.clear();
193 bvec cache = loadCache();
194 bmap cc;
195 for(auto c:cache)
196 cc[c.bank + c.file] = c;
197
198 bvec ncache;
199 for(auto bank:banks)
200 {
201 DIR *dir = opendir(bank.c_str());
202
203 if(!dir)
204 continue;
205
206
207 struct dirent *fn;
208
209 while((fn = readdir(dir))) {
210 const char *filename = fn->d_name;
211
212 //check for extension
213 if(!strstr(filename, INSTRUMENT_EXTENSION))
214 continue;
215
216 auto xiz = processXiz(filename, bank, cc);
217 fields.push_back(xiz);
218 ncache.push_back(xiz);
219 }
220
221 closedir(dir);
222
223 }
224 saveCache(ncache);
225}
226
228 std::string bank, bmap &cache) const
229{
230 string fname = bank+filename;
231
232 //Grab a timestamp
233 struct stat st;
234 int time = 0;
235
236 //gah windows, just implement the darn standard APIs
237#ifndef WIN32
238 int ret = lstat(fname.c_str(), &st);
239 if(ret != -1)
240 time = st.st_mtim.tv_sec;
241#else
242 int ret = 0;
243 time = rand();
244#endif
245
246
247 //quickly check if the file exists in the cache and if it is up-to-date
248 if(cache.find(fname) != cache.end() &&
249 cache[fname].time == time)
250 return cache[fname];
251
252
253
254 //verify if the name is like this NNNN-name (where N is a digit)
255 int no = 0;
256 unsigned int startname = 0;
257
258 for(unsigned int i = 0; i < 4; ++i) {
259 if(filename.length() <= i)
260 break;
261
262 if(isdigit(filename[i])) {
263 no = no * 10 + (filename[i] - '0');
264 startname++;
265 }
266 }
267
268 if(startname + 1 < filename.length())
269 startname++; //to take out the "-"
270
271 std::string name = filename;
272
273 //remove the file extension
274 for(int i = name.size() - 1; i >= 2; i--) {
275 if(name[i] == '.') {
276 name = name.substr(0, i);
277 break;
278 }
279 }
280
281
282 BankEntry entry;
283 entry.file = filename;
284 entry.bank = bank;
285 entry.id = no;
286 entry.time = time;
287
288 if(no != 0) //the instrument position in the bank is found
289 entry.name = name.substr(startname);
290 else
291 entry.name = name;
292
293 const char *types[] = {
294 "None",
295 "Piano",
296 "Chromatic Percussion",
297 "Organ",
298 "Guitar",
299 "Bass",
300 "Solo Strings",
301 "Ensemble",
302 "Brass",
303 "Reed",
304 "Pipe",
305 "Synth Lead",
306 "Synth Pad",
307 "Synth Effects",
308 "Ethnic",
309 "Percussive",
310 "Sound Effects",
311 };
312
313
314 //Try to obtain other metadata (expensive)
315 XMLwrapper xml;
316 ret = xml.loadXMLfile(fname);
317 if(xml.enterbranch("INSTRUMENT")) {
318 if(xml.enterbranch("INFO")) {
319 char author[1024];
320 char comments[1024];
321 int type = 0;
322 xml.getparstr("author", author, 1024);
323 xml.getparstr("comments", comments, 1024);
324 type = xml.getpar("type", 0, 0, 16);
325 entry.author = author;
326 entry.comments = comments;
327 entry.type = types[type];
328 xml.exitbranch();
329 }
330 if(xml.enterbranch("INSTRUMENT_KIT")) {
331 for(int i = 0; i < NUM_KIT_ITEMS; ++i) {
332 if(xml.enterbranch("INSTRUMENT_KIT_ITEM", i) == 0) {
333 entry.add |= xml.getparbool("add_enabled", false);
334 entry.sub |= xml.getparbool("sub_enabled", false);
335 entry.pad |= xml.getparbool("pad_enabled", false);
336 xml.exitbranch();
337 }
338 }
339 xml.exitbranch();
340 }
341 xml.exitbranch();
342 }
343
344 //printf("Bank Entry:\n");
345 //printf("\tname - %s\n", entry.name.c_str());
346 //printf("\tauthor - %s\n", line(entry.author).c_str());
347 //printf("\tbank - %s\n", entry.bank.c_str());
348 //printf("\tadd/pad/sub - %d/%d/%d\n", entry.add, entry.pad, entry.sub);
349
350 return entry;
351}
352
353}
#define bind(x, y)
#define NUM_KIT_ITEMS
Definition globals.h:135
CAdPlugDatabase::CRecord::RecordType type
Definition adplugdb.cpp:93
std::vector< std::string > svec
Definition BankDb.h:32
bvec fields
Definition BankDb.h:55
void addBankDir(std::string)
Definition BankDb.cpp:112
void scanBanks(void)
Definition BankDb.cpp:190
bvec search(std::string) const
Definition BankDb.cpp:95
svec banks
Definition BankDb.h:56
std::map< std::string, BankEntry > bmap
Definition BankDb.h:34
std::vector< BankEntry > bvec
Definition BankDb.h:33
BankEntry processXiz(std::string, std::string, bmap &) const
Definition BankDb.cpp:227
void clear(void)
Definition BankDb.cpp:122
Definition XMLwrapper.h:47
int getpar(const std::string &name, int defaultpar, int min, int max) const
Definition XMLwrapper.cpp:467
std::vector< XmlNode > getBranch(void) const
Definition XMLwrapper.cpp:682
void endbranch()
Definition XMLwrapper.cpp:291
void exitbranch()
Definition XMLwrapper.cpp:441
void getparstr(const std::string &name, char *par, int maxstrlen) const
int saveXMLfile(const std::string &filename, int compression) const
Definition XMLwrapper.cpp:190
int loadXMLfile(const std::string &filename)
Definition XMLwrapper.cpp:312
void beginbranch(const std::string &name)
int getparbool(const std::string &name, int defaultpar) const
Definition XMLwrapper.cpp:499
void add(const XmlNode &node)
Definition XMLwrapper.cpp:674
int enterbranch(const std::string &name)
Definition XMLwrapper.h:35
unsigned * m
Definition inflate.c:1559
register unsigned j
Definition inflate.c:1576
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
static char filename[]
Definition features.c:5
static PuglViewHint int value
Definition pugl.h:1708
static const char * name
Definition pugl.h:1582
Definition zynaddsubfx-src.cpp:569
static bvec loadCache(void)
Definition BankDb.cpp:136
static const char * INSTRUMENT_EXTENSION
Definition Bank.cpp:41
static void saveCache(bvec vec)
Definition BankDb.cpp:165
const AbsTime * time
Definition PADnoteParameters.h:189
static std::string getCacheName(void)
Definition BankDb.cpp:128
static svec split(string s)
Definition BankDb.cpp:65
bool platform_strcasestr(const char *hay, const char *needle)
Definition BankDb.cpp:21
BankDb::bvec bvec
Definition BankDb.cpp:15
BankDb::svec svec
Definition BankDb.cpp:14
bool sfind(std::string hay, std::string needle)
Definition BankDb.cpp:41
#define false
Definition ordinals.h:83
Definition BankDb.h:9
std::string name
Definition BankDb.h:13
bool add
Definition BankDb.h:18
bool pad
Definition BankDb.h:19
bool sub
Definition BankDb.h:20
int time
Definition BankDb.h:21
std::string type
Definition BankDb.h:16
std::string bank
Definition BankDb.h:12
std::string file
Definition BankDb.h:11
BankEntry(void)
Definition BankDb.cpp:17
bool operator<(const BankEntry &b) const
Definition BankDb.cpp:60
bool match(std::string) const
Definition BankDb.cpp:48
int id
Definition BankDb.h:17
std::string author
Definition BankDb.h:15
std::string comments
Definition BankDb.h:14
const char const char const char const char char * fn
Definition swell-functions.h:168
int n
Definition crypt.c:458
return c
Definition crypt.c:175
b
Definition crypt.c:628
int match(string, pattern, ignore_case __WDL) ZCONST char *string
#define dirent
Definition unix.c:70
closedir((DIR *) G.wild_dir)
char * getenv()
struct zdirent * file
Definition win32.c:1500
ss
Definition zipinfo.c:2292