/[svn]/linuxsampler/trunk/src/db/InstrumentsDbUtilities.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/db/InstrumentsDbUtilities.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3092 - (show annotations) (download)
Mon Jan 16 22:02:36 2017 UTC (7 years, 3 months ago) by schoenebeck
File size: 28030 byte(s)
* Instruments DB: Added support for scanning SFZ (.sfz) files.
* Instruments DB: Added support for scanning Sound Font (.sf2) files.
* Bumped version (2.0.0.svn40).

1 /***************************************************************************
2 * *
3 * Copyright (C) 2007 - 2009 Grigor Iliev *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software *
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, *
18 * MA 02110-1301 USA *
19 ***************************************************************************/
20
21 #include "InstrumentsDbUtilities.h"
22
23 #include "../common/File.h"
24 #include "../common/global_private.h"
25
26 #include <algorithm>
27 #include <errno.h>
28
29 #include "../common/Exception.h"
30 #include "InstrumentsDb.h"
31 #include "../engines/sfz/sfz.h"
32 #if HAVE_SF2
33 # if AC_APPLE_UNIVERSAL_BUILD
34 # include <libgig/SF.h>
35 # else
36 # include <SF.h>
37 # endif
38 #endif // HAVE_SF2
39
40 namespace LinuxSampler {
41
42 class GigFileInfo : public InstrumentFileInfo {
43 public:
44 GigFileInfo(String fileName) : InstrumentFileInfo(fileName) {
45 m_gig = NULL;
46 m_riff = NULL;
47 try {
48 m_riff = new RIFF::File(fileName);
49 m_gig = new gig::File(m_riff);
50 m_gig->SetAutoLoad(false); // avoid time consuming samples scanning
51 } catch (RIFF::Exception e) {
52 throw Exception(e.Message);
53 } catch (...) {
54 throw Exception("Unknown exception while accessing gig file");
55 }
56 }
57
58 virtual ~GigFileInfo() {
59 if (m_gig) delete m_gig;
60 if (m_riff) delete m_riff;
61 }
62
63 String formatName() OVERRIDE {
64 return "GIG";
65 }
66
67 String formatVersion() OVERRIDE {
68 return (m_gig->pVersion) ? ToString(m_gig->pVersion->major) : "";
69 }
70
71 optional<InstrumentInfo> getInstrumentInfo(int index, ScanProgress* pProgress) OVERRIDE {
72 InstrumentInfo info;
73 try {
74 ::gig::progress_t* progress = (pProgress) ? &pProgress->GigFileProgress : NULL;
75 ::gig::Instrument* pInstrument = m_gig->GetInstrument(index, progress);
76 if (!pInstrument)
77 return optional<InstrumentInfo>::nothing;
78
79 info.instrumentName = pInstrument->pInfo->Name;
80 info.product = (!pInstrument->pInfo->Product.empty()) ? pInstrument->pInfo->Product : m_gig->pInfo->Product;
81 info.artists = (!pInstrument->pInfo->Artists.empty()) ? pInstrument->pInfo->Artists : m_gig->pInfo->Artists;
82 info.keywords = (!pInstrument->pInfo->Keywords.empty()) ? pInstrument->pInfo->Keywords : m_gig->pInfo->Keywords;
83 info.comments = (!pInstrument->pInfo->Comments.empty()) ? pInstrument->pInfo->Comments : m_gig->pInfo->Comments;
84 info.isDrum = pInstrument->IsDrum;
85 } catch (RIFF::Exception e) {
86 throw Exception(e.Message);
87 } catch (...) {
88 throw Exception("Unknown exception while accessing gig file");
89 }
90 return info;
91 }
92 private:
93 ::RIFF::File* m_riff;
94 ::gig::File* m_gig;
95 };
96
97 class SFZFileInfo : public InstrumentFileInfo {
98 public:
99 SFZFileInfo(String fileName) : InstrumentFileInfo(fileName) {
100 m_sfz = NULL;
101 try {
102 m_sfz = new ::sfz::File(fileName);
103 } catch (sfz::Exception e) {
104 throw Exception(e.Message());
105 } catch (...) {
106 throw Exception("Unknown exception while accessing sfz file");
107 }
108 }
109
110 virtual ~SFZFileInfo() {
111 if (m_sfz) delete m_sfz;
112 }
113
114 String formatName() OVERRIDE {
115 return "SFZ";
116 }
117
118 String formatVersion() OVERRIDE {
119 return "";
120 }
121
122 optional<InstrumentInfo> getInstrumentInfo(int index, ScanProgress* pProgress) OVERRIDE {
123 if (index != 0)
124 return optional<InstrumentInfo>::nothing;
125
126 InstrumentInfo info;
127 // yeah, lousy info, but SFZ does not provide any meta info unfortunately yet
128 return info;
129 }
130 private:
131 ::sfz::File* m_sfz;
132 };
133
134 #if HAVE_SF2
135
136 class Sf2FileInfo : public InstrumentFileInfo {
137 public:
138 Sf2FileInfo(String fileName) : InstrumentFileInfo(fileName) {
139 m_sf2 = NULL;
140 m_riff = NULL;
141 try {
142 m_riff = new RIFF::File(fileName);
143 m_sf2 = new sf2::File(m_riff);
144 } catch (RIFF::Exception e) {
145 throw Exception(e.Message);
146 } catch (...) {
147 throw Exception("Unknown exception while accessing sf2 file");
148 }
149 }
150
151 virtual ~Sf2FileInfo() {
152 if (m_sf2) delete m_sf2;
153 if (m_riff) delete m_riff;
154 }
155
156 String formatName() OVERRIDE {
157 return "SF2";
158 }
159
160 String formatVersion() OVERRIDE {
161 if (!m_sf2->pInfo || !m_sf2->pInfo->pVer) return "";
162 String major = ToString(m_sf2->pInfo->pVer->Major);
163 //String minor = ToString(m_sf2->pInfo->pVer->Minor);
164 //return major + "." + minor;
165 return major;
166 }
167
168 optional<InstrumentInfo> getInstrumentInfo(int index, ScanProgress* pProgress) OVERRIDE {
169 if (index >= m_sf2->GetPresetCount())
170 return optional<InstrumentInfo>::nothing;
171
172 InstrumentInfo info;
173 try {
174 ::sf2::Preset* preset = m_sf2->GetPreset(index);
175 if (!preset)
176 return optional<InstrumentInfo>::nothing;
177
178 info.instrumentName = preset->Name;
179 if (m_sf2->pInfo) {
180 info.product = m_sf2->pInfo->Product;
181 info.comments = m_sf2->pInfo->Comments;
182 info.artists = m_sf2->pInfo->Engineers;
183 }
184 } catch (RIFF::Exception e) {
185 throw Exception(e.Message);
186 } catch (...) {
187 throw Exception("Unknown exception while accessing gig file");
188 }
189 return info;
190 }
191 private:
192 ::RIFF::File* m_riff;
193 ::sf2::File* m_sf2;
194 };
195
196 #endif // #if HAVE_SF2
197
198 void DbInstrument::Copy(const DbInstrument& Instr) {
199 if (this == &Instr) return;
200
201 InstrFile = Instr.InstrFile;
202 InstrNr = Instr.InstrNr;
203 FormatFamily = Instr.FormatFamily;
204 FormatVersion = Instr.FormatVersion;
205 Size = Instr.Size;
206 Created = Instr.Created;
207 Modified = Instr.Modified;
208 Description = Instr.Description;
209 IsDrum = Instr.IsDrum;
210 Product = Instr.Product;
211 Artists = Instr.Artists;
212 Keywords = Instr.Keywords;
213 }
214
215
216 void DbDirectory::Copy(const DbDirectory& Dir) {
217 if (this == &Dir) return;
218
219 Created = Dir.Created;
220 Modified = Dir.Modified;
221 Description = Dir.Description;
222 }
223
224 SearchQuery::SearchQuery() {
225 MinSize = -1;
226 MaxSize = -1;
227 InstrType = BOTH;
228 }
229
230 void SearchQuery::SetFormatFamilies(String s) {
231 if (s.length() == 0) return;
232 int i = 0;
233 int j = s.find(',', 0);
234
235 while (j != std::string::npos) {
236 FormatFamilies.push_back(s.substr(i, j - i));
237 i = j + 1;
238 j = s.find(',', i);
239 }
240
241 if (i < s.length()) FormatFamilies.push_back(s.substr(i));
242 }
243
244 void SearchQuery::SetSize(String s) {
245 String s2 = GetMin(s);
246 if (s2.length() > 0) MinSize = atoll(s2.c_str());
247 else MinSize = -1;
248
249 s2 = GetMax(s);
250 if (s2.length() > 0) MaxSize = atoll(s2.c_str());
251 else MaxSize = -1;
252 }
253
254 void SearchQuery::SetCreated(String s) {
255 CreatedAfter = GetMin(s);
256 CreatedBefore = GetMax(s);
257 }
258
259 void SearchQuery::SetModified(String s) {
260 ModifiedAfter = GetMin(s);
261 ModifiedBefore = GetMax(s);
262 }
263
264 String SearchQuery::GetMin(String s) {
265 if (s.length() < 3) return "";
266 if (s.at(0) == '.' && s.at(1) == '.') return "";
267 int i = s.find("..");
268 if (i == std::string::npos) return "";
269 return s.substr(0, i);
270 }
271
272 String SearchQuery::GetMax(String s) {
273 if (s.length() < 3) return "";
274 if (s.find("..", s.length() - 2) != std::string::npos) return "";
275 int i = s.find("..");
276 if (i == std::string::npos) return "";
277 return s.substr(i + 2);
278 }
279
280 void ScanJob::Copy(const ScanJob& Job) {
281 if (this == &Job) return;
282
283 JobId = Job.JobId;
284 FilesTotal = Job.FilesTotal;
285 FilesScanned = Job.FilesScanned;
286 Scanning = Job.Scanning;
287 Status = Job.Status;
288 }
289
290 int JobList::AddJob(ScanJob Job) {
291 if (Counter + 1 < Counter) Counter = 0;
292 else Counter++;
293 Job.JobId = Counter;
294 Jobs.push_back(Job);
295 if (Jobs.size() > 3) {
296 std::vector<ScanJob>::iterator iter = Jobs.begin();
297 Jobs.erase(iter);
298 }
299 return Job.JobId;
300 }
301
302 ScanJob& JobList::GetJobById(int JobId) {
303 for (int i = 0; i < Jobs.size(); i++) {
304 if (Jobs.at(i).JobId == JobId) return Jobs.at(i);
305 }
306
307 throw Exception("Invalid job ID: " + ToString(JobId));
308 }
309
310 bool AbstractFinder::IsRegex(String Pattern) {
311 if(Pattern.find('?') != String::npos) return true;
312 if(Pattern.find('*') != String::npos) return true;
313 return false;
314 }
315
316 void AbstractFinder::AddSql(String Col, String Pattern, std::stringstream& Sql) {
317 if (Pattern.length() == 0) return;
318
319 if (IsRegex(Pattern)) {
320 #ifndef WIN32
321 Sql << " AND " << Col << " regexp ?";
322 #else
323 for (int i = 0; i < Pattern.length(); i++) {
324 if (Pattern.at(i) == '?') Pattern.at(i) = '_';
325 else if (Pattern.at(i) == '*') Pattern.at(i) = '%';
326 }
327 Sql << " AND " << Col << " LIKE ?";
328 #endif
329 Params.push_back(Pattern);
330 return;
331 }
332
333 String buf;
334 std::vector<String> tokens;
335 std::vector<String> tokens2;
336 std::stringstream ss(Pattern);
337 while (ss >> buf) tokens.push_back(buf);
338
339 if (tokens.size() == 0) {
340 Sql << " AND " << Col << " LIKE ?";
341 Params.push_back("%" + Pattern + "%");
342 return;
343 }
344
345 bool b = false;
346 for (int i = 0; i < tokens.size(); i++) {
347 Sql << (i == 0 ? " AND (" : "");
348
349 for (int j = 0; j < tokens.at(i).length(); j++) {
350 if (tokens.at(i).at(j) == '+') tokens.at(i).at(j) = ' ';
351 }
352
353 ss.clear();
354 ss.str("");
355 ss << tokens.at(i);
356
357 tokens2.clear();
358 while (ss >> buf) tokens2.push_back(buf);
359
360 if (b && tokens2.size() > 0) Sql << " OR ";
361 if (tokens2.size() > 1) Sql << "(";
362 for (int j = 0; j < tokens2.size(); j++) {
363 if (j != 0) Sql << " AND ";
364 Sql << Col << " LIKE ?";
365 Params.push_back("%" + tokens2.at(j) + "%");
366 b = true;
367 }
368 if (tokens2.size() > 1) Sql << ")";
369 }
370 if (!b) Sql << "0)";
371 else Sql << ")";
372 }
373
374 DirectoryFinder::DirectoryFinder(SearchQuery* pQuery) : pDirectories(new std::vector<String>) {
375 pStmt = NULL;
376 this->pQuery = pQuery;
377 std::stringstream sql;
378 sql << "SELECT dir_name from instr_dirs WHERE dir_id!=0 AND parent_dir_id=?";
379
380 if (pQuery->CreatedAfter.length() != 0) {
381 sql << " AND created > ?";
382 Params.push_back(pQuery->CreatedAfter);
383 }
384 if (pQuery->CreatedBefore.length() != 0) {
385 sql << " AND created < ?";
386 Params.push_back(pQuery->CreatedBefore);
387 }
388 if (pQuery->ModifiedAfter.length() != 0) {
389 sql << " AND modified > ?";
390 Params.push_back(pQuery->ModifiedAfter);
391 }
392 if (pQuery->ModifiedBefore.length() != 0) {
393 sql << " AND modified < ?";
394 Params.push_back(pQuery->ModifiedBefore);
395 }
396
397 AddSql("dir_name", pQuery->Name, sql);
398 AddSql("description", pQuery->Description, sql);
399 SqlQuery = sql.str();
400
401 InstrumentsDb* idb = InstrumentsDb::GetInstrumentsDb();
402
403 int res = sqlite3_prepare(idb->GetDb(), SqlQuery.c_str(), -1, &pStmt, NULL);
404 if (res != SQLITE_OK) {
405 throw Exception("DB error: " + ToString(sqlite3_errmsg(idb->GetDb())));
406 }
407
408 for(int i = 0; i < Params.size(); i++) {
409 idb->BindTextParam(pStmt, i + 2, Params.at(i));
410 }
411 }
412
413 DirectoryFinder::~DirectoryFinder() {
414 if (pStmt != NULL) sqlite3_finalize(pStmt);
415 }
416
417 StringListPtr DirectoryFinder::GetDirectories() {
418 #if __cplusplus >= 201103L && !CONFIG_NO_CPP11STL
419 return std::move(pDirectories);
420 #else
421 return pDirectories;
422 #endif
423 }
424
425 void DirectoryFinder::ProcessDirectory(String Path, int DirId) {
426 InstrumentsDb* idb = InstrumentsDb::GetInstrumentsDb();
427 idb->BindIntParam(pStmt, 1, DirId);
428
429 String s = Path;
430 if(Path.compare("/") != 0) s += "/";
431 int res = sqlite3_step(pStmt);
432 while(res == SQLITE_ROW) {
433 pDirectories->push_back(s + idb->toAbstractName(ToString(sqlite3_column_text(pStmt, 0))));
434 res = sqlite3_step(pStmt);
435 }
436
437 if (res != SQLITE_DONE) {
438 sqlite3_finalize(pStmt);
439 throw Exception("DB error: " + ToString(sqlite3_errmsg(idb->GetDb())));
440 }
441
442 res = sqlite3_reset(pStmt);
443 if (res != SQLITE_OK) {
444 sqlite3_finalize(pStmt);
445 throw Exception("DB error: " + ToString(sqlite3_errmsg(idb->GetDb())));
446 }
447 }
448
449 InstrumentFinder::InstrumentFinder(SearchQuery* pQuery) : pInstruments(new std::vector<String>) {
450 pStmt = NULL;
451 this->pQuery = pQuery;
452 std::stringstream sql;
453 sql << "SELECT instr_name from instruments WHERE dir_id=?";
454
455 if (pQuery->CreatedAfter.length() != 0) {
456 sql << " AND created > ?";
457 Params.push_back(pQuery->CreatedAfter);
458 }
459 if (pQuery->CreatedBefore.length() != 0) {
460 sql << " AND created < ?";
461 Params.push_back(pQuery->CreatedBefore);
462 }
463 if (pQuery->ModifiedAfter.length() != 0) {
464 sql << " AND modified > ?";
465 Params.push_back(pQuery->ModifiedAfter);
466 }
467 if (pQuery->ModifiedBefore.length() != 0) {
468 sql << " AND modified < ?";
469 Params.push_back(pQuery->ModifiedBefore);
470 }
471 if (pQuery->MinSize != -1) sql << " AND instr_size > " << pQuery->MinSize;
472 if (pQuery->MaxSize != -1) sql << " AND instr_size < " << pQuery->MaxSize;
473
474 if (pQuery->InstrType == SearchQuery::CHROMATIC) sql << " AND is_drum = 0";
475 else if (pQuery->InstrType == SearchQuery::DRUM) sql << " AND is_drum != 0";
476
477 if (pQuery->FormatFamilies.size() > 0) {
478 sql << " AND (format_family=?";
479 Params.push_back(pQuery->FormatFamilies.at(0));
480 for (int i = 1; i < pQuery->FormatFamilies.size(); i++) {
481 sql << "OR format_family=?";
482 Params.push_back(pQuery->FormatFamilies.at(i));
483 }
484 sql << ")";
485 }
486
487 AddSql("instr_name", pQuery->Name, sql);
488 AddSql("description", pQuery->Description, sql);
489 AddSql("product", pQuery->Product, sql);
490 AddSql("artists", pQuery->Artists, sql);
491 AddSql("keywords", pQuery->Keywords, sql);
492 SqlQuery = sql.str();
493
494 InstrumentsDb* idb = InstrumentsDb::GetInstrumentsDb();
495
496 int res = sqlite3_prepare(idb->GetDb(), SqlQuery.c_str(), -1, &pStmt, NULL);
497 if (res != SQLITE_OK) {
498 throw Exception("DB error: " + ToString(sqlite3_errmsg(idb->GetDb())));
499 }
500
501 for(int i = 0; i < Params.size(); i++) {
502 idb->BindTextParam(pStmt, i + 2, Params.at(i));
503 }
504 }
505
506 InstrumentFinder::~InstrumentFinder() {
507 if (pStmt != NULL) sqlite3_finalize(pStmt);
508 }
509
510 void InstrumentFinder::ProcessDirectory(String Path, int DirId) {
511 InstrumentsDb* idb = InstrumentsDb::GetInstrumentsDb();
512 idb->BindIntParam(pStmt, 1, DirId);
513
514 String s = Path;
515 if(Path.compare("/") != 0) s += "/";
516 int res = sqlite3_step(pStmt);
517 while(res == SQLITE_ROW) {
518 pInstruments->push_back(s + idb->toAbstractName(ToString(sqlite3_column_text(pStmt, 0))));
519 res = sqlite3_step(pStmt);
520 }
521
522 if (res != SQLITE_DONE) {
523 sqlite3_finalize(pStmt);
524 throw Exception("DB error: " + ToString(sqlite3_errmsg(idb->GetDb())));
525 }
526
527 res = sqlite3_reset(pStmt);
528 if (res != SQLITE_OK) {
529 sqlite3_finalize(pStmt);
530 throw Exception("DB error: " + ToString(sqlite3_errmsg(idb->GetDb())));
531 }
532 }
533
534 StringListPtr InstrumentFinder::GetInstruments() {
535 #if __cplusplus >= 201103L && !CONFIG_NO_CPP11STL
536 return std::move(pInstruments);
537 #else
538 return pInstruments;
539 #endif
540 }
541
542 void DirectoryCounter::ProcessDirectory(String Path, int DirId) {
543 count += InstrumentsDb::GetInstrumentsDb()->GetDirectoryCount(DirId);
544 }
545
546 void InstrumentCounter::ProcessDirectory(String Path, int DirId) {
547 count += InstrumentsDb::GetInstrumentsDb()->GetInstrumentCount(DirId);
548 }
549
550 DirectoryCopier::DirectoryCopier(String SrcParentDir, String DestDir) {
551 this->SrcParentDir = SrcParentDir;
552 this->DestDir = DestDir;
553
554 if (DestDir.at(DestDir.length() - 1) != '/') {
555 this->DestDir.append("/");
556 }
557 if (SrcParentDir.at(SrcParentDir.length() - 1) != '/') {
558 this->SrcParentDir.append("/");
559 }
560 }
561
562 void DirectoryCopier::ProcessDirectory(String Path, int DirId) {
563 InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
564
565 String dir = DestDir;
566 String subdir = Path;
567 if(subdir.length() > SrcParentDir.length()) {
568 subdir = subdir.substr(SrcParentDir.length());
569 dir += subdir;
570 db->AddDirectory(dir);
571 }
572
573 int dstDirId = db->GetDirectoryId(dir);
574 if(dstDirId == -1) {
575 throw Exception("Unkown DB directory: " + InstrumentsDb::toEscapedPath(dir));
576 }
577 IntListPtr ids = db->GetInstrumentIDs(DirId);
578 for (int i = 0; i < ids->size(); i++) {
579 String name = db->GetInstrumentName(ids->at(i));
580 db->CopyInstrument(ids->at(i), name, dstDirId, dir);
581 }
582 }
583
584 ScanProgress::ScanProgress() {
585 TotalFileCount = ScannedFileCount = Status = 0;
586 CurrentFile = "";
587 GigFileProgress.custom = this;
588 GigFileProgress.callback = GigFileProgressCallback;
589 }
590
591 void ScanProgress::StatusChanged() {
592 InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
593 db->Jobs.GetJobById(JobId).FilesTotal = GetTotalFileCount();
594 db->Jobs.GetJobById(JobId).FilesScanned = GetScannedFileCount();
595 db->Jobs.GetJobById(JobId).Scanning = CurrentFile;
596 db->Jobs.GetJobById(JobId).Status = GetStatus();
597
598 InstrumentsDb::GetInstrumentsDb()->FireJobStatusChanged(JobId);
599 }
600
601 int ScanProgress::GetTotalFileCount() {
602 return TotalFileCount;
603 }
604
605 void ScanProgress::SetTotalFileCount(int Count) {
606 if (TotalFileCount == Count) return;
607 TotalFileCount = Count;
608 StatusChanged();
609 }
610
611 int ScanProgress::GetScannedFileCount() {
612 return ScannedFileCount;
613 }
614
615 void ScanProgress::SetScannedFileCount(int Count) {
616 if (ScannedFileCount == Count) return;
617 ScannedFileCount = Count;
618 if (Count > TotalFileCount) TotalFileCount = Count;
619 StatusChanged();
620 }
621
622 int ScanProgress::GetStatus() {
623 return Status;
624 }
625
626 void ScanProgress::SetStatus(int Status) {
627 if (this->Status == Status) return;
628 if (Status < 0) this->Status = 0;
629 else if (Status > 100) this->Status = 100;
630 else this->Status = Status;
631 StatusChanged();
632 }
633
634 void ScanProgress::SetErrorStatus(int Err) {
635 if (Err > 0) Err *= -1;
636 Status = Err;
637 StatusChanged();
638 }
639
640 void ScanProgress::GigFileProgressCallback(gig::progress_t* pProgress) {
641 if (pProgress == NULL) return;
642 ScanProgress* sp = static_cast<ScanProgress*> (pProgress->custom);
643
644 sp->SetStatus((int)(pProgress->factor * 100));
645 }
646
647 AddInstrumentsJob::AddInstrumentsJob(int JobId, ScanMode Mode, String DbDir, String FsDir, bool insDir) {
648 this->JobId = JobId;
649 Progress.JobId = JobId;
650 this->Mode = Mode;
651 this->DbDir = DbDir;
652 this->FsDir = FsDir;
653 this->insDir = insDir;
654 }
655
656 void AddInstrumentsJob::Run() {
657 try {
658 InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
659
660 switch (Mode) {
661 case NON_RECURSIVE:
662 Progress.SetTotalFileCount(GetFileCount());
663 db->AddInstrumentsNonrecursive(DbDir, FsDir, insDir, &Progress);
664 break;
665 case RECURSIVE:
666 db->AddInstrumentsRecursive(DbDir, FsDir, false, insDir, &Progress);
667 break;
668 case FLAT:
669 db->AddInstrumentsRecursive(DbDir, FsDir, true, insDir, &Progress);
670 break;
671 default:
672 throw Exception("Unknown scan mode");
673 }
674
675 // Just to be sure that the frontends will be notified about the job completion
676 if (Progress.GetTotalFileCount() != Progress.GetScannedFileCount()) {
677 Progress.SetTotalFileCount(Progress.GetScannedFileCount());
678 }
679 if (Progress.GetStatus() != 100) Progress.SetStatus(100);
680 } catch(Exception e) {
681 Progress.SetErrorStatus(-1);
682 throw e;
683 }
684 }
685
686 int AddInstrumentsJob::GetFileCount() {
687 int count = 0;
688
689 try {
690 FileListPtr fileList = File::GetFiles(FsDir);
691
692 for (int i = 0; i < fileList->size(); i++) {
693 String s = fileList->at(i);
694 if (InstrumentFileInfo::isSupportedFile(s)) count++;
695 }
696 } catch(Exception e) {
697 e.PrintMessage();
698 return 0;
699 }
700
701 return count;
702 }
703
704 AddInstrumentsFromFileJob::AddInstrumentsFromFileJob(int JobId, String DbDir, String FilePath, int Index, bool insDir) {
705 this->JobId = JobId;
706 Progress.JobId = JobId;
707 Progress.SetTotalFileCount(1);
708
709 this->DbDir = DbDir;
710 this->FilePath = FilePath;
711 this->Index = Index;
712 this->insDir = insDir;
713 }
714
715 void AddInstrumentsFromFileJob::Run() {
716 try {
717 InstrumentsDb::GetInstrumentsDb()->AddInstruments(DbDir, insDir, FilePath, Index, &Progress);
718
719 // Just to be sure that the frontends will be notified about the job completion
720 if (Progress.GetTotalFileCount() != Progress.GetScannedFileCount()) {
721 Progress.SetTotalFileCount(Progress.GetScannedFileCount());
722 }
723 if (Progress.GetStatus() != 100) Progress.SetStatus(100);
724 } catch(Exception e) {
725 Progress.SetErrorStatus(-1);
726 throw e;
727 }
728 }
729
730
731 void DirectoryScanner::Scan(String DbDir, String FsDir, bool Flat, bool insDir, ScanProgress* pProgress) {
732 dmsg(2,("DirectoryScanner: Scan(DbDir=%s,FsDir=%s,Flat=%d,insDir=%d)\n", DbDir.c_str(), FsDir.c_str(), Flat, insDir));
733 if (DbDir.empty() || FsDir.empty()) throw Exception("Directory expected");
734
735 this->DbDir = DbDir;
736 this->FsDir = FsDir;
737 this->insDir = insDir;
738 if (DbDir.at(DbDir.length() - 1) != '/') {
739 this->DbDir.append("/");
740 }
741 if (FsDir.at(FsDir.length() - 1) != File::DirSeparator) {
742 this->FsDir.push_back(File::DirSeparator);
743 }
744 this->Flat = Flat;
745 this->pProgress = pProgress;
746
747 File::WalkDirectoryTree(FsDir, this);
748 }
749
750 void DirectoryScanner::DirectoryEntry(std::string Path) {
751 dmsg(2,("DirectoryScanner: DirectoryEntry(Path=%s)\n", Path.c_str()));
752
753 String dir = DbDir;
754 if (!Flat) {
755 String subdir = Path;
756 if(subdir.length() > FsDir.length()) {
757 subdir = subdir.substr(FsDir.length());
758 #ifdef WIN32
759 replace(subdir.begin(), subdir.end(), '\\', '/');
760 #endif
761 dir += subdir;
762 }
763 }
764
765 InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
766
767 if (HasInstrumentFiles(Path)) {
768 if (!db->DirectoryExist(dir)) db->AddDirectory(dir);
769 db->AddInstrumentsNonrecursive(dir, Path, insDir, pProgress);
770 }
771 };
772
773 bool DirectoryScanner::HasInstrumentFiles(String Dir) {
774 InstrumentFileCounter c;
775 return c.Count(Dir) > 0;
776 }
777
778 int InstrumentFileCounter::Count(String FsDir) {
779 dmsg(2,("InstrumentFileCounter: Count(FsDir=%s)\n", FsDir.c_str()));
780 if (FsDir.empty()) throw Exception("Directory expected");
781 FileCount = 0;
782
783 File::WalkDirectoryTree(FsDir, this);
784 return FileCount;
785 }
786
787 void InstrumentFileCounter::FileEntry(std::string Path) {
788 dmsg(2,("InstrumentFileCounter: FileEntry(Path=%s)\n", Path.c_str()));
789 if (InstrumentFileInfo::isSupportedFile(Path)) FileCount++;
790 };
791
792
793 InstrumentFileInfo* InstrumentFileInfo::getFileInfoFor(String filename) {
794 if (filename.length() < 4) return NULL;
795 String fileExtension = filename.substr(filename.length() - 4);
796 if (!strcasecmp(".gig", fileExtension.c_str()))
797 return new GigFileInfo(filename);
798 if (!strcasecmp(".sfz", fileExtension.c_str()))
799 return new SFZFileInfo(filename);
800 #if HAVE_SF2
801 if (!strcasecmp(".sf2", fileExtension.c_str()))
802 return new Sf2FileInfo(filename);
803 #endif
804 return NULL;
805 }
806
807 bool InstrumentFileInfo::isSupportedFile(String filename) {
808 if (filename.length() < 4) return false;
809 String fileExtension = filename.substr(filename.length() - 4);
810 if (!strcasecmp(".gig", fileExtension.c_str())) return true;
811 if (!strcasecmp(".sfz", fileExtension.c_str())) return true;
812 #if HAVE_SF2
813 if (!strcasecmp(".sf2", fileExtension.c_str())) return true;
814 #endif
815 return false;
816 }
817
818 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC