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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1161 - (show annotations) (download)
Mon Apr 16 15:51:18 2007 UTC (16 years, 11 months ago) by iliev
File size: 46259 byte(s)
* Implemented instruments database

1 /***************************************************************************
2 * *
3 * Copyright (C) 2007 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 "InstrumentsDb.h"
22
23 #if HAVE_SQLITE3
24
25 #include <iostream>
26 #include <sstream>
27 #include <dirent.h>
28 #include <errno.h>
29 #include <ftw.h>
30 #include "../common/Exception.h"
31
32 namespace LinuxSampler {
33
34 void DbInstrument::Copy(const DbInstrument& Instr) {
35 if (this == &Instr) return;
36
37 InstrFile = Instr.InstrFile;
38 InstrNr = Instr.InstrNr;
39 FormatFamily = Instr.FormatFamily;
40 FormatVersion = Instr.FormatVersion;
41 Size = Instr.Size;
42 Created = Instr.Created;
43 Modified = Instr.Modified;
44 Description = Instr.Description;
45 IsDrum = Instr.IsDrum;
46 Product = Instr.Product;
47 Artists = Instr.Artists;
48 Keywords = Instr.Keywords;
49 }
50
51
52 void DbDirectory::Copy(const DbDirectory& Dir) {
53 if (this == &Dir) return;
54
55 Created = Dir.Created;
56 Modified = Dir.Modified;
57 Description = Dir.Description;
58 }
59
60
61 InstrumentsDb* InstrumentsDb::pInstrumentsDb = new InstrumentsDb;
62
63 InstrumentsDb::InstrumentsDb() {
64 db = NULL;
65 DbInstrumentsMutex = Mutex();
66 }
67
68 InstrumentsDb::~InstrumentsDb() {
69 if (db != NULL) sqlite3_close(db);
70 }
71
72 void InstrumentsDb::Destroy() {
73 if (pInstrumentsDb != NULL) {
74 delete pInstrumentsDb;
75 pInstrumentsDb = NULL;
76 }
77 }
78
79 void InstrumentsDb::AddInstrumentsDbListener(InstrumentsDb::Listener* l) {
80 llInstrumentsDbListeners.AddListener(l);
81 }
82
83 void InstrumentsDb::RemoveInstrumentsDbListener(InstrumentsDb::Listener* l) {
84 llInstrumentsDbListeners.RemoveListener(l);
85 }
86
87 InstrumentsDb* InstrumentsDb::GetInstrumentsDb() {
88 return pInstrumentsDb;
89 }
90
91 void InstrumentsDb::SetDbFile(String File) {
92 DbInstrumentsMutex.Lock();
93 if (File.empty() || DbFile.length() > 0) {
94 DbInstrumentsMutex.Unlock();
95 throw Exception("Failed to set the database file");
96 }
97 DbFile = File;
98 DbInstrumentsMutex.Unlock();
99 }
100
101 sqlite3* InstrumentsDb::GetDb() {
102 if ( db != NULL) return db;
103
104 if (DbFile.empty()) DbFile = "/var/lib/linuxsampler/instruments.db";
105 int rc = sqlite3_open(DbFile.c_str(), &db);
106 if (rc) {
107 sqlite3_close(db);
108 db = NULL;
109 throw Exception("Cannot open instruments database: " + DbFile);
110 }
111
112 return db;
113 }
114
115 int InstrumentsDb::GetDirectoryCount(int DirId) {
116 dmsg(2,("InstrumentsDb: GetDirectoryCount(DirId=%d)\n", DirId));
117 if(DirId == -1) return -1;
118
119 std::stringstream sql;
120 sql << "SELECT COUNT(*) FROM instr_dirs WHERE parent_dir_id=" << DirId;
121
122 int count = ExecSqlInt(sql.str());
123
124 // While the root dir has ID 0 and parent ID 0, the directory
125 // count for the root dir will be incorrect, so we should fix it.
126 if (count != -1 && DirId == 0) count--;
127 return count;
128 }
129
130 int InstrumentsDb::GetDirectoryCount(String Dir) {
131 dmsg(2,("InstrumentsDb: GetDirectoryCount(Dir=%s)\n", Dir.c_str()));
132 int i;
133
134 DbInstrumentsMutex.Lock();
135 try { i = GetDirectoryCount(GetDirectoryId(Dir)); }
136 catch (Exception e) {
137 DbInstrumentsMutex.Unlock();
138 throw e;
139 }
140 DbInstrumentsMutex.Unlock();
141 if (i == -1) throw Exception("Unkown DB directory: " + Dir);
142
143 return i;
144 }
145
146 IntListPtr InstrumentsDb::GetDirectoryIDs(int DirId) {
147 std::stringstream sql;
148 sql << "SELECT dir_id FROM instr_dirs ";
149 sql << "WHERE parent_dir_id=" << DirId << " AND dir_id!=0";
150
151 return ExecSqlIntList(sql.str());
152 }
153
154 StringListPtr InstrumentsDb::GetDirectories(String Dir) {
155 dmsg(2,("InstrumentsDb: GetDirectories(Dir=%s)\n", Dir.c_str()));
156
157 DbInstrumentsMutex.Lock();
158 try {
159 int dirId = GetDirectoryId(Dir);
160 if(dirId == -1) throw Exception("Unknown DB directory: " + Dir);
161
162 std::stringstream sql;
163 sql << "SELECT dir_name FROM instr_dirs ";
164 sql << "WHERE parent_dir_id=" << dirId << " AND dir_id!=0";
165
166 DbInstrumentsMutex.Unlock();
167 return ExecSqlStringList(sql.str());
168 } catch (Exception e) {
169 DbInstrumentsMutex.Unlock();
170 throw e;
171 }
172 }
173
174 int InstrumentsDb::GetDirectoryId(String Dir) {
175 dmsg(2,("InstrumentsDb: GetDirectoryId(Dir=%s)\n", Dir.c_str()));
176 CheckPathName(Dir);
177
178 if (Dir.empty() || Dir.at(0) != '/') {
179 return -1;
180 } else if (Dir.length() == 1) {
181 // We expect the root directory id to be always 0.
182 return 0;
183 }
184
185 int id = 0, i = 1;
186 int j = Dir.find('/', i);
187
188 while(j != std::string::npos) {
189 id = GetDirectoryId(id, Dir.substr(i, j - i));
190 i = j + 1;
191 if (i >= Dir.length()) return id;
192 j = Dir.find('/', i);
193 }
194
195 return GetDirectoryId(id, Dir.substr(i));
196 }
197
198 int InstrumentsDb::GetDirectoryId(int ParentDirId, String DirName) {
199 dmsg(2,("InstrumentsDb: GetDirectoryId(ParentDirId=%d, DirName=%s)\n", ParentDirId, DirName.c_str()));
200 std::stringstream sql;
201 sql << "SELECT dir_id FROM instr_dirs WHERE parent_dir_id=";
202 sql << ParentDirId << " AND dir_name=?";
203 return ExecSqlInt(sql.str(), DirName);
204 }
205
206 void InstrumentsDb::AddDirectory(String Dir) {
207 dmsg(2,("InstrumentsDb: AddDirectory(Dir=%s)\n", Dir.c_str()));
208 CheckPathName(Dir);
209 String ParentDir = GetParentDirectory(Dir);
210
211 DbInstrumentsMutex.Lock();
212 try {
213 if (Dir.length() > 1) {
214 if (Dir.at(Dir.length() - 1) == '/') Dir.erase(Dir.length() - 1);
215 }
216
217 String dirName = GetFileName(Dir);
218 if(ParentDir.empty() || dirName.empty()) {
219 throw Exception("Failed to add DB directory: " + Dir);
220 }
221
222 int id = GetDirectoryId(ParentDir);
223 if (id == -1) throw Exception("DB directory doesn't exist: " + ParentDir);
224 int id2 = GetDirectoryId(id, dirName);
225 if (id2 != -1) throw Exception("DB directory already exist: " + Dir);
226
227 std::stringstream sql;
228 sql << "INSERT INTO instr_dirs (parent_dir_id, dir_name) VALUES (";
229 sql << id << ", ?)";
230
231 ExecSql(sql.str(), dirName);
232 } catch (Exception e) {
233 DbInstrumentsMutex.Unlock();
234 throw e;
235 }
236
237 DbInstrumentsMutex.Unlock();
238
239 FireDirectoryCountChanged(ParentDir);
240 }
241
242 void InstrumentsDb::RemoveDirectory(String Dir, bool Force) {
243 dmsg(2,("InstrumentsDb: RemoveDirectory(Dir=%s,Force=%d)\n", Dir.c_str(), Force));
244
245 String ParentDir = GetParentDirectory(Dir);
246
247 DbInstrumentsMutex.Lock();
248 try {
249 int dirId = GetDirectoryId(Dir);
250 if (dirId == -1) throw Exception("Unknown DB directory: " + Dir);
251 if (dirId == 0) throw Exception("Cannot delete the root directory: " + Dir);
252 if(ParentDir.empty()) throw Exception("Unknown parent directory");
253 if (Force) RemoveDirectoryContent(dirId);
254 RemoveDirectory(dirId);
255 } catch (Exception e) {
256 DbInstrumentsMutex.Unlock();
257 throw e;
258 }
259
260 DbInstrumentsMutex.Unlock();
261 FireDirectoryCountChanged(ParentDir);
262 }
263
264 void InstrumentsDb::RemoveDirectoryContent(int DirId, int Level) {
265 dmsg(2,("InstrumentsDb: RemoveDirectoryContent(DirId=%d,Level=%d)\n", DirId, Level));
266 if (Level > 1000) throw Exception("Directory level too deep: " + ToString(Level));
267 IntListPtr dirIds = GetDirectoryIDs(DirId);
268
269 for (int i = 0; i < dirIds->size(); i++) {
270 RemoveDirectoryContent(dirIds->at(i), Level + 1);
271 }
272
273 RemoveAllDirectories(DirId);
274 RemoveAllInstruments(DirId);
275 }
276
277 void InstrumentsDb::RemoveDirectory(int DirId) {
278 dmsg(2,("InstrumentsDb: RemoveDirectory(DirId=%d)\n", DirId));
279 if (GetInstrumentCount(DirId) > 0 || GetDirectoryCount(DirId) > 0) {
280 throw Exception("The specified DB directory is not empty");
281 }
282
283 std::stringstream sql;
284 sql << "DELETE FROM instr_dirs WHERE dir_id=" << DirId;
285
286 ExecSql(sql.str());
287 }
288
289 void InstrumentsDb::RemoveAllDirectories(int DirId) {
290 dmsg(2,("InstrumentsDb: RemoveAllDirectories(DirId=%d)\n", DirId));
291 IntListPtr dirIds = GetDirectoryIDs(DirId);
292
293 for (int i = 0; i < dirIds->size(); i++) {
294 if (!IsDirectoryEmpty(dirIds->at(i))) {
295 throw Exception("DB directory not empty!");
296 }
297 }
298 std::stringstream sql;
299 sql << "DELETE FROM instr_dirs WHERE parent_dir_id=" << DirId;
300 sql << " AND dir_id!=0";
301
302 ExecSql(sql.str());
303 }
304
305 bool InstrumentsDb::IsDirectoryEmpty(int DirId) {
306 dmsg(2,("InstrumentsDb: IsDirectoryEmpty(DirId=%d)\n", DirId));
307 int dirCount = GetDirectoryCount(DirId);
308 int instrCount = GetInstrumentCount(DirId);
309 dmsg(3,("InstrumentsDb: IsDirectoryEmpty: dirCount=%d,instrCount=%d\n", dirCount, instrCount));
310 if (dirCount == -1 || instrCount == -1) return false;
311 return dirCount == 0 && instrCount == 0;
312 }
313
314 bool InstrumentsDb::DirectoryExist(String Dir) {
315 dmsg(2,("InstrumentsDb: DirectoryExist(Dir=%s)\n", Dir.c_str()));
316 bool b;
317
318 DbInstrumentsMutex.Lock();
319 try { b = GetDirectoryId(Dir) != -1; }
320 catch (Exception e) {
321 DbInstrumentsMutex.Unlock();
322 throw e;
323 }
324 DbInstrumentsMutex.Unlock();
325
326 return b;
327 }
328
329 DbDirectory InstrumentsDb::GetDirectoryInfo(String Dir) {
330 dmsg(2,("InstrumentsDb: GetDirectoryInfo(Dir=%s)\n", Dir.c_str()));
331 DbDirectory d;
332
333 DbInstrumentsMutex.Lock();
334
335 try {
336 int id = GetDirectoryId(Dir);
337 if(id == -1) throw Exception("Unknown DB directory: " + Dir);
338
339 sqlite3_stmt *pStmt = NULL;
340 std::stringstream sql;
341 sql << "SELECT created,modified,description FROM instr_dirs ";
342 sql << "WHERE dir_id=" << id;
343
344 int res = sqlite3_prepare(GetDb(), sql.str().c_str(), -1, &pStmt, NULL);
345 if (res != SQLITE_OK) {
346 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
347 }
348
349 res = sqlite3_step(pStmt);
350 if(res == SQLITE_ROW) {
351 d.Created = ToString(sqlite3_column_text(pStmt, 0));
352 d.Modified = ToString(sqlite3_column_text(pStmt, 1));
353 d.Description = ToString(sqlite3_column_text(pStmt, 2));
354 } else {
355 sqlite3_finalize(pStmt);
356
357 if (res != SQLITE_DONE) {
358 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
359 } else {
360 throw Exception("Unknown DB directory: " + Dir);
361 }
362 }
363
364 sqlite3_finalize(pStmt);
365 } catch (Exception e) {
366 DbInstrumentsMutex.Unlock();
367 throw e;
368 }
369
370 DbInstrumentsMutex.Unlock();
371 return d;
372 }
373
374 void InstrumentsDb::RenameDirectory(String Dir, String Name) {
375 dmsg(2,("InstrumentsDb: RenameDirectory(Dir=%s,Name=%s)\n", Dir.c_str(), Name.c_str()));
376 CheckFileName(Name);
377
378 DbInstrumentsMutex.Lock();
379 try {
380 int dirId = GetDirectoryId(Dir);
381 if (dirId == -1) throw Exception("Unknown DB directory: " + Dir);
382
383 std::stringstream sql;
384 sql << "SELECT parent_dir_id FROM instr_dirs WHERE dir_id=" << dirId;
385
386 int parent = ExecSqlInt(sql.str());
387 if (parent == -1) throw Exception("Unknown parent directory: " + Dir);
388 if (GetDirectoryId(parent, Name) != -1) {
389 throw Exception("Cannot rename. Directory with that name already exists: " + Name);
390 }
391
392 sql.str("");
393 sql << "UPDATE instr_dirs SET dir_name=? WHERE dir_id=" << dirId;
394 ExecSql(sql.str(), Name);
395 } catch (Exception e) {
396 DbInstrumentsMutex.Unlock();
397 throw e;
398 }
399
400 DbInstrumentsMutex.Unlock();
401 FireDirectoryNameChanged(Dir, Name);
402 }
403
404 void InstrumentsDb::MoveDirectory(String Dir, String Dst) {
405 dmsg(2,("InstrumentsDb: MoveDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
406
407 String ParentDir = GetParentDirectory(Dir);
408 if(ParentDir.empty()) throw Exception("Unknown parent directory");
409
410 DbInstrumentsMutex.Lock();
411 try {
412 int dirId = GetDirectoryId(Dir);
413 if (dirId == -1) throw Exception("Unknown DB directory: " + Dir);
414 int dstId = GetDirectoryId(Dst);
415 if (dstId == -1) throw Exception("Unknown DB directory: " + Dst);
416 if (dirId == dstId) {
417 throw Exception("Cannot move directory to itself");
418 }
419
420 if (Dir.at(Dir.length() - 1) != '/') Dir.append("/");
421 if (Dst.length() > Dir.length()) {
422 if (Dir.compare(Dst.substr(0, Dir.length())) == 0) {
423 throw Exception("Cannot move a directory to a subdirectory of itself.");
424 }
425 }
426
427 std::stringstream sql;
428 sql << "UPDATE instr_dirs SET parent_dir_id=" << dstId;
429 sql << " WHERE dir_id=" << dirId;
430 ExecSql(sql.str());
431 } catch (Exception e) {
432 DbInstrumentsMutex.Unlock();
433 throw e;
434 }
435
436 DbInstrumentsMutex.Unlock();
437 FireDirectoryCountChanged(ParentDir);
438 FireDirectoryCountChanged(Dst);
439 }
440
441 void InstrumentsDb::SetDirectoryDescription(String Dir, String Desc) {
442 dmsg(2,("InstrumentsDb: SetDirectoryDescription(Dir=%s,Desc=%s)\n", Dir.c_str(), Desc.c_str()));
443
444 DbInstrumentsMutex.Lock();
445 try {
446 int id = GetDirectoryId(Dir);
447 if(id == -1) throw Exception("Unknown DB directory: " + Dir);
448
449 std::stringstream sql;
450 sql << "UPDATE instr_dirs SET description=?,modified=CURRENT_TIMESTAMP ";
451 sql << "WHERE dir_id="<< id;
452
453 ExecSql(sql.str(), Desc);
454 } catch (Exception e) {
455 DbInstrumentsMutex.Unlock();
456 throw e;
457 }
458 DbInstrumentsMutex.Unlock();
459
460 FireDirectoryInfoChanged(Dir);
461 }
462
463 void InstrumentsDb::AddInstruments(String DbDir, String FilePath, int Index) {
464 dmsg(2,("InstrumentsDb: AddInstruments(DbDir=%s,FilePath=%s,Index=%d)\n", DbDir.c_str(), FilePath.c_str(), Index));
465 if (DbDir.empty() || FilePath.empty()) return;
466
467 DbInstrumentsMutex.Lock();
468 try {
469 int dirId = GetDirectoryId(DbDir);
470 if (dirId == -1) throw Exception("Invalid DB directory: " + DbDir);
471
472 struct stat statBuf;
473 int res = stat(FilePath.c_str(), &statBuf);
474 if (res) {
475 std::stringstream ss;
476 ss << "Fail to stat `" << FilePath << "`: " << strerror(errno);
477 throw Exception(ss.str());
478 }
479
480 if (S_ISREG(statBuf.st_mode)) {
481 AddInstrumentsFromFile(DbDir, FilePath, Index);
482 DbInstrumentsMutex.Unlock();
483 return;
484 }
485
486 if (!S_ISDIR(statBuf.st_mode)) {
487 DbInstrumentsMutex.Unlock();
488 return;
489 }
490
491 if (Index != -1) {
492 std::stringstream ss;
493 ss << "`" << FilePath << "` is directory, not an instrument file";
494 throw Exception(ss.str());
495 }
496
497 AddInstrumentsRecursive(DbDir, FilePath, false);
498 } catch (Exception e) {
499 DbInstrumentsMutex.Unlock();
500 throw e;
501 }
502
503 DbInstrumentsMutex.Unlock();
504 }
505
506 void InstrumentsDb::AddInstrumentsNonrecursive(String DbDir, String FsDir) {
507 dmsg(2,("InstrumentsDb: AddInstrumentsNonrecursive(DbDir=%s,FsDir=%s)\n", DbDir.c_str(), FsDir.c_str()));
508 if (DbDir.empty() || FsDir.empty()) return;
509
510 DbInstrumentsMutex.Lock();
511 try {
512 int dirId = GetDirectoryId(DbDir);
513 if (dirId == -1) throw Exception("Invalid DB directory: " + DbDir);
514
515 struct stat statBuf;
516 int res = stat(FsDir.c_str(), &statBuf);
517 if (res) {
518 std::stringstream ss;
519 ss << "Fail to stat `" << FsDir << "`: " << strerror(errno);
520 throw Exception(ss.str());
521 }
522
523 if (!S_ISDIR(statBuf.st_mode)) {
524 throw Exception("Directory expected");
525 }
526
527 if (FsDir.at(FsDir.length() - 1) != '/') FsDir.append("/");
528
529 DIR* pDir = opendir(FsDir.c_str());
530 if (pDir == NULL) {
531 std::stringstream ss;
532 ss << "The scanning of directory `" << FsDir << "` failed: ";
533 ss << strerror(errno);
534 std::cout << ss.str();
535 DbInstrumentsMutex.Unlock();
536 return;
537 }
538
539 struct dirent* pEnt = readdir(pDir);
540 while (pEnt != NULL) {
541 if (pEnt->d_type != DT_REG) {
542 pEnt = readdir(pDir);
543 continue;
544 }
545
546 AddInstrumentsFromFile(DbDir, FsDir + String(pEnt->d_name));
547 pEnt = readdir(pDir);
548 }
549
550 if (closedir(pDir)) {
551 std::stringstream ss;
552 ss << "Failed to close directory `" << FsDir << "`: ";
553 ss << strerror(errno);
554 std::cout << ss.str();
555 }
556 } catch (Exception e) {
557 DbInstrumentsMutex.Unlock();
558 throw e;
559 }
560
561 DbInstrumentsMutex.Unlock();
562 }
563
564 void InstrumentsDb::AddInstrumentsRecursive(String DbDir, String FsDir, bool Flat) {
565 dmsg(2,("InstrumentsDb: AddInstrumentsRecursive(DbDir=%s,FsDir=%s,Flat=%d)\n", DbDir.c_str(), FsDir.c_str(), Flat));
566 DirectoryScanner::Scan(DbDir, FsDir, Flat);
567 }
568
569 int InstrumentsDb::GetInstrumentCount(int DirId) {
570 dmsg(2,("InstrumentsDb: GetInstrumentCount(DirId=%d)\n", DirId));
571 if(DirId == -1) return -1;
572
573 std::stringstream sql;
574 sql << "SELECT COUNT(*) FROM instruments WHERE dir_id=" << DirId;
575
576 return ExecSqlInt(sql.str());
577 }
578
579 int InstrumentsDb::GetInstrumentCount(String Dir) {
580 dmsg(2,("InstrumentsDb: GetInstrumentCount(Dir=%s)\n", Dir.c_str()));
581 int i;
582
583 DbInstrumentsMutex.Lock();
584 try { i = GetInstrumentCount(GetDirectoryId(Dir)); }
585 catch (Exception e) {
586 DbInstrumentsMutex.Unlock();
587 throw e;
588 }
589 DbInstrumentsMutex.Unlock();
590
591 if (i == -1) throw Exception("Unknown Db directory: " + Dir);
592 return i;
593 }
594
595 IntListPtr InstrumentsDb::GetInstrumentIDs(int DirId) {
596 std::stringstream sql;
597 sql << "SELECT instr_id FROM instruments WHERE dir_id=" << DirId;
598
599 return ExecSqlIntList(sql.str());
600 }
601
602 StringListPtr InstrumentsDb::GetInstruments(String Dir) {
603 dmsg(2,("InstrumentsDb: GetInstruments(Dir=%s)\n", Dir.c_str()));
604 DbInstrumentsMutex.Lock();
605 try {
606 int dirId = GetDirectoryId(Dir);
607 if(dirId == -1) throw Exception("Unknown DB directory: " + Dir);
608
609 std::stringstream sql;
610 sql << "SELECT instr_name FROM instruments WHERE dir_id=" << dirId;
611
612 StringListPtr instrs = ExecSqlStringList(sql.str());
613 DbInstrumentsMutex.Unlock();
614 return instrs;
615 } catch (Exception e) {
616 DbInstrumentsMutex.Unlock();
617 throw e;
618 }
619 }
620
621 int InstrumentsDb::GetInstrumentId(String Instr) {
622 dmsg(2,("InstrumentsDb: GetInstrumentId(Instr=%s)\n", Instr.c_str()));
623 String Dir = GetDirectoryPath(Instr);
624 if (Dir.empty()) return -1;
625
626 return GetInstrumentId(GetDirectoryId(Dir), GetFileName(Instr));
627 }
628
629 int InstrumentsDb::GetInstrumentId(int DirId, String InstrName) {
630 dmsg(2,("InstrumentsDb: GetInstrumentId(DirId=%d,InstrName=%s)\n", DirId, InstrName.c_str()));
631 if (DirId == -1 || InstrName.empty()) return -1;
632
633 std::stringstream sql;
634 sql << "SELECT instr_id FROM instruments WHERE dir_id=";
635 sql << DirId << " AND instr_name=?";
636 return ExecSqlInt(sql.str(), InstrName);
637 }
638
639 void InstrumentsDb::RemoveInstrument(String Instr) {
640 dmsg(2,("InstrumentsDb: RemoveInstrument(Instr=%s)\n", Instr.c_str()));
641 String ParentDir = GetDirectoryPath(Instr);
642 if(ParentDir.empty()) throw Exception("Unknown parent directory");
643
644 DbInstrumentsMutex.Lock();
645 try {
646 int instrId = GetInstrumentId(Instr);
647 if(instrId == -1) {
648 throw Exception("The specified instrument does not exist: " + Instr);
649 }
650 RemoveInstrument(instrId);
651 } catch (Exception e) {
652 DbInstrumentsMutex.Unlock();
653 throw e;
654 }
655 DbInstrumentsMutex.Unlock();
656 FireInstrumentCountChanged(ParentDir);
657 }
658
659 void InstrumentsDb::RemoveInstrument(int InstrId) {
660 dmsg(2,("InstrumentsDb: RemoveInstrument(InstrId=%d)\n", InstrId));
661
662 std::stringstream sql;
663 sql << "DELETE FROM instruments WHERE instr_id=" << InstrId;
664
665 ExecSql(sql.str());
666 }
667
668 void InstrumentsDb::RemoveAllInstruments(int DirId) {
669 dmsg(2,("InstrumentsDb: RemoveAllInstruments(DirId=%d)\n", DirId));
670
671 std::stringstream sql;
672 sql << "DELETE FROM instruments WHERE dir_id=" << DirId;
673 ExecSql(sql.str());
674 }
675
676 DbInstrument InstrumentsDb::GetInstrumentInfo(String Instr) {
677 dmsg(2,("InstrumentsDb: GetInstrumentInfo(Instr=%s)\n", Instr.c_str()));
678 DbInstrument i;
679
680 DbInstrumentsMutex.Lock();
681 try {
682 int id = GetInstrumentId(Instr);
683 if(id == -1) throw Exception("Unknown DB instrument: " + Instr);
684
685 sqlite3_stmt *pStmt = NULL;
686 std::stringstream sql;
687 sql << "SELECT instr_file,instr_nr,format_family,format_version,";
688 sql << "instr_size,created,modified,description,is_drum,product,";
689 sql << "artists,keywords FROM instruments WHERE instr_id=" << id;
690
691 int res = sqlite3_prepare(GetDb(), sql.str().c_str(), -1, &pStmt, NULL);
692 if (res != SQLITE_OK) {
693 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
694 }
695
696 res = sqlite3_step(pStmt);
697 if(res == SQLITE_ROW) {
698 i.InstrFile = ToString(sqlite3_column_text(pStmt, 0));
699 i.InstrNr = sqlite3_column_int(pStmt, 1);
700 i.FormatFamily = ToString(sqlite3_column_text(pStmt, 2));
701 i.FormatVersion = ToString(sqlite3_column_text(pStmt, 3));
702 i.Size = sqlite3_column_int64(pStmt, 4);
703 i.Created = ToString(sqlite3_column_text(pStmt, 5));
704 i.Modified = ToString(sqlite3_column_text(pStmt, 6));
705 i.Description = ToString(sqlite3_column_text(pStmt, 7));
706 i.IsDrum = sqlite3_column_int(pStmt, 8);
707 i.Product = ToString(sqlite3_column_text(pStmt, 9));
708 i.Artists = ToString(sqlite3_column_text(pStmt, 10));
709 i.Keywords = ToString(sqlite3_column_text(pStmt, 11));
710 } else {
711 sqlite3_finalize(pStmt);
712
713 if (res != SQLITE_DONE) {
714 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
715 } else {
716 throw Exception("Unknown DB instrument: " + Instr);
717 }
718 }
719
720 sqlite3_finalize(pStmt);
721 } catch (Exception e) {
722 DbInstrumentsMutex.Unlock();
723 throw e;
724 }
725 DbInstrumentsMutex.Unlock();
726
727 return i;
728 }
729
730 void InstrumentsDb::RenameInstrument(String Instr, String Name) {
731 dmsg(2,("InstrumentsDb: RenameInstrument(Instr=%s,Name=%s)\n", Instr.c_str(), Name.c_str()));
732 CheckFileName(Name);
733
734 DbInstrumentsMutex.Lock();
735 try {
736 int dirId = GetDirectoryId(GetDirectoryPath(Instr));
737 if (dirId == -1) throw Exception("Unknown DB instrument: " + Instr);
738
739 int instrId = GetInstrumentId(dirId, GetFileName(Instr));
740 if (instrId == -1) throw Exception("Unknown DB instrument: " + Instr);
741
742 if (GetInstrumentId(dirId, Name) != -1) {
743 throw Exception("Cannot rename. Instrument with that name already exists: " + Name);
744 }
745
746 std::stringstream sql;
747 sql << "UPDATE instruments SET instr_name=? WHERE instr_id=" << instrId;
748 ExecSql(sql.str(), Name);
749 } catch (Exception e) {
750 DbInstrumentsMutex.Unlock();
751 throw e;
752 }
753 DbInstrumentsMutex.Unlock();
754 FireInstrumentNameChanged(Instr, Name);
755 }
756
757 void InstrumentsDb::MoveInstrument(String Instr, String Dst) {
758 dmsg(2,("InstrumentsDb: MoveInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
759 String ParentDir = GetDirectoryPath(Instr);
760 if(ParentDir.empty()) throw Exception("Unknown parent directory");
761
762 DbInstrumentsMutex.Lock();
763 try {
764 int dirId = GetDirectoryId(GetDirectoryPath(Instr));
765 if (dirId == -1) throw Exception("Unknown DB instrument: " + Instr);
766
767 String instrName = GetFileName(Instr);
768 int instrId = GetInstrumentId(dirId, instrName);
769 if (instrId == -1) throw Exception("Unknown DB instrument: " + Instr);
770
771 int dstId = GetDirectoryId(Dst);
772 if (dstId == -1) throw Exception("Unknown DB directory: " + Dst);
773 if (dirId == dstId) {
774 DbInstrumentsMutex.Unlock();
775 return;
776 }
777
778 if (GetInstrumentId(dstId, instrName) != -1) {
779 throw Exception("Cannot move. Instrument with that name already exists: " + instrName);
780 }
781
782 std::stringstream sql;
783 sql << "UPDATE instruments SET dir_id=" << dstId;
784 sql << " WHERE instr_id=" << instrId;
785 ExecSql(sql.str());
786 } catch (Exception e) {
787 DbInstrumentsMutex.Unlock();
788 throw e;
789 }
790 DbInstrumentsMutex.Unlock();
791 FireInstrumentCountChanged(ParentDir);
792 FireInstrumentCountChanged(Dst);
793 }
794
795 void InstrumentsDb::SetInstrumentDescription(String Instr, String Desc) {
796 dmsg(2,("InstrumentsDb: SetInstrumentDescription(Instr=%s,Desc=%s)\n", Instr.c_str(), Desc.c_str()));
797
798 DbInstrumentsMutex.Lock();
799 try {
800 int id = GetInstrumentId(Instr);
801 if(id == -1) throw Exception("Unknown DB instrument: " + Instr);
802
803 std::stringstream sql;
804 sql << "UPDATE instruments SET description=?,modified=CURRENT_TIMESTAMP ";
805 sql << "WHERE instr_id="<< id;
806
807 ExecSql(sql.str(), Desc);
808 } catch (Exception e) {
809 DbInstrumentsMutex.Unlock();
810 throw e;
811 }
812 DbInstrumentsMutex.Unlock();
813 FireInstrumentInfoChanged(Instr);
814 }
815
816 void InstrumentsDb::AddInstrumentsFromFile(String DbDir, String File, int Index) {
817 dmsg(2,("InstrumentsDb: AddInstrumentsFromFile(DbDir=%s,File=%s,Index=%d)\n", DbDir.c_str(), File.c_str(), Index));
818
819 if(File.length() < 4) return;
820
821 try {
822 if(!strcasecmp(".gig", File.substr(File.length() - 4).c_str())) {
823 AddGigInstruments(DbDir, File, Index);
824 }
825 } catch(Exception e) {
826 std::cout << e.Message() << std::endl;
827 }
828 }
829
830 void InstrumentsDb::AddGigInstruments(String DbDir, String File, int Index) {
831 dmsg(2,("InstrumentsDb: AddGigInstruments(DbDir=%s,File=%s,Index=%d)\n", DbDir.c_str(), File.c_str(), Index));
832 int dirId = GetDirectoryId(DbDir);
833 if (dirId == -1) throw Exception("Invalid DB directory: " + DbDir);
834
835 struct stat statBuf;
836 int res = stat(File.c_str(), &statBuf);
837 if (res) {
838 std::stringstream ss;
839 ss << "Fail to stat `" << File << "`: " << strerror(errno);
840 throw Exception(ss.str());
841 }
842
843 if (!S_ISREG(statBuf.st_mode)) {
844 std::stringstream ss;
845 ss << "`" << File << "` is not a regular file";
846 throw Exception(ss.str());
847 }
848
849 RIFF::File* riff = NULL;
850 gig::File* gig = NULL;
851 try {
852 riff = new RIFF::File(File);
853 gig::File* gig = new gig::File(riff);
854
855 std::stringstream sql;
856 sql << "INSERT INTO instruments (dir_id,instr_name,instr_file,";
857 sql << "instr_nr,format_family,format_version,instr_size,";
858 sql << "description,is_drum,product,artists,keywords) VALUES (";
859 sql << dirId << ",?,?,?,'GIG',?," << statBuf.st_size << ",?,?,?,?,?)";
860
861 sqlite3_stmt* pStmt = NULL;
862
863 int res = sqlite3_prepare(GetDb(), sql.str().c_str(), -1, &pStmt, NULL);
864 if (res != SQLITE_OK) {
865 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
866 }
867
868 BindTextParam(pStmt, 2, File);
869 String ver = "";
870 if (gig->pVersion != NULL) ver = ToString(gig->pVersion->major);
871 BindTextParam(pStmt, 4, ver);
872
873 if (Index == -1) {
874 int instrIndex = 0;
875 gig::Instrument* pInstrument = gig->GetFirstInstrument();
876 while (pInstrument) {
877 BindTextParam(pStmt, 7, gig->pInfo->Product);
878 BindTextParam(pStmt, 8, gig->pInfo->Artists);
879 BindTextParam(pStmt, 9, gig->pInfo->Keywords);
880 AddGigInstrument(pStmt, DbDir, dirId, File, pInstrument, instrIndex);
881
882 instrIndex++;
883 pInstrument = gig->GetNextInstrument();
884 }
885 } else {
886 gig::Instrument* pInstrument = gig->GetInstrument(Index);
887 if (pInstrument != NULL) {
888 BindTextParam(pStmt, 7, gig->pInfo->Product);
889 BindTextParam(pStmt, 8, gig->pInfo->Artists);
890 BindTextParam(pStmt, 9, gig->pInfo->Keywords);
891 AddGigInstrument(pStmt, DbDir, dirId, File, pInstrument, Index);
892 }
893 }
894
895 delete gig;
896 delete riff;
897 } catch (RIFF::Exception e) {
898 if (gig != NULL) delete gig;
899 if (riff != NULL) delete riff;
900 std::stringstream ss;
901 ss << "Failed to scan `" << File << "`: " << e.Message;
902
903 throw Exception(ss.str());
904 } catch (Exception e) {
905 if (gig != NULL) delete gig;
906 if (riff != NULL) delete riff;
907 throw e;
908 } catch (...) {
909 if (gig != NULL) delete gig;
910 if (riff != NULL) delete riff;
911 throw Exception("Failed to scan `" + File + "`");
912 }
913 }
914
915 void InstrumentsDb::AddGigInstrument (sqlite3_stmt* pStmt, String DbDir, int DirId, String File, gig::Instrument* pInstrument, int Index) {
916 String name = pInstrument->pInfo->Name;
917 if (name == "") return;
918 name = GetUniqueInstrumentName(DirId, name);
919
920 std::stringstream sql2;
921 sql2 << "SELECT COUNT(*) FROM instruments WHERE instr_file=? AND ";
922 sql2 << "instr_nr=" << Index;
923 if (ExecSqlInt(sql2.str(), File) > 0) return;
924
925 BindTextParam(pStmt, 1, name);
926 BindIntParam(pStmt, 3, Index);
927
928 BindTextParam(pStmt, 5, pInstrument->pInfo->Comments);
929 BindIntParam(pStmt, 6, pInstrument->IsDrum);
930
931 if (!pInstrument->pInfo->Product.empty()) {
932 BindTextParam(pStmt, 7, pInstrument->pInfo->Product);
933 }
934 if (!pInstrument->pInfo->Artists.empty()) {
935 BindTextParam(pStmt, 8, pInstrument->pInfo->Artists);
936 }
937
938 if (!pInstrument->pInfo->Keywords.empty()) {
939 BindTextParam(pStmt, 9, pInstrument->pInfo->Keywords);
940 }
941
942 int res = sqlite3_step(pStmt);
943 if(res != SQLITE_DONE) {
944 sqlite3_finalize(pStmt);
945 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
946 }
947
948 res = sqlite3_reset(pStmt);
949 FireInstrumentCountChanged(DbDir);
950 }
951
952 void InstrumentsDb::ExecSql(String Sql) {
953 dmsg(2,("InstrumentsDb: ExecSql(Sql=%s)\n", Sql.c_str()));
954 sqlite3_stmt *pStmt = NULL;
955
956 int res = sqlite3_prepare(GetDb(), Sql.c_str(), -1, &pStmt, NULL);
957 if (res != SQLITE_OK) {
958 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
959 }
960
961 res = sqlite3_step(pStmt);
962 if(res != SQLITE_DONE) {
963 sqlite3_finalize(pStmt);
964 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
965 }
966
967 sqlite3_finalize(pStmt);
968 }
969
970 void InstrumentsDb::ExecSql(String Sql, String Param) {
971 dmsg(2,("InstrumentsDb: ExecSql(Sql=%s,Param=%s)\n", Sql.c_str(), Param.c_str()));
972 sqlite3_stmt *pStmt = NULL;
973
974 int res = sqlite3_prepare(GetDb(), Sql.c_str(), -1, &pStmt, NULL);
975 if (res != SQLITE_OK) {
976 sqlite3_finalize(pStmt);
977 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
978 }
979
980 BindTextParam(pStmt, 1, Param);
981
982 res = sqlite3_step(pStmt);
983 if (res != SQLITE_DONE) {
984 sqlite3_finalize(pStmt);
985 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
986 }
987
988 sqlite3_finalize(pStmt);
989 }
990
991 int InstrumentsDb::ExecSqlInt(String Sql) {
992 dmsg(2,("InstrumentsDb: ExecSqlInt(Sql=%s)\n", Sql.c_str()));
993 sqlite3_stmt *pStmt = NULL;
994
995 int res = sqlite3_prepare(GetDb(), Sql.c_str(), -1, &pStmt, NULL);
996 if (res != SQLITE_OK) {
997 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
998 }
999
1000 int i = -1;
1001 res = sqlite3_step(pStmt);
1002 if(res == SQLITE_ROW) {
1003 i = sqlite3_column_int(pStmt, 0);
1004 } else if (res != SQLITE_DONE) {
1005 sqlite3_finalize(pStmt);
1006 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1007 }
1008
1009 sqlite3_finalize(pStmt);
1010
1011 return i;
1012 }
1013
1014 int InstrumentsDb::ExecSqlInt(String Sql, String Param) {
1015 dmsg(2,("InstrumentsDb: ExecSqlInt(Sql=%s,Param=%s)\n", Sql.c_str(), Param.c_str()));
1016 sqlite3_stmt *pStmt = NULL;
1017
1018 int res = sqlite3_prepare(GetDb(), Sql.c_str(), -1, &pStmt, NULL);
1019 if (res != SQLITE_OK) {
1020 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1021 }
1022
1023 BindTextParam(pStmt, 1, Param);
1024
1025 int i = -1;
1026 res = sqlite3_step(pStmt);
1027 if(res == SQLITE_ROW) {
1028 i = sqlite3_column_int(pStmt, 0);
1029 } else if (res != SQLITE_DONE) {
1030 sqlite3_finalize(pStmt);
1031 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1032 }
1033
1034 sqlite3_finalize(pStmt);
1035 return i;
1036 }
1037
1038 String InstrumentsDb::ExecSqlString(String Sql) {
1039 dmsg(2,("InstrumentsDb: ExecSqlString(Sql=%s)\n", Sql.c_str()));
1040 sqlite3_stmt *pStmt = NULL;
1041
1042 int res = sqlite3_prepare(GetDb(), Sql.c_str(), -1, &pStmt, NULL);
1043 if (res != SQLITE_OK) {
1044 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1045 }
1046
1047 String s;
1048 res = sqlite3_step(pStmt);
1049 if(res == SQLITE_ROW) {
1050 s = ToString(sqlite3_column_text(pStmt, 0));
1051 } else if (res != SQLITE_DONE) {
1052 sqlite3_finalize(pStmt);
1053 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1054 }
1055
1056 sqlite3_finalize(pStmt);
1057
1058 return s;
1059 }
1060
1061 IntListPtr InstrumentsDb::ExecSqlIntList(String Sql) {
1062 IntListPtr intList(new std::vector<int>);
1063
1064 sqlite3_stmt *pStmt = NULL;
1065
1066 int res = sqlite3_prepare(GetDb(), Sql.c_str(), -1, &pStmt, NULL);
1067 if (res != SQLITE_OK) {
1068 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1069 }
1070
1071 res = sqlite3_step(pStmt);
1072 while(res == SQLITE_ROW) {
1073 intList->push_back(sqlite3_column_int(pStmt, 0));
1074 res = sqlite3_step(pStmt);
1075 }
1076
1077 if (res != SQLITE_DONE) {
1078 sqlite3_finalize(pStmt);
1079 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1080 }
1081
1082 sqlite3_finalize(pStmt);
1083
1084 return intList;
1085 }
1086
1087 StringListPtr InstrumentsDb::ExecSqlStringList(String Sql) {
1088 StringListPtr stringList(new std::vector<String>);
1089
1090 sqlite3_stmt *pStmt = NULL;
1091
1092 int res = sqlite3_prepare(GetDb(), Sql.c_str(), -1, &pStmt, NULL);
1093 if (res != SQLITE_OK) {
1094 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1095 }
1096
1097 res = sqlite3_step(pStmt);
1098 while(res == SQLITE_ROW) {
1099 stringList->push_back(ToString(sqlite3_column_text(pStmt, 0)));
1100 res = sqlite3_step(pStmt);
1101 }
1102
1103 if (res != SQLITE_DONE) {
1104 sqlite3_finalize(pStmt);
1105 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1106 }
1107
1108 sqlite3_finalize(pStmt);
1109
1110 return stringList;
1111 }
1112
1113 void InstrumentsDb::BindTextParam(sqlite3_stmt* pStmt, int Index, String Text) {
1114 if (pStmt == NULL) return;
1115 int res = sqlite3_bind_text(pStmt, Index, Text.c_str(), -1, SQLITE_STATIC);
1116 if (res != SQLITE_OK) {
1117 sqlite3_finalize(pStmt);
1118 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1119 }
1120 }
1121
1122 void InstrumentsDb::BindIntParam(sqlite3_stmt* pStmt, int Index, int Param) {
1123 if (pStmt == NULL) return;
1124 int res = sqlite3_bind_int(pStmt, Index, Param);
1125 if (res != SQLITE_OK) {
1126 sqlite3_finalize(pStmt);
1127 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1128 }
1129 }
1130
1131 String InstrumentsDb::GetDirectoryPath(String File) {
1132 if (File.empty()) return String("");
1133 if (File.at(0) != '/') String("");
1134 if (File.length() == 1) return File;
1135 if (File.at(File.length() - 1) == '/') return File.substr(0, File.length() - 1);
1136 int i = File.rfind('/', File.length() - 1);
1137 if(i == std::string::npos) return String("");
1138 if(i == 0) return String("/");
1139 return File.substr(0, i);
1140 }
1141
1142 String InstrumentsDb::GetFileName(String Path) {
1143 if (Path.length() < 2) return String("");
1144 if (Path.at(0) != '/') String("");
1145 if (Path.at(Path.length() - 1) == '/') return String("");
1146 int i = Path.rfind('/', Path.length() - 1);
1147 return Path.substr(i + 1);
1148 }
1149
1150 void InstrumentsDb::CheckPathName(String Path) {
1151 if (Path.empty()) return;
1152
1153 int i = 0, j = Path.find('/', i);
1154
1155 while(j != std::string::npos) {
1156 if (j + 1 >= Path.length()) return;
1157 if (Path.at(j + 1) == '/') throw Exception("Invalid path name: " + Path);
1158
1159 i = j + 1;
1160 j = Path.find('/', i);
1161 }
1162 }
1163
1164 String InstrumentsDb::GetParentDirectory(String Dir) {
1165 if (Dir.length() < 2) return String("");
1166 if (Dir.at(0) != '/') String("");
1167 int i = Dir.rfind('/', Dir.length() - 2);
1168 if (i == 0) return "/";
1169 return Dir.substr(0, i);
1170 }
1171
1172 void InstrumentsDb::CheckFileName(String File) {
1173 if (File.empty()) throw Exception("Invalid file name: " + File);
1174 if (File.find('/') != std::string::npos) {
1175 throw Exception("Invalid file name: " + File);
1176 }
1177 }
1178
1179 String InstrumentsDb::GetUniqueInstrumentName(int DirId, String Name) {
1180 dmsg(2,("InstrumentsDb: GetUniqueInstrumentName(DirId=%d,Name=%s)\n", DirId, Name.c_str()));
1181 std::stringstream sql;
1182 sql << "SELECT COUNT(*) FROM instruments WHERE dir_id=" << DirId;
1183 sql << " AND instr_name=?";
1184
1185 if (ExecSqlInt(sql.str(), Name) == 0) return Name;
1186 std::stringstream ss;
1187 for(int i = 2; i < 1001; i++) {
1188 ss.str("");
1189 ss << Name << '[' << i << ']';
1190 if (ExecSqlInt(sql.str(), ss.str()) == 0) return ss.str();
1191 }
1192
1193 throw Exception("Unable to find an unique name: " + Name);
1194 }
1195
1196 void InstrumentsDb::FireDirectoryCountChanged(String Dir) {
1197 for (int i = 0; i < llInstrumentsDbListeners.GetListenerCount(); i++) {
1198 llInstrumentsDbListeners.GetListener(i)->DirectoryCountChanged(Dir);
1199 }
1200 }
1201
1202 void InstrumentsDb::FireDirectoryInfoChanged(String Dir) {
1203 for (int i = 0; i < llInstrumentsDbListeners.GetListenerCount(); i++) {
1204 llInstrumentsDbListeners.GetListener(i)->DirectoryInfoChanged(Dir);
1205 }
1206 }
1207
1208 void InstrumentsDb::FireDirectoryNameChanged(String Dir, String NewName) {
1209 for (int i = 0; i < llInstrumentsDbListeners.GetListenerCount(); i++) {
1210 llInstrumentsDbListeners.GetListener(i)->DirectoryNameChanged(Dir, NewName);
1211 }
1212 }
1213
1214 void InstrumentsDb::FireInstrumentCountChanged(String Dir) {
1215 for (int i = 0; i < llInstrumentsDbListeners.GetListenerCount(); i++) {
1216 llInstrumentsDbListeners.GetListener(i)->InstrumentCountChanged(Dir);
1217 }
1218 }
1219
1220 void InstrumentsDb::FireInstrumentInfoChanged(String Instr) {
1221 for (int i = 0; i < llInstrumentsDbListeners.GetListenerCount(); i++) {
1222 llInstrumentsDbListeners.GetListener(i)->InstrumentInfoChanged(Instr);
1223 }
1224 }
1225
1226 void InstrumentsDb::FireInstrumentNameChanged(String Instr, String NewName) {
1227 for (int i = 0; i < llInstrumentsDbListeners.GetListenerCount(); i++) {
1228 llInstrumentsDbListeners.GetListener(i)->InstrumentNameChanged(Instr, NewName);
1229 }
1230 }
1231
1232
1233 String DirectoryScanner::DbDir;
1234 String DirectoryScanner::FsDir;
1235 bool DirectoryScanner::Flat;
1236
1237 void DirectoryScanner::Scan(String DbDir, String FsDir, bool Flat) {
1238 dmsg(2,("DirectoryScanner: Scan(DbDir=%s,FsDir=%s,Flat=%d)\n", DbDir.c_str(), FsDir.c_str(), Flat));
1239 if (DbDir.empty() || FsDir.empty()) throw Exception("Directory expected");
1240
1241 struct stat statBuf;
1242 int res = stat(FsDir.c_str(), &statBuf);
1243 if (res) {
1244 std::stringstream ss;
1245 ss << "Fail to stat `" << FsDir << "`: " << strerror(errno);
1246 throw Exception(ss.str());
1247 }
1248
1249 if (!S_ISDIR(statBuf.st_mode)) {
1250 throw Exception("Directory expected");
1251 }
1252
1253 DirectoryScanner::DbDir = DbDir;
1254 DirectoryScanner::FsDir = FsDir;
1255 if (DbDir.at(DbDir.length() - 1) != '/') {
1256 DirectoryScanner::DbDir.append("/");
1257 }
1258 if (FsDir.at(FsDir.length() - 1) != '/') {
1259 DirectoryScanner::FsDir.append("/");
1260 }
1261 DirectoryScanner::Flat = Flat;
1262
1263 ftw(FsDir.c_str(), FtwCallback, 10);
1264 }
1265
1266 int DirectoryScanner::FtwCallback(const char* fpath, const struct stat* sb, int typeflag) {
1267 dmsg(2,("DirectoryScanner: FtwCallback(fpath=%s)\n", fpath));
1268 if (typeflag != FTW_D) return 0;
1269
1270 String dir = DbDir;
1271 if (!Flat) {
1272 String subdir = fpath;
1273 if(subdir.length() > FsDir.length()) {
1274 subdir = subdir.substr(FsDir.length());
1275 dir += subdir;
1276 }
1277 }
1278
1279 InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
1280 if (!db->DirectoryExist(dir)) db->AddDirectory(dir);
1281
1282 db->AddInstrumentsNonrecursive(dir, String(fpath));
1283
1284 return 0;
1285 };
1286
1287 } // namespace LinuxSampler
1288
1289 #endif // HAVE_SQLITE3

  ViewVC Help
Powered by ViewVC