Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

220 lines
4.9KB

  1. #include "BankDb.h"
  2. #include "XMLwrapper.h"
  3. #include "../globals.h"
  4. #include <cstring>
  5. #include <dirent.h>
  6. #define INSTRUMENT_EXTENSION ".xiz"
  7. using std::string;
  8. typedef BankDb::svec svec;
  9. typedef BankDb::bvec bvec;
  10. BankEntry::BankEntry(void)
  11. :id(0), add(false), pad(false), sub(false)
  12. {}
  13. bool sfind(std::string hay, std::string needle)
  14. {
  15. return strcasestr(hay.c_str(), needle.c_str());
  16. }
  17. bool BankEntry::match(string s) const
  18. {
  19. if(s == "#pad")
  20. return pad;
  21. else if(s == "#sub")
  22. return sub;
  23. else if(s == "#add")
  24. return add;
  25. return sfind(file,s) || sfind(name,s) || sfind(bank, s) ||
  26. sfind(type, s) || sfind(comments,s) || sfind(author,s);
  27. }
  28. static svec split(string s)
  29. {
  30. svec vec;
  31. string ss;
  32. for(char c:s) {
  33. if(isspace(c) && !ss.empty()) {
  34. vec.push_back(ss);
  35. ss.clear();
  36. } else if(!isspace(c)) {
  37. ss.push_back(c);
  38. }
  39. }
  40. if(!ss.empty())
  41. vec.push_back(ss);
  42. return vec;
  43. }
  44. static string line(string s)
  45. {
  46. string ss;
  47. for(char c:s) {
  48. if(c != '\n')
  49. ss.push_back(c);
  50. else
  51. return ss;
  52. }
  53. return ss;
  54. }
  55. bvec BankDb::search(std::string ss) const
  56. {
  57. bvec vec;
  58. const svec sterm = split(ss);
  59. for(auto field:fields) {
  60. bool match = true;
  61. for(auto s:sterm)
  62. match &= field.match(s);
  63. if(match)
  64. vec.push_back(field);
  65. }
  66. return vec;
  67. }
  68. void BankDb::addBankDir(std::string bnk)
  69. {
  70. bool repeat = false;
  71. for(auto b:banks)
  72. repeat |= b == bnk;
  73. if(!repeat)
  74. banks.push_back(bnk);
  75. }
  76. void BankDb::clear(void)
  77. {
  78. banks.clear();
  79. fields.clear();
  80. }
  81. void BankDb::scanBanks(void)
  82. {
  83. fields.clear();
  84. for(auto bank:banks)
  85. {
  86. DIR *dir = opendir(bank.c_str());
  87. if(!dir)
  88. continue;
  89. struct dirent *fn;
  90. while((fn = readdir(dir))) {
  91. const char *filename = fn->d_name;
  92. //check for extension
  93. if(!strstr(filename, INSTRUMENT_EXTENSION))
  94. continue;
  95. auto xiz = processXiz(filename, bank);
  96. fields.push_back(xiz);
  97. }
  98. closedir(dir);
  99. }
  100. }
  101. BankEntry BankDb::processXiz(std::string filename, std::string bank) const
  102. {
  103. //verify if the name is like this NNNN-name (where N is a digit)
  104. int no = 0;
  105. unsigned int startname = 0;
  106. for(unsigned int i = 0; i < 4; ++i) {
  107. if(filename.length() <= i)
  108. break;
  109. if(isdigit(filename[i])) {
  110. no = no * 10 + (filename[i] - '0');
  111. startname++;
  112. }
  113. }
  114. if(startname + 1 < filename.length())
  115. startname++; //to take out the "-"
  116. std::string name = filename;
  117. //remove the file extension
  118. for(int i = name.size() - 1; i >= 2; i--) {
  119. if(name[i] == '.') {
  120. name = name.substr(0, i);
  121. break;
  122. }
  123. }
  124. BankEntry entry;
  125. entry.file = filename;
  126. entry.bank = bank;
  127. entry.id = no;
  128. if(no != 0) //the instrument position in the bank is found
  129. entry.name = name.substr(startname);
  130. else
  131. entry.name = name;
  132. const char *types[] = {
  133. "None",
  134. "Piano",
  135. "Chromatic Percussion",
  136. "Organ",
  137. "Guitar",
  138. "Bass",
  139. "Solo Strings",
  140. "Ensemble",
  141. "Brass",
  142. "Reed",
  143. "Pipe",
  144. "Synth Lead",
  145. "Synth Pad",
  146. "Synth Effects",
  147. "Ethnic",
  148. "Percussive",
  149. "Sound Effects",
  150. };
  151. //Try to obtain other metadata (expensive)
  152. XMLwrapper xml;
  153. string fname = bank+filename;
  154. int ret = xml.loadXMLfile(fname);
  155. if(xml.enterbranch("INSTRUMENT")) {
  156. if(xml.enterbranch("INFO")) {
  157. char author[1024];
  158. char comments[1024];
  159. int type = 0;
  160. xml.getparstr("author", author, 1024);
  161. xml.getparstr("comments", comments, 1024);
  162. type = xml.getpar("type", 0, 0, 16);
  163. entry.author = author;
  164. entry.comments = comments;
  165. entry.type = types[type];
  166. xml.exitbranch();
  167. }
  168. if(xml.enterbranch("INSTRUMENT_KIT")) {
  169. for(int i = 0; i < NUM_KIT_ITEMS; ++i) {
  170. if(xml.enterbranch("INSTRUMENT_KIT_ITEM", i) == 0) {
  171. entry.add |= xml.getparbool("add_enabled", false);
  172. entry.sub |= xml.getparbool("sub_enabled", false);
  173. entry.pad |= xml.getparbool("pad_enabled", false);
  174. xml.exitbranch();
  175. }
  176. }
  177. xml.exitbranch();
  178. }
  179. xml.exitbranch();
  180. }
  181. //printf("Bank Entry:\n");
  182. //printf("\tname - %s\n", entry.name.c_str());
  183. //printf("\tauthor - %s\n", line(entry.author).c_str());
  184. //printf("\tadd/pad/sub - %d/%d/%d\n", entry.add, entry.pad, entry.sub);
  185. return entry;
  186. }