/[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 1781 - (show annotations) (download)
Mon Sep 29 18:21:21 2008 UTC (15 years, 6 months ago) by iliev
File size: 71190 byte(s)
* Implemented option for adding instruments in separate directories
  in the instruments database
  (patch by Chris Cherrett & Andrew Williams, a bit adjusted)

1 /***************************************************************************
2 * *
3 * Copyright (C) 2007, 2008 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 #include "../common/File.h"
24 #include "../common/global_private.h"
25
26 #include <iostream>
27 #include <sstream>
28 #include <vector>
29 #include <errno.h>
30 #include <fnmatch.h>
31
32 #include "../common/Exception.h"
33
34 namespace LinuxSampler {
35
36 InstrumentsDb InstrumentsDb::instance;
37
38 void InstrumentsDb::CreateInstrumentsDb(String FilePath) {
39 File f = File(FilePath);
40 if (f.Exist()) {
41 throw Exception("File exists: " + FilePath);
42 }
43
44 GetInstrumentsDb()->SetDbFile(FilePath);
45
46 String sql =
47 " CREATE TABLE instr_dirs ( "
48 " dir_id INTEGER PRIMARY KEY AUTOINCREMENT, "
49 " parent_dir_id INTEGER DEFAULT 0, "
50 " dir_name TEXT, "
51 " created TIMESTAMP DEFAULT CURRENT_TIMESTAMP, "
52 " modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP, "
53 " description TEXT, "
54 " FOREIGN KEY(parent_dir_id) REFERENCES instr_dirs(dir_id), "
55 " UNIQUE (parent_dir_id,dir_name) "
56 " ); ";
57
58 GetInstrumentsDb()->ExecSql(sql);
59
60 sql = "INSERT INTO instr_dirs (dir_id, parent_dir_id, dir_name) VALUES (0, -2, '/');";
61 GetInstrumentsDb()->ExecSql(sql);
62
63 sql =
64 " CREATE TABLE instruments ( "
65 " instr_id INTEGER PRIMARY KEY AUTOINCREMENT, "
66 " dir_id INTEGER DEFAULT 0, "
67 " instr_name TEXT, "
68 " instr_file TEXT, "
69 " instr_nr INTEGER, "
70 " format_family TEXT, "
71 " format_version TEXT, "
72 " instr_size INTEGER, "
73 " created TIMESTAMP DEFAULT CURRENT_TIMESTAMP, "
74 " modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP, "
75 " description TEXT, "
76 " is_drum INTEGER(1), "
77 " product TEXT, "
78 " artists TEXT, "
79 " keywords TEXT, "
80 " FOREIGN KEY(dir_id) REFERENCES instr_dirs(dir_id), "
81 " UNIQUE (dir_id,instr_name) "
82 " ); ";
83
84 GetInstrumentsDb()->ExecSql(sql);
85 }
86
87 InstrumentsDb::InstrumentsDb() {
88 db = NULL;
89 DbInstrumentsMutex = Mutex();
90 InTransaction = false;
91 }
92
93 InstrumentsDb::~InstrumentsDb() {
94 if (db != NULL) sqlite3_close(db);
95 }
96
97 void InstrumentsDb::AddInstrumentsDbListener(InstrumentsDb::Listener* l) {
98 llInstrumentsDbListeners.AddListener(l);
99 }
100
101 void InstrumentsDb::RemoveInstrumentsDbListener(InstrumentsDb::Listener* l) {
102 llInstrumentsDbListeners.RemoveListener(l);
103 }
104
105 InstrumentsDb* InstrumentsDb::GetInstrumentsDb() {
106 return &instance;
107 }
108
109 void InstrumentsDb::SetDbFile(String File) {
110 DbInstrumentsMutex.Lock();
111 if (File.empty() || DbFile.length() > 0) {
112 DbInstrumentsMutex.Unlock();
113 throw Exception("Failed to set the database file");
114 }
115 DbFile = File;
116 DbInstrumentsMutex.Unlock();
117 }
118
119 sqlite3* InstrumentsDb::GetDb() {
120 if ( db != NULL) return db;
121
122 if (DbFile.empty()) DbFile = CONFIG_DEFAULT_INSTRUMENTS_DB_LOCATION;
123 #if defined(__APPLE__) /* 20071224 Toshi Nagata */
124 if (DbFile.find("~") == 0)
125 DbFile.replace(0, 1, getenv("HOME"));
126 #endif
127 int rc = sqlite3_open(DbFile.c_str(), &db);
128 if (rc) {
129 sqlite3_close(db);
130 db = NULL;
131 throw Exception("Cannot open instruments database: " + DbFile);
132 }
133 rc = sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8, NULL, Regexp, NULL, NULL);
134 if (rc) { throw Exception("Failed to add user function for handling regular expressions."); }
135
136 // TODO: remove this in the next version
137 try {
138 int i = ExecSqlInt("SELECT parent_dir_id FROM instr_dirs WHERE dir_id=0");
139 // The parent ID of the root directory should be -2 now.
140 if(i != -2) ExecSql("UPDATE instr_dirs SET parent_dir_id=-2 WHERE dir_id=0");
141 } catch(Exception e) { }
142 ////////////////////////////////////////
143
144 return db;
145 }
146
147 int InstrumentsDb::GetDirectoryCount(int DirId) {
148 dmsg(2,("InstrumentsDb: GetDirectoryCount(DirId=%d)\n", DirId));
149 if(DirId == -1) return -1;
150
151 std::stringstream sql;
152 sql << "SELECT COUNT(*) FROM instr_dirs WHERE parent_dir_id=" << DirId;
153
154 int count = ExecSqlInt(sql.str());
155
156 return count;
157 }
158
159 int InstrumentsDb::GetDirectoryCount(String Dir, bool Recursive) {
160 dmsg(2,("InstrumentsDb: GetDirectoryCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
161 int i;
162
163 BeginTransaction();
164 try {
165 if (Recursive) {
166 DirectoryCounter directoryCounter;
167 DirectoryTreeWalk(Dir, &directoryCounter);
168 i = directoryCounter.GetDirectoryCount();
169 } else {
170 i = GetDirectoryCount(GetDirectoryId(Dir));
171 }
172 } catch (Exception e) {
173 EndTransaction();
174 throw e;
175 }
176 EndTransaction();
177 if (i == -1) throw Exception("Unkown DB directory: " + toEscapedPath(Dir));
178
179 return i;
180 }
181
182 IntListPtr InstrumentsDb::GetDirectoryIDs(int DirId) {
183 std::stringstream sql;
184 sql << "SELECT dir_id FROM instr_dirs ";
185 sql << "WHERE parent_dir_id=" << DirId << " AND dir_id!=0";
186
187 return ExecSqlIntList(sql.str());
188 }
189
190 StringListPtr InstrumentsDb::GetDirectories(String Dir, bool Recursive) {
191 dmsg(2,("InstrumentsDb: GetDirectories(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
192
193 BeginTransaction();
194 try {
195 int dirId = GetDirectoryId(Dir);
196 if(dirId == -1) throw Exception("Unknown DB directory: " + toEscapedPath(Dir));
197
198 StringListPtr pDirs;
199 if (Recursive) {
200 SearchQuery q;
201 DirectoryFinder directoryFinder(&q);
202 DirectoryTreeWalk(Dir, &directoryFinder);
203 pDirs = directoryFinder.GetDirectories();
204 } else {
205 pDirs = GetDirectories(dirId);
206 }
207 EndTransaction();
208 return pDirs;
209 } catch (Exception e) {
210 EndTransaction();
211 throw e;
212 }
213 }
214
215 StringListPtr InstrumentsDb::GetDirectories(int DirId) {
216 std::stringstream sql;
217 sql << "SELECT dir_name FROM instr_dirs ";
218 sql << "WHERE parent_dir_id=" << DirId << " AND dir_id!=0";
219 StringListPtr dirs = ExecSqlStringList(sql.str());
220
221 for (int i = 0; i < dirs->size(); i++) {
222 for (int j = 0; j < dirs->at(i).length(); j++) {
223 if (dirs->at(i).at(j) == '/') dirs->at(i).at(j) = '\0';
224 }
225 }
226
227 return dirs;
228 }
229
230 int InstrumentsDb::GetDirectoryId(String Dir) {
231 dmsg(2,("InstrumentsDb: GetDirectoryId(Dir=%s)\n", Dir.c_str()));
232 CheckPathName(Dir);
233
234 if (Dir.empty() || Dir.at(0) != '/') {
235 return -1;
236 } else if (Dir.length() == 1) {
237 // We expect the root directory id to be always 0.
238 return 0;
239 }
240
241 int id = 0, i = 1;
242 int j = Dir.find('/', i);
243
244 while(j != std::string::npos) {
245 id = GetDirectoryId(id, Dir.substr(i, j - i));
246 i = j + 1;
247 if (i >= Dir.length()) return id;
248 j = Dir.find('/', i);
249 }
250
251 return GetDirectoryId(id, Dir.substr(i));
252 }
253
254 int InstrumentsDb::GetDirectoryId(int ParentDirId, String DirName) {
255 dmsg(2,("InstrumentsDb: GetDirectoryId(ParentDirId=%d, DirName=%s)\n", ParentDirId, DirName.c_str()));
256 DirName = toDbName(DirName);
257 std::stringstream sql;
258 sql << "SELECT dir_id FROM instr_dirs WHERE parent_dir_id=";
259 sql << ParentDirId << " AND dir_name=?";
260 return ExecSqlInt(sql.str(), DirName);
261 }
262
263 int InstrumentsDb::GetDirectoryId(int InstrId) {
264 dmsg(2,("InstrumentsDb: GetDirectoryId(InstrId=%d)\n", InstrId));
265 std::stringstream sql;
266 sql << "SELECT dir_id FROM instruments WHERE instr_id=" << InstrId;
267 return ExecSqlInt(sql.str());
268 }
269
270 String InstrumentsDb::GetDirectoryName(int DirId) {
271 String sql = "SELECT dir_name FROM instr_dirs WHERE dir_id=" + ToString(DirId);
272 String name = ExecSqlString(sql);
273 if (name.empty()) throw Exception("Directory ID not found");
274 return name;
275 }
276
277 int InstrumentsDb::GetParentDirectoryId(int DirId) {
278 if (DirId == 0) throw Exception("The root directory is specified");
279 String sql = "SELECT parent_dir_id FROM instr_dirs WHERE dir_id=" + ToString(DirId);
280 int parentId = ExecSqlInt(sql);
281 if (parentId == -1) throw Exception("DB directory not found");
282 return parentId;
283 }
284
285 String InstrumentsDb::GetDirectoryPath(int DirId) {
286 String path = "";
287 int count = 1000; // used to prevent infinite loops
288
289 while(--count) {
290 if (DirId == 0) {
291 path = "/" + path;
292 break;
293 }
294 path = GetDirectoryName(DirId) + "/" + path;
295 DirId = GetParentDirectoryId(DirId);
296 }
297
298 if (!count) throw Exception("Possible infinite loop detected");
299
300 return path;
301 }
302
303 StringListPtr InstrumentsDb::GetInstrumentsByFile(String File) {
304 dmsg(2,("InstrumentsDb: GetInstrumentsByFile(File=%s)\n", File.c_str()));
305
306 StringListPtr instrs(new std::vector<String>);
307
308 BeginTransaction();
309 try {
310 File = toEscapedFsPath(File);
311 IntListPtr ids = ExecSqlIntList("SELECT instr_id FROM instruments WHERE instr_file=?", File);
312
313 for (int i = 0; i < ids->size(); i++) {
314 String name = GetInstrumentName(ids->at(i));
315 String dir = GetDirectoryPath(GetDirectoryId(ids->at(i)));
316 instrs->push_back(dir + name);
317 }
318 } catch (Exception e) {
319 EndTransaction();
320 throw e;
321 }
322 EndTransaction();
323
324 return instrs;
325 }
326
327 void InstrumentsDb::AddDirectory(String Dir) {
328 dmsg(2,("InstrumentsDb: AddDirectory(Dir=%s)\n", Dir.c_str()));
329 CheckPathName(Dir);
330 String ParentDir = GetParentDirectory(Dir);
331
332 BeginTransaction();
333 try {
334 if (Dir.length() > 1) {
335 if (Dir.at(Dir.length() - 1) == '/') Dir.erase(Dir.length() - 1);
336 }
337
338 String dirName = GetFileName(Dir);
339 if(ParentDir.empty() || dirName.empty()) {
340 throw Exception("Failed to add DB directory: " + toEscapedPath(Dir));
341 }
342
343 int id = GetDirectoryId(ParentDir);
344 if (id == -1) throw Exception("DB directory doesn't exist: " + toEscapedPath(ParentDir));
345 int id2 = GetDirectoryId(id, dirName);
346 if (id2 != -1) throw Exception("DB directory already exist: " + toEscapedPath(Dir));
347 id2 = GetInstrumentId(id, dirName);
348 if (id2 != -1) throw Exception("Instrument with that name exist: " + toEscapedPath(Dir));
349
350 std::stringstream sql;
351 sql << "INSERT INTO instr_dirs (parent_dir_id, dir_name) VALUES (";
352 sql << id << ", ?)";
353
354 ExecSql(sql.str(), toDbName(dirName));
355 } catch (Exception e) {
356 EndTransaction();
357 throw e;
358 }
359
360 EndTransaction();
361
362 FireDirectoryCountChanged(ParentDir);
363 }
364
365 void InstrumentsDb::RemoveDirectory(String Dir, bool Force) {
366 dmsg(2,("InstrumentsDb: RemoveDirectory(Dir=%s,Force=%d)\n", Dir.c_str(), Force));
367
368 String ParentDir = GetParentDirectory(Dir);
369
370 BeginTransaction();
371 try {
372 int dirId = GetDirectoryId(Dir);
373 if (dirId == -1) throw Exception("Unknown DB directory: " + toEscapedPath(Dir));
374 if (dirId == 0) throw Exception("Cannot delete the root directory: " + Dir);
375 if(ParentDir.empty()) throw Exception("Unknown parent directory");
376 if (Force) RemoveDirectoryContent(dirId);
377 RemoveDirectory(dirId);
378 } catch (Exception e) {
379 EndTransaction();
380 throw e;
381 }
382
383 EndTransaction();
384 FireDirectoryCountChanged(ParentDir);
385 }
386
387 void InstrumentsDb::RemoveDirectoryContent(int DirId, int Level) {
388 dmsg(2,("InstrumentsDb: RemoveDirectoryContent(DirId=%d,Level=%d)\n", DirId, Level));
389 if (Level > 1000) throw Exception("Directory level too deep: " + ToString(Level));
390 IntListPtr dirIds = GetDirectoryIDs(DirId);
391
392 for (int i = 0; i < dirIds->size(); i++) {
393 RemoveDirectoryContent(dirIds->at(i), Level + 1);
394 }
395
396 RemoveAllDirectories(DirId);
397 RemoveAllInstruments(DirId);
398 }
399
400 void InstrumentsDb::RemoveDirectory(int DirId) {
401 dmsg(2,("InstrumentsDb: RemoveDirectory(DirId=%d)\n", DirId));
402 if (GetInstrumentCount(DirId) > 0 || GetDirectoryCount(DirId) > 0) {
403 throw Exception("The specified DB directory is not empty");
404 }
405
406 std::stringstream sql;
407 sql << "DELETE FROM instr_dirs WHERE dir_id=" << DirId;
408
409 ExecSql(sql.str());
410 }
411
412 void InstrumentsDb::RemoveAllDirectories(int DirId) {
413 dmsg(2,("InstrumentsDb: RemoveAllDirectories(DirId=%d)\n", DirId));
414 IntListPtr dirIds = GetDirectoryIDs(DirId);
415
416 for (int i = 0; i < dirIds->size(); i++) {
417 if (!IsDirectoryEmpty(dirIds->at(i))) {
418 throw Exception("DB directory not empty!");
419 }
420 }
421 std::stringstream sql;
422 sql << "DELETE FROM instr_dirs WHERE parent_dir_id=" << DirId;
423 sql << " AND dir_id!=0";
424
425 ExecSql(sql.str());
426 }
427
428 bool InstrumentsDb::IsDirectoryEmpty(int DirId) {
429 dmsg(2,("InstrumentsDb: IsDirectoryEmpty(DirId=%d)\n", DirId));
430 int dirCount = GetDirectoryCount(DirId);
431 int instrCount = GetInstrumentCount(DirId);
432 dmsg(3,("InstrumentsDb: IsDirectoryEmpty: dirCount=%d,instrCount=%d\n", dirCount, instrCount));
433 if (dirCount == -1 || instrCount == -1) return false;
434 return dirCount == 0 && instrCount == 0;
435 }
436
437 bool InstrumentsDb::DirectoryExist(String Dir) {
438 dmsg(2,("InstrumentsDb: DirectoryExist(Dir=%s)\n", Dir.c_str()));
439 bool b;
440
441 DbInstrumentsMutex.Lock();
442 try { b = GetDirectoryId(Dir) != -1; }
443 catch (Exception e) {
444 DbInstrumentsMutex.Unlock();
445 throw e;
446 }
447 DbInstrumentsMutex.Unlock();
448
449 return b;
450 }
451
452 DbDirectory InstrumentsDb::GetDirectoryInfo(String Dir) {
453 dmsg(2,("InstrumentsDb: GetDirectoryInfo(Dir=%s)\n", Dir.c_str()));
454 DbDirectory d;
455
456 BeginTransaction();
457
458 try {
459 int id = GetDirectoryId(Dir);
460 if(id == -1) throw Exception("Unknown DB directory: " + toEscapedPath(Dir));
461
462 sqlite3_stmt *pStmt = NULL;
463 std::stringstream sql;
464 sql << "SELECT created,modified,description FROM instr_dirs ";
465 sql << "WHERE dir_id=" << id;
466
467 int res = sqlite3_prepare(GetDb(), sql.str().c_str(), -1, &pStmt, NULL);
468 if (res != SQLITE_OK) {
469 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
470 }
471
472 res = sqlite3_step(pStmt);
473 if(res == SQLITE_ROW) {
474 d.Created = ToString(sqlite3_column_text(pStmt, 0));
475 d.Modified = ToString(sqlite3_column_text(pStmt, 1));
476 d.Description = ToString(sqlite3_column_text(pStmt, 2));
477 } else {
478 sqlite3_finalize(pStmt);
479
480 if (res != SQLITE_DONE) {
481 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
482 } else {
483 throw Exception("Unknown DB directory: " + toEscapedPath(Dir));
484 }
485 }
486
487 sqlite3_finalize(pStmt);
488 } catch (Exception e) {
489 EndTransaction();
490 throw e;
491 }
492
493 EndTransaction();
494 return d;
495 }
496
497 void InstrumentsDb::RenameDirectory(String Dir, String Name) {
498 dmsg(2,("InstrumentsDb: RenameDirectory(Dir=%s,Name=%s)\n", Dir.c_str(), Name.c_str()));
499 CheckFileName(Name);
500 String dbName = toDbName(Name);
501
502 BeginTransaction();
503 try {
504 int dirId = GetDirectoryId(Dir);
505 if (dirId == -1) throw Exception("Unknown DB directory: " + toEscapedText(Dir));
506
507 std::stringstream sql;
508 sql << "SELECT parent_dir_id FROM instr_dirs WHERE dir_id=" << dirId;
509
510 int parent = ExecSqlInt(sql.str());
511 if (parent == -1) throw Exception("Unknown parent directory: " + toEscapedPath(Dir));
512
513 if (GetDirectoryId(parent, dbName) != -1) {
514 String s = toEscapedPath(Name);
515 throw Exception("Cannot rename. Directory with that name already exists: " + s);
516 }
517
518 if (GetInstrumentId(parent, dbName) != -1) {
519 throw Exception("Cannot rename. Instrument with that name exist: " + toEscapedPath(Dir));
520 }
521
522 sql.str("");
523 sql << "UPDATE instr_dirs SET dir_name=? WHERE dir_id=" << dirId;
524 ExecSql(sql.str(), dbName);
525 } catch (Exception e) {
526 EndTransaction();
527 throw e;
528 }
529
530 EndTransaction();
531 FireDirectoryNameChanged(Dir, toAbstractName(Name));
532 }
533
534 void InstrumentsDb::MoveDirectory(String Dir, String Dst) {
535 dmsg(2,("InstrumentsDb: MoveDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
536
537 if(Dir.compare("/") == 0) throw Exception("Cannot move the root directory");
538 String ParentDir = GetParentDirectory(Dir);
539 if(ParentDir.empty()) throw Exception("Unknown parent directory");
540
541 BeginTransaction();
542 try {
543 int dirId = GetDirectoryId(Dir);
544 if (dirId == -1) throw Exception("Unknown DB directory: " + toEscapedPath(Dir));
545 int dstId = GetDirectoryId(Dst);
546 if (dstId == -1) throw Exception("Unknown DB directory: " + toEscapedPath(Dst));
547 if (dirId == dstId) {
548 throw Exception("Cannot move directory to itself");
549 }
550
551 if (Dir.at(Dir.length() - 1) != '/') Dir.append("/");
552 if (Dst.length() > Dir.length()) {
553 if (Dir.compare(Dst.substr(0, Dir.length())) == 0) {
554 throw Exception("Cannot move a directory to a subdirectory of itself.");
555 }
556 }
557
558 Dir.erase(Dir.length() - 1);
559 String dirName = GetFileName(Dir);
560
561 int id2 = GetDirectoryId(dstId, dirName);
562 if (id2 != -1) throw Exception("DB directory already exist: " + toEscapedPath(dirName));
563 id2 = GetInstrumentId(dstId, dirName);
564 if (id2 != -1) throw Exception("Instrument with that name exist: " + toEscapedPath(dirName));
565
566 std::stringstream sql;
567 sql << "UPDATE instr_dirs SET parent_dir_id=" << dstId;
568 sql << " WHERE dir_id=" << dirId;
569 ExecSql(sql.str());
570 } catch (Exception e) {
571 EndTransaction();
572 throw e;
573 }
574
575 EndTransaction();
576 FireDirectoryCountChanged(ParentDir);
577 FireDirectoryCountChanged(Dst);
578 }
579
580 void InstrumentsDb::CopyDirectory(String Dir, String Dst) {
581 dmsg(2,("InstrumentsDb: CopyDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
582
583 if(Dir.compare("/") == 0) throw Exception("Cannot copy the root directory");
584 String ParentDir = GetParentDirectory(Dir);
585 if(ParentDir.empty()) throw Exception("Unknown parent directory");
586
587 BeginTransaction();
588 try {
589 int dirId = GetDirectoryId(Dir);
590 if (dirId == -1) throw Exception("Unknown DB directory: " + toEscapedPath(Dir));
591 int dstId = GetDirectoryId(Dst);
592 if (dstId == -1) throw Exception("Unknown DB directory: " + toEscapedPath(Dst));
593 if (dirId == dstId) {
594 throw Exception("Cannot copy directory to itself");
595 }
596
597 if (Dir.at(Dir.length() - 1) != '/') Dir.append("/");
598 if (Dst.length() > Dir.length()) {
599 if (Dir.compare(Dst.substr(0, Dir.length())) == 0) {
600 throw Exception("Cannot copy a directory to a subdirectory of itself.");
601 }
602 }
603
604 Dir.erase(Dir.length() - 1);
605 String dirName = GetFileName(Dir);
606
607 int id2 = GetDirectoryId(dstId, dirName);
608 if (id2 != -1) throw Exception("DB directory already exist: " + toEscapedPath(dirName));
609 id2 = GetInstrumentId(dstId, dirName);
610 if (id2 != -1) throw Exception("Instrument with that name exist: " + toEscapedPath(dirName));
611
612 DirectoryCopier directoryCopier(ParentDir, Dst);
613 DirectoryTreeWalk(Dir, &directoryCopier);
614 } catch (Exception e) {
615 EndTransaction();
616 throw e;
617 }
618
619 EndTransaction();
620 }
621
622 void InstrumentsDb::SetDirectoryDescription(String Dir, String Desc) {
623 dmsg(2,("InstrumentsDb: SetDirectoryDescription(Dir=%s,Desc=%s)\n", Dir.c_str(), Desc.c_str()));
624
625 BeginTransaction();
626 try {
627 int id = GetDirectoryId(Dir);
628 if(id == -1) throw Exception("Unknown DB directory: " + toEscapedPath(Dir));
629
630 std::stringstream sql;
631 sql << "UPDATE instr_dirs SET description=?,modified=CURRENT_TIMESTAMP ";
632 sql << "WHERE dir_id="<< id;
633
634 ExecSql(sql.str(), Desc);
635 } catch (Exception e) {
636 EndTransaction();
637 throw e;
638 }
639 EndTransaction();
640
641 FireDirectoryInfoChanged(Dir);
642 }
643
644 int InstrumentsDb::AddInstruments(ScanMode Mode, String DbDir, String FsDir, bool bBackground, bool insDir) {
645 dmsg(2,("InstrumentsDb: AddInstruments(Mode=%d,DbDir=%s,FsDir=%s,bBackground=%d,insDir=%d)\n", Mode, DbDir.c_str(), FsDir.c_str(), bBackground, insDir));
646 if(!bBackground) {
647 switch (Mode) {
648 case NON_RECURSIVE:
649 AddInstrumentsNonrecursive(DbDir, FsDir, insDir);
650 break;
651 case RECURSIVE:
652 AddInstrumentsRecursive(DbDir, FsDir, false, insDir);
653 break;
654 case FLAT:
655 AddInstrumentsRecursive(DbDir, FsDir, true, insDir);
656 break;
657 default:
658 throw Exception("Unknown scan mode");
659 }
660
661 return -1;
662 }
663
664 ScanJob job;
665 int jobId = Jobs.AddJob(job);
666 InstrumentsDbThread.Execute(new AddInstrumentsJob(jobId, Mode, DbDir, FsDir, insDir));
667
668 return jobId;
669 }
670
671 int InstrumentsDb::AddInstruments(String DbDir, String FilePath, int Index, bool bBackground) {
672 dmsg(2,("InstrumentsDb: AddInstruments(DbDir=%s,FilePath=%s,Index=%d,bBackground=%d)\n", DbDir.c_str(), FilePath.c_str(), Index, bBackground));
673 if(!bBackground) {
674 AddInstruments(DbDir, false, FilePath, Index);
675 return -1;
676 }
677
678 ScanJob job;
679 int jobId = Jobs.AddJob(job);
680 InstrumentsDbThread.Execute(new AddInstrumentsFromFileJob(jobId, DbDir, FilePath, Index, false));
681
682 return jobId;
683 }
684
685 void InstrumentsDb::AddInstruments(String DbDir, bool insDir, String FilePath, int Index, ScanProgress* pProgress) {
686 dmsg(2,("InstrumentsDb: AddInstruments(DbDir=%s,insDir=%d,FilePath=%s,Index=%d)\n", DbDir.c_str(), insDir, FilePath.c_str(), Index));
687 if (DbDir.empty() || FilePath.empty()) return;
688
689 DbInstrumentsMutex.Lock();
690 try {
691 int dirId = GetDirectoryId(DbDir);
692 if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedText(DbDir));
693
694 File f = File(FilePath);
695 if (!f.Exist()) {
696 std::stringstream ss;
697 ss << "Fail to stat `" << FilePath << "`: " << f.GetErrorMsg();
698 throw Exception(ss.str());
699 }
700
701 if (!f.IsFile()) {
702 std::stringstream ss;
703 ss << "`" << FilePath << "` is not an instrument file";
704 throw Exception(ss.str());
705 }
706
707 if(insDir) {
708 std::string tmp = f.basename(FilePath, ".");
709 String gigDir;
710 if(DbDir.length() == 1 && DbDir.at(0) == '/') //DbDir is /
711 gigDir = DbDir + (String)tmp + "/";
712 else
713 gigDir = DbDir +"/"+ (String)tmp + "/";
714 dmsg(2,("InstrumentsDb: AddInstrumentsNonrecursive(Dir from file mode=%d, Created SubDir=%s)\n",insDir, gigDir.c_str()));
715 DbInstrumentsMutex.Unlock();
716 AddDirectory(gigDir);//TODO: Add some error checking here to make sure the dir is created
717 DbInstrumentsMutex.Lock();
718 AddInstrumentsFromFile(gigDir, FilePath, Index, pProgress);
719 } else {
720 AddInstrumentsFromFile(DbDir, FilePath, Index, pProgress);
721 }
722 } catch (Exception e) {
723 DbInstrumentsMutex.Unlock();
724 throw e;
725 }
726
727 DbInstrumentsMutex.Unlock();
728 }
729
730 void InstrumentsDb::AddInstrumentsNonrecursive(String DbDir, String FsDir, bool insDir, ScanProgress* pProgress) {
731 dmsg(2,("InstrumentsDb: AddInstrumentsNonrecursive(DbDir=%s,FsDir=%s,insDir=%d)\n", DbDir.c_str(), FsDir.c_str(), insDir));
732 if (DbDir.empty() || FsDir.empty()) return;
733
734 DbInstrumentsMutex.Lock();
735 try {
736 int dirId = GetDirectoryId(DbDir);
737 if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedPath(DbDir));
738
739 File f = File(FsDir);
740 if (!f.Exist()) {
741 std::stringstream ss;
742 ss << "Fail to stat `" << FsDir << "`: " << f.GetErrorMsg();
743 throw Exception(ss.str());
744 }
745
746 if (!f.IsDirectory()) {
747 throw Exception("Directory expected: " + FsDir);
748 }
749
750 if (FsDir.at(FsDir.length() - 1) != File::DirSeparator) {
751 FsDir.push_back(File::DirSeparator);
752 }
753
754 try {
755 FileListPtr fileList = File::GetFiles(FsDir);
756 for (int i = 0; i < fileList->size(); i++) {
757 if(insDir)
758 {
759 //File gFile = File(fileList->at(i));
760 String gigDir;
761 if(DbDir.length() == 1 && DbDir.at(0) == '/') //DbDir is /
762 gigDir = DbDir + f.basename(fileList->at(i),".") + "/";
763 else
764 gigDir = DbDir +"/"+ f.basename(fileList->at(i),".") + "/";
765 dmsg(2,("InstrumentsDb: AddInstrumentsNonrecursive(Dir from file mode=%d, Created SubDir=%s)\n",insDir, gigDir.c_str()));
766 DbInstrumentsMutex.Unlock(); // UnLock the db so we can add our extra directory
767 AddDirectory(gigDir);//TODO: Add some error checking here to make sure the dir is created
768 DbInstrumentsMutex.Lock(); //Lock and carry on
769 AddInstrumentsFromFile(gigDir, FsDir + fileList->at(i), -1, pProgress);
770 }
771 else
772 {
773 AddInstrumentsFromFile(DbDir, FsDir + fileList->at(i), -1, pProgress);
774 }
775 }
776 } catch(Exception e) {
777 e.PrintMessage();
778 DbInstrumentsMutex.Unlock();
779 return;
780 }
781 } catch (Exception e) {
782 DbInstrumentsMutex.Unlock();
783 throw e;
784 }
785
786 DbInstrumentsMutex.Unlock();
787 }
788
789 void InstrumentsDb::AddInstrumentsRecursive(String DbDir, String FsDir, bool Flat, bool insDir, ScanProgress* pProgress) {
790 dmsg(2,("InstrumentsDb: AddInstrumentsRecursive(DbDir=%s,FsDir=%s,Flat=%d,insDir=%d)\n", DbDir.c_str(), FsDir.c_str(), Flat, insDir));
791 if (pProgress != NULL) {
792 InstrumentFileCounter c;
793 pProgress->SetTotalFileCount(c.Count(FsDir));
794 }
795
796 DirectoryScanner d;
797 d.Scan(DbDir, FsDir, Flat, insDir, pProgress);
798 }
799
800 int InstrumentsDb::GetInstrumentCount(int DirId) {
801 dmsg(2,("InstrumentsDb: GetInstrumentCount(DirId=%d)\n", DirId));
802 if(DirId == -1) return -1;
803
804 std::stringstream sql;
805 sql << "SELECT COUNT(*) FROM instruments WHERE dir_id=" << DirId;
806
807 return ExecSqlInt(sql.str());
808 }
809
810 int InstrumentsDb::GetInstrumentCount(String Dir, bool Recursive) {
811 dmsg(2,("InstrumentsDb: GetInstrumentCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
812 int i;
813
814 BeginTransaction();
815 try {
816 if (Recursive) {
817 InstrumentCounter instrumentCounter;
818 DirectoryTreeWalk(Dir, &instrumentCounter);
819 i = instrumentCounter.GetInstrumentCount();
820 } else {
821 i = GetInstrumentCount(GetDirectoryId(Dir));
822 }
823 } catch (Exception e) {
824 EndTransaction();
825 throw e;
826 }
827 EndTransaction();
828
829 if (i == -1) throw Exception("Unknown Db directory: " + toEscapedPath(Dir));
830 return i;
831 }
832
833 IntListPtr InstrumentsDb::GetInstrumentIDs(int DirId) {
834 std::stringstream sql;
835 sql << "SELECT instr_id FROM instruments WHERE dir_id=" << DirId;
836
837 return ExecSqlIntList(sql.str());
838 }
839
840 StringListPtr InstrumentsDb::GetInstruments(String Dir, bool Recursive) {
841 dmsg(2,("InstrumentsDb: GetInstruments(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
842 BeginTransaction();
843 try {
844 int dirId = GetDirectoryId(Dir);
845 if(dirId == -1) throw Exception("Unknown DB directory: " + toEscapedPath(Dir));
846
847 StringListPtr pInstrs;
848
849 if(Recursive) {
850 SearchQuery q;
851 InstrumentFinder instrumentFinder(&q);
852 DirectoryTreeWalk(Dir, &instrumentFinder);
853 pInstrs = instrumentFinder.GetInstruments();
854 } else {
855 std::stringstream sql;
856 sql << "SELECT instr_name FROM instruments WHERE dir_id=" << dirId;
857
858 pInstrs = ExecSqlStringList(sql.str());
859 // Converting to abstract names
860 for (int i = 0; i < pInstrs->size(); i++) {
861 for (int j = 0; j < pInstrs->at(i).length(); j++) {
862 if (pInstrs->at(i).at(j) == '/') pInstrs->at(i).at(j) = '\0';
863 }
864 }
865 }
866 EndTransaction();
867 return pInstrs;
868 } catch (Exception e) {
869 EndTransaction();
870 throw e;
871 }
872 }
873
874 int InstrumentsDb::GetInstrumentId(String Instr) {
875 dmsg(2,("InstrumentsDb: GetInstrumentId(Instr=%s)\n", Instr.c_str()));
876 String Dir = GetDirectoryPath(Instr);
877 if (Dir.empty()) return -1;
878
879 return GetInstrumentId(GetDirectoryId(Dir), GetFileName(Instr));
880 }
881
882 int InstrumentsDb::GetInstrumentId(int DirId, String InstrName) {
883 dmsg(2,("InstrumentsDb: GetInstrumentId(DirId=%d,InstrName=%s)\n", DirId, InstrName.c_str()));
884 if (DirId == -1 || InstrName.empty()) return -1;
885
886 std::stringstream sql;
887 sql << "SELECT instr_id FROM instruments WHERE dir_id=";
888 sql << DirId << " AND instr_name=?";
889 return ExecSqlInt(sql.str(), toDbName(InstrName));
890 }
891
892 String InstrumentsDb::GetInstrumentName(int InstrId) {
893 dmsg(2,("InstrumentsDb: GetInstrumentName(InstrId=%d)\n", InstrId));
894 std::stringstream sql;
895 sql << "SELECT instr_name FROM instruments WHERE instr_id=" << InstrId;
896 return toAbstractName(ExecSqlString(sql.str()));
897 }
898
899 void InstrumentsDb::RemoveInstrument(String Instr) {
900 dmsg(2,("InstrumentsDb: RemoveInstrument(Instr=%s)\n", Instr.c_str()));
901 String ParentDir = GetDirectoryPath(Instr);
902 if(ParentDir.empty()) throw Exception("Unknown parent directory");
903
904 BeginTransaction();
905 try {
906 int instrId = GetInstrumentId(Instr);
907 if(instrId == -1) {
908 throw Exception("The specified instrument does not exist: " + toEscapedPath(Instr));
909 }
910 RemoveInstrument(instrId);
911 } catch (Exception e) {
912 EndTransaction();
913 throw e;
914 }
915 EndTransaction();
916 FireInstrumentCountChanged(ParentDir);
917 }
918
919 void InstrumentsDb::RemoveInstrument(int InstrId) {
920 dmsg(2,("InstrumentsDb: RemoveInstrument(InstrId=%d)\n", InstrId));
921
922 std::stringstream sql;
923 sql << "DELETE FROM instruments WHERE instr_id=" << InstrId;
924
925 ExecSql(sql.str());
926 }
927
928 void InstrumentsDb::RemoveAllInstruments(int DirId) {
929 dmsg(2,("InstrumentsDb: RemoveAllInstruments(DirId=%d)\n", DirId));
930
931 std::stringstream sql;
932 sql << "DELETE FROM instruments WHERE dir_id=" << DirId;
933 ExecSql(sql.str());
934 }
935
936 DbInstrument InstrumentsDb::GetInstrumentInfo(String Instr) {
937 dmsg(2,("InstrumentsDb: GetInstrumentInfo(Instr=%s)\n", Instr.c_str()));
938 DbInstrument i;
939
940 BeginTransaction();
941 try {
942 int id = GetInstrumentId(Instr);
943 if(id == -1) throw Exception("Unknown DB instrument: " + toEscapedPath(Instr));
944 i = GetInstrumentInfo(id);
945 } catch (Exception e) {
946 EndTransaction();
947 throw e;
948 }
949 EndTransaction();
950
951 return i;
952 }
953
954 DbInstrument InstrumentsDb::GetInstrumentInfo(int InstrId) {
955 sqlite3_stmt *pStmt = NULL;
956 std::stringstream sql;
957 sql << "SELECT instr_file,instr_nr,format_family,format_version,";
958 sql << "instr_size,created,modified,description,is_drum,product,";
959 sql << "artists,keywords FROM instruments WHERE instr_id=" << InstrId;
960
961 int res = sqlite3_prepare(GetDb(), sql.str().c_str(), -1, &pStmt, NULL);
962 if (res != SQLITE_OK) {
963 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
964 }
965
966 DbInstrument i;
967 res = sqlite3_step(pStmt);
968 if(res == SQLITE_ROW) {
969 i.InstrFile = ToString(sqlite3_column_text(pStmt, 0));
970 i.InstrNr = sqlite3_column_int(pStmt, 1);
971 i.FormatFamily = ToString(sqlite3_column_text(pStmt, 2));
972 i.FormatVersion = ToString(sqlite3_column_text(pStmt, 3));
973 i.Size = sqlite3_column_int64(pStmt, 4);
974 i.Created = ToString(sqlite3_column_text(pStmt, 5));
975 i.Modified = ToString(sqlite3_column_text(pStmt, 6));
976 i.Description = ToString(sqlite3_column_text(pStmt, 7));
977 i.IsDrum = sqlite3_column_int(pStmt, 8);
978 i.Product = ToString(sqlite3_column_text(pStmt, 9));
979 i.Artists = ToString(sqlite3_column_text(pStmt, 10));
980 i.Keywords = ToString(sqlite3_column_text(pStmt, 11));
981 } else {
982 sqlite3_finalize(pStmt);
983
984 if (res != SQLITE_DONE) {
985 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
986 } else {
987 throw Exception("Unknown DB instrument");
988 }
989 }
990
991 sqlite3_finalize(pStmt);
992 return i;
993 }
994
995 void InstrumentsDb::RenameInstrument(String Instr, String Name) {
996 dmsg(2,("InstrumentsDb: RenameInstrument(Instr=%s,Name=%s)\n", Instr.c_str(), Name.c_str()));
997 CheckFileName(Name);
998
999 BeginTransaction();
1000 try {
1001 int dirId = GetDirectoryId(GetDirectoryPath(Instr));
1002 if (dirId == -1) throw Exception("Unknown DB instrument: " + toEscapedPath(Instr));
1003
1004 int instrId = GetInstrumentId(dirId, GetFileName(Instr));
1005 if (instrId == -1) throw Exception("Unknown DB instrument: " + toEscapedPath(Instr));
1006
1007 if (GetInstrumentId(dirId, Name) != -1) {
1008 String s = toEscapedPath(Name);
1009 throw Exception("Cannot rename. Instrument with that name already exists: " + s);
1010 }
1011
1012 if (GetDirectoryId(dirId, Name) != -1) {
1013 String s = toEscapedPath(Name);
1014 throw Exception("Cannot rename. Directory with that name already exists: " + s);
1015 }
1016
1017 std::stringstream sql;
1018 sql << "UPDATE instruments SET instr_name=? WHERE instr_id=" << instrId;
1019 ExecSql(sql.str(), toDbName(Name));
1020 } catch (Exception e) {
1021 EndTransaction();
1022 throw e;
1023 }
1024 EndTransaction();
1025 FireInstrumentNameChanged(Instr, toAbstractName(Name));
1026 }
1027
1028 void InstrumentsDb::MoveInstrument(String Instr, String Dst) {
1029 dmsg(2,("InstrumentsDb: MoveInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
1030 String ParentDir = GetDirectoryPath(Instr);
1031 if(ParentDir.empty()) throw Exception("Unknown parent directory");
1032
1033 BeginTransaction();
1034 try {
1035 int dirId = GetDirectoryId(ParentDir);
1036 if (dirId == -1) throw Exception("Unknown DB instrument: " + toEscapedPath(Instr));
1037
1038 String instrName = GetFileName(Instr);
1039 int instrId = GetInstrumentId(dirId, instrName);
1040 if (instrId == -1) throw Exception("Unknown DB instrument: " + toEscapedPath(Instr));
1041
1042 int dstId = GetDirectoryId(Dst);
1043 if (dstId == -1) throw Exception("Unknown DB directory: " + toEscapedPath(Dst));
1044 if (dirId == dstId) {
1045 EndTransaction();
1046 return;
1047 }
1048
1049 if (GetInstrumentId(dstId, instrName) != -1) {
1050 String s = toEscapedPath(instrName);
1051 throw Exception("Cannot move. Instrument with that name already exists: " + s);
1052 }
1053
1054 if (GetDirectoryId(dstId, instrName) != -1) {
1055 String s = toEscapedPath(instrName);
1056 throw Exception("Cannot move. Directory with that name already exists: " + s);
1057 }
1058
1059 std::stringstream sql;
1060 sql << "UPDATE instruments SET dir_id=" << dstId;
1061 sql << " WHERE instr_id=" << instrId;
1062 ExecSql(sql.str());
1063 } catch (Exception e) {
1064 EndTransaction();
1065 throw e;
1066 }
1067 EndTransaction();
1068 FireInstrumentCountChanged(ParentDir);
1069 FireInstrumentCountChanged(Dst);
1070 }
1071
1072 void InstrumentsDb::CopyInstrument(String Instr, String Dst) {
1073 dmsg(2,("InstrumentsDb: CopyInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
1074 String ParentDir = GetDirectoryPath(Instr);
1075 if(ParentDir.empty()) throw Exception("Unknown parent directory");
1076
1077 BeginTransaction();
1078 try {
1079 int dirId = GetDirectoryId(GetDirectoryPath(Instr));
1080 if (dirId == -1) throw Exception("Unknown DB instrument: " + toEscapedPath(Instr));
1081
1082 String instrName = GetFileName(Instr);
1083 int instrId = GetInstrumentId(dirId, instrName);
1084 if (instrId == -1) throw Exception("Unknown DB instrument: " + toEscapedPath(Instr));
1085
1086 int dstId = GetDirectoryId(Dst);
1087 if (dstId == -1) throw Exception("Unknown DB directory: " + toEscapedPath(Dst));
1088 if (dirId == dstId) {
1089 EndTransaction();
1090 return;
1091 }
1092
1093 CopyInstrument(instrId, instrName, dstId, Dst);
1094 } catch (Exception e) {
1095 EndTransaction();
1096 throw e;
1097 }
1098 EndTransaction();
1099
1100 }
1101
1102 void InstrumentsDb::CopyInstrument(int InstrId, String InstrName, int DstDirId, String DstDir) {
1103 if (GetInstrumentId(DstDirId, InstrName) != -1) {
1104 String s = toEscapedPath(InstrName);
1105 throw Exception("Cannot copy. Instrument with that name already exists: " + s);
1106 }
1107
1108 if (GetDirectoryId(DstDirId, InstrName) != -1) {
1109 String s = toEscapedPath(InstrName);
1110 throw Exception("Cannot copy. Directory with that name already exists: " + s);
1111 }
1112
1113 DbInstrument i = GetInstrumentInfo(InstrId);
1114 sqlite3_stmt *pStmt = NULL;
1115 std::stringstream sql;
1116 sql << "INSERT INTO instruments (dir_id,instr_name,instr_file,instr_nr,format_family,";
1117 sql << "format_version,instr_size,description,is_drum,product,artists,keywords) ";
1118 sql << "VALUES (" << DstDirId << ",?,?," << i.InstrNr << ",?,?," << i.Size << ",?,";
1119 sql << i.IsDrum << ",?,?,?)";
1120
1121 int res = sqlite3_prepare(GetDb(), sql.str().c_str(), -1, &pStmt, NULL);
1122 if (res != SQLITE_OK) {
1123 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1124 }
1125
1126 String s = toDbName(InstrName);
1127 BindTextParam(pStmt, 1, s);
1128 BindTextParam(pStmt, 2, i.InstrFile);
1129 BindTextParam(pStmt, 3, i.FormatFamily);
1130 BindTextParam(pStmt, 4, i.FormatVersion);
1131 BindTextParam(pStmt, 5, i.Description);
1132 BindTextParam(pStmt, 6, i.Product);
1133 BindTextParam(pStmt, 7, i.Artists);
1134 BindTextParam(pStmt, 8, i.Keywords);
1135
1136 res = sqlite3_step(pStmt);
1137 if(res != SQLITE_DONE) {
1138 sqlite3_finalize(pStmt);
1139 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1140 }
1141
1142 sqlite3_finalize(pStmt);
1143 FireInstrumentCountChanged(DstDir);
1144 }
1145
1146 void InstrumentsDb::SetInstrumentDescription(String Instr, String Desc) {
1147 dmsg(2,("InstrumentsDb: SetInstrumentDescription(Instr=%s,Desc=%s)\n", Instr.c_str(), Desc.c_str()));
1148
1149 BeginTransaction();
1150 try {
1151 int id = GetInstrumentId(Instr);
1152 if(id == -1) throw Exception("Unknown DB instrument: " + toEscapedPath(Instr));
1153
1154 std::stringstream sql;
1155 sql << "UPDATE instruments SET description=?,modified=CURRENT_TIMESTAMP ";
1156 sql << "WHERE instr_id="<< id;
1157
1158 ExecSql(sql.str(), Desc);
1159 } catch (Exception e) {
1160 EndTransaction();
1161 throw e;
1162 }
1163 EndTransaction();
1164 FireInstrumentInfoChanged(Instr);
1165 }
1166
1167 void InstrumentsDb::AddInstrumentsFromFile(String DbDir, String File, int Index, ScanProgress* pProgress) {
1168 dmsg(2,("InstrumentsDb: AddInstrumentsFromFile(DbDir=%s,File=%s,Index=%d)\n", DbDir.c_str(), File.c_str(), Index));
1169
1170 if(File.length() < 4) return;
1171
1172 try {
1173 if(!strcasecmp(".gig", File.substr(File.length() - 4).c_str())) {
1174 if (pProgress != NULL) {
1175 pProgress->SetStatus(0);
1176 pProgress->CurrentFile = File;
1177 }
1178
1179 AddGigInstruments(DbDir, File, Index, pProgress);
1180
1181 if (pProgress != NULL) {
1182 pProgress->SetScannedFileCount(pProgress->GetScannedFileCount() + 1);
1183 }
1184 }
1185 } catch(Exception e) {
1186 e.PrintMessage();
1187 }
1188 }
1189
1190 void InstrumentsDb::AddGigInstruments(String DbDir, String FilePath, int Index, ScanProgress* pProgress) {
1191 dmsg(2,("InstrumentsDb: AddGigInstruments(DbDir=%s,FilePath=%s,Index=%d)\n", DbDir.c_str(), FilePath.c_str(), Index));
1192 int dirId = GetDirectoryId(DbDir);
1193 if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedPath(DbDir));
1194
1195 File f = File(FilePath);
1196 if (!f.Exist()) {
1197 std::stringstream ss;
1198 ss << "Fail to stat `" << FilePath << "`: " << f.GetErrorMsg();
1199 throw Exception(ss.str());
1200 }
1201
1202 if (!f.IsFile()) {
1203 std::stringstream ss;
1204 ss << "`" << FilePath << "` is not a regular file";
1205 throw Exception(ss.str());
1206 }
1207
1208 RIFF::File* riff = NULL;
1209 gig::File* gig = NULL;
1210 try {
1211 riff = new RIFF::File(FilePath);
1212 gig::File* gig = new gig::File(riff);
1213 gig->SetAutoLoad(false); // avoid time consuming samples scanning
1214
1215 std::stringstream sql;
1216 sql << "INSERT INTO instruments (dir_id,instr_name,instr_file,";
1217 sql << "instr_nr,format_family,format_version,instr_size,";
1218 sql << "description,is_drum,product,artists,keywords) VALUES (";
1219 sql << dirId << ",?,?,?,'GIG',?," << f.GetSize() << ",?,?,?,?,?)";
1220
1221 sqlite3_stmt* pStmt = NULL;
1222
1223 int res = sqlite3_prepare(GetDb(), sql.str().c_str(), -1, &pStmt, NULL);
1224 if (res != SQLITE_OK) {
1225 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1226 }
1227
1228 String s = toEscapedFsPath(FilePath);
1229 BindTextParam(pStmt, 2, s);
1230 String ver = "";
1231 if (gig->pVersion != NULL) ver = ToString(gig->pVersion->major);
1232 BindTextParam(pStmt, 4, ver);
1233
1234 if (Index == -1) {
1235 int instrIndex = 0;
1236 if (pProgress != NULL) gig->GetInstrument(0, &(pProgress->GigFileProgress)); // TODO: this workaround should be fixed
1237 gig::Instrument* pInstrument = gig->GetFirstInstrument();
1238 while (pInstrument) {
1239 BindTextParam(pStmt, 7, gig->pInfo->Product);
1240 BindTextParam(pStmt, 8, gig->pInfo->Artists);
1241 BindTextParam(pStmt, 9, gig->pInfo->Keywords);
1242 AddGigInstrument(pStmt, DbDir, dirId, FilePath, pInstrument, instrIndex);
1243
1244 instrIndex++;
1245 pInstrument = gig->GetNextInstrument();
1246 }
1247 } else {
1248 gig::Instrument* pInstrument;
1249 if (pProgress == NULL) pInstrument = gig->GetInstrument(Index);
1250 else pInstrument = gig->GetInstrument(Index, &(pProgress->GigFileProgress));
1251 if (pInstrument != NULL) {
1252 BindTextParam(pStmt, 7, gig->pInfo->Product);
1253 BindTextParam(pStmt, 8, gig->pInfo->Artists);
1254 BindTextParam(pStmt, 9, gig->pInfo->Keywords);
1255 AddGigInstrument(pStmt, DbDir, dirId, FilePath, pInstrument, Index);
1256 }
1257 }
1258
1259 sqlite3_finalize(pStmt);
1260 delete gig;
1261 delete riff;
1262 } catch (RIFF::Exception e) {
1263 if (gig != NULL) delete gig;
1264 if (riff != NULL) delete riff;
1265 std::stringstream ss;
1266 ss << "Failed to scan `" << FilePath << "`: " << e.Message;
1267
1268 throw Exception(ss.str());
1269 } catch (Exception e) {
1270 if (gig != NULL) delete gig;
1271 if (riff != NULL) delete riff;
1272 throw e;
1273 } catch (...) {
1274 if (gig != NULL) delete gig;
1275 if (riff != NULL) delete riff;
1276 throw Exception("Failed to scan `" + FilePath + "`");
1277 }
1278 }
1279
1280 void InstrumentsDb::AddGigInstrument(sqlite3_stmt* pStmt, String DbDir, int DirId, String File, gig::Instrument* pInstrument, int Index) {
1281 dmsg(2,("InstrumentsDb: AddGigInstrument(DbDir=%s,DirId=%d,File=%s,Index=%d)\n", DbDir.c_str(), DirId, File.c_str(), Index));
1282 String name = pInstrument->pInfo->Name;
1283 if (name == "") return;
1284 name = GetUniqueInstrumentName(DirId, name);
1285
1286 std::stringstream sql2;
1287 sql2 << "SELECT COUNT(*) FROM instruments WHERE instr_file=? AND ";
1288 sql2 << "instr_nr=" << Index;
1289 String s = toEscapedFsPath(File);
1290 if (ExecSqlInt(sql2.str(), s) > 0) return;
1291
1292 BindTextParam(pStmt, 1, name);
1293 BindIntParam(pStmt, 3, Index);
1294
1295 BindTextParam(pStmt, 5, pInstrument->pInfo->Comments);
1296 BindIntParam(pStmt, 6, pInstrument->IsDrum);
1297
1298 if (!pInstrument->pInfo->Product.empty()) {
1299 BindTextParam(pStmt, 7, pInstrument->pInfo->Product);
1300 }
1301 if (!pInstrument->pInfo->Artists.empty()) {
1302 BindTextParam(pStmt, 8, pInstrument->pInfo->Artists);
1303 }
1304
1305 if (!pInstrument->pInfo->Keywords.empty()) {
1306 BindTextParam(pStmt, 9, pInstrument->pInfo->Keywords);
1307 }
1308
1309 int res = sqlite3_step(pStmt);
1310 if(res != SQLITE_DONE) {
1311 sqlite3_finalize(pStmt);
1312 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1313 }
1314
1315 res = sqlite3_reset(pStmt);
1316 FireInstrumentCountChanged(DbDir);
1317 }
1318
1319 void InstrumentsDb::DirectoryTreeWalk(String AbstractPath, DirectoryHandler* pHandler) {
1320 int DirId = GetDirectoryId(AbstractPath);
1321 if(DirId == -1) throw Exception("Unknown DB directory: " + toEscapedPath(AbstractPath));
1322 DirectoryTreeWalk(pHandler, AbstractPath, DirId, 0);
1323 }
1324
1325 void InstrumentsDb::DirectoryTreeWalk(DirectoryHandler* pHandler, String AbstractPath, int DirId, int Level) {
1326 if(Level == 1000) throw Exception("Possible infinite loop detected");
1327 pHandler->ProcessDirectory(AbstractPath, DirId);
1328
1329 String s;
1330 StringListPtr pDirs = GetDirectories(DirId);
1331 for(int i = 0; i < pDirs->size(); i++) {
1332 if (AbstractPath.length() == 1 && AbstractPath.at(0) == '/') {
1333 s = "/" + pDirs->at(i);
1334 } else {
1335 s = AbstractPath + "/" + pDirs->at(i);
1336 }
1337 DirectoryTreeWalk(pHandler, s, GetDirectoryId(DirId, pDirs->at(i)), Level + 1);
1338 }
1339 }
1340
1341 StringListPtr InstrumentsDb::FindDirectories(String Dir, SearchQuery* pQuery, bool Recursive) {
1342 dmsg(2,("InstrumentsDb: FindDirectories(Dir=%s)\n", Dir.c_str()));
1343 DirectoryFinder directoryFinder(pQuery);
1344
1345 BeginTransaction();
1346 try {
1347 int DirId = GetDirectoryId(Dir);
1348 if(DirId == -1) throw Exception("Unknown DB directory: " + toEscapedPath(Dir));
1349
1350 if (Recursive) DirectoryTreeWalk(Dir, &directoryFinder);
1351 else directoryFinder.ProcessDirectory(Dir, DirId);
1352 } catch (Exception e) {
1353 EndTransaction();
1354 throw e;
1355 }
1356 EndTransaction();
1357
1358 return directoryFinder.GetDirectories();
1359 }
1360
1361 StringListPtr InstrumentsDb::FindInstruments(String Dir, SearchQuery* pQuery, bool Recursive) {
1362 dmsg(2,("InstrumentsDb: FindInstruments(Dir=%s)\n", Dir.c_str()));
1363 InstrumentFinder instrumentFinder(pQuery);
1364
1365 BeginTransaction();
1366 try {
1367 int DirId = GetDirectoryId(Dir);
1368 if(DirId == -1) throw Exception("Unknown DB directory: " + toEscapedPath(Dir));
1369
1370 if (Recursive) DirectoryTreeWalk(Dir, &instrumentFinder);
1371 else instrumentFinder.ProcessDirectory(Dir, DirId);
1372 } catch (Exception e) {
1373 EndTransaction();
1374 throw e;
1375 }
1376 EndTransaction();
1377
1378 return instrumentFinder.GetInstruments();
1379 }
1380
1381 StringListPtr InstrumentsDb::FindLostInstrumentFiles() {
1382 dmsg(2,("InstrumentsDb: FindLostInstrumentFiles()\n"));
1383
1384 BeginTransaction();
1385 try {
1386 StringListPtr files = ExecSqlStringList("SELECT DISTINCT instr_file FROM instruments");
1387 StringListPtr result(new std::vector<String>);
1388 for (int i = 0; i < files->size(); i++) {
1389 File f(toNonEscapedFsPath(files->at(i)));
1390 if (!f.Exist()) result->push_back(files->at(i));
1391 }
1392 return result;
1393 } catch (Exception e) {
1394 EndTransaction();
1395 throw e;
1396 }
1397 EndTransaction();
1398 }
1399
1400 void InstrumentsDb::SetInstrumentFilePath(String OldPath, String NewPath) {
1401 if (OldPath == NewPath) return;
1402 StringListPtr instrs;
1403 BeginTransaction();
1404 try {
1405 std::vector<String> params(2);
1406 params[0] = toEscapedFsPath(NewPath);
1407 params[1] = toEscapedFsPath(OldPath);
1408 instrs = GetInstrumentsByFile(OldPath);
1409 ExecSql("UPDATE instruments SET instr_file=? WHERE instr_file=?", params);
1410 } catch (Exception e) {
1411 EndTransaction();
1412 throw e;
1413 }
1414 EndTransaction();
1415
1416 for (int i = 0; i < instrs->size(); i++) {
1417 FireInstrumentInfoChanged(instrs->at(i));
1418 }
1419 }
1420
1421 void InstrumentsDb::BeginTransaction() {
1422 dmsg(2,("InstrumentsDb: BeginTransaction(InTransaction=%d)\n", InTransaction));
1423 DbInstrumentsMutex.Lock();
1424 if (InTransaction) return;
1425
1426 if(db == NULL) return;
1427 sqlite3_stmt *pStmt = NULL;
1428
1429 InTransaction = true;
1430 int res = sqlite3_prepare(db, "BEGIN TRANSACTION", -1, &pStmt, NULL);
1431 if (res != SQLITE_OK) {
1432 std::cerr << ToString(sqlite3_errmsg(db)) << std::endl;
1433 return;
1434 }
1435
1436 res = sqlite3_step(pStmt);
1437 if(res != SQLITE_DONE) {
1438 sqlite3_finalize(pStmt);
1439 std::cerr << ToString(sqlite3_errmsg(db)) << std::endl;
1440 return;
1441 }
1442
1443 sqlite3_finalize(pStmt);
1444 }
1445
1446 void InstrumentsDb::EndTransaction() {
1447 dmsg(2,("InstrumentsDb: EndTransaction(InTransaction=%d)\n", InTransaction));
1448 if (!InTransaction) {
1449 DbInstrumentsMutex.Unlock();
1450 return;
1451 }
1452 InTransaction = false;
1453
1454 if(db == NULL) {
1455 DbInstrumentsMutex.Unlock();
1456 return;
1457 }
1458 sqlite3_stmt *pStmt = NULL;
1459
1460 int res = sqlite3_prepare(db, "END TRANSACTION", -1, &pStmt, NULL);
1461 if (res != SQLITE_OK) {
1462 std::cerr << ToString(sqlite3_errmsg(db)) << std::endl;
1463 DbInstrumentsMutex.Unlock();
1464 return;
1465 }
1466
1467 res = sqlite3_step(pStmt);
1468 if(res != SQLITE_DONE) {
1469 sqlite3_finalize(pStmt);
1470 std::cerr << ToString(sqlite3_errmsg(db)) << std::endl;
1471 DbInstrumentsMutex.Unlock();
1472 return;
1473 }
1474
1475 sqlite3_finalize(pStmt);
1476 DbInstrumentsMutex.Unlock();
1477 }
1478
1479 void InstrumentsDb::ExecSql(String Sql) {
1480 dmsg(2,("InstrumentsDb: ExecSql(Sql=%s)\n", Sql.c_str()));
1481 std::vector<String> Params;
1482 ExecSql(Sql, Params);
1483 }
1484
1485 void InstrumentsDb::ExecSql(String Sql, String Param) {
1486 dmsg(2,("InstrumentsDb: ExecSql(Sql=%s,Param=%s)\n", Sql.c_str(), Param.c_str()));
1487 std::vector<String> Params;
1488 Params.push_back(Param);
1489 ExecSql(Sql, Params);
1490 }
1491
1492 void InstrumentsDb::ExecSql(String Sql, std::vector<String>& Params) {
1493 dmsg(2,("InstrumentsDb: ExecSql(Sql=%s,Params)\n", Sql.c_str()));
1494 sqlite3_stmt *pStmt = NULL;
1495
1496 int res = sqlite3_prepare(GetDb(), Sql.c_str(), -1, &pStmt, NULL);
1497 if (res != SQLITE_OK) {
1498 sqlite3_finalize(pStmt);
1499 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1500 }
1501
1502 for(int i = 0; i < Params.size(); i++) {
1503 BindTextParam(pStmt, i + 1, Params[i]);
1504 }
1505
1506 res = sqlite3_step(pStmt);
1507 if (res != SQLITE_DONE) {
1508 sqlite3_finalize(pStmt);
1509 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1510 }
1511
1512 sqlite3_finalize(pStmt);
1513 }
1514
1515 int InstrumentsDb::ExecSqlInt(String Sql) {
1516 dmsg(2,("InstrumentsDb: ExecSqlInt(Sql=%s)\n", Sql.c_str()));
1517 sqlite3_stmt *pStmt = NULL;
1518
1519 int res = sqlite3_prepare(GetDb(), Sql.c_str(), -1, &pStmt, NULL);
1520 if (res != SQLITE_OK) {
1521 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1522 }
1523
1524 int i = -1;
1525 res = sqlite3_step(pStmt);
1526 if(res == SQLITE_ROW) {
1527 i = sqlite3_column_int(pStmt, 0);
1528 } else if (res != SQLITE_DONE) {
1529 sqlite3_finalize(pStmt);
1530 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1531 }
1532
1533 sqlite3_finalize(pStmt);
1534
1535 return i;
1536 }
1537
1538 int InstrumentsDb::ExecSqlInt(String Sql, String Param) {
1539 dmsg(2,("InstrumentsDb: ExecSqlInt(Sql=%s,Param=%s)\n", Sql.c_str(), Param.c_str()));
1540 sqlite3_stmt *pStmt = NULL;
1541
1542 int res = sqlite3_prepare(GetDb(), Sql.c_str(), -1, &pStmt, NULL);
1543 if (res != SQLITE_OK) {
1544 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1545 }
1546
1547 BindTextParam(pStmt, 1, Param);
1548
1549 int i = -1;
1550 res = sqlite3_step(pStmt);
1551 if(res == SQLITE_ROW) {
1552 i = sqlite3_column_int(pStmt, 0);
1553 } else if (res != SQLITE_DONE) {
1554 sqlite3_finalize(pStmt);
1555 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1556 }
1557
1558 sqlite3_finalize(pStmt);
1559 return i;
1560 }
1561
1562 String InstrumentsDb::ExecSqlString(String Sql) {
1563 dmsg(2,("InstrumentsDb: ExecSqlString(Sql=%s)\n", Sql.c_str()));
1564 sqlite3_stmt *pStmt = NULL;
1565
1566 int res = sqlite3_prepare(GetDb(), Sql.c_str(), -1, &pStmt, NULL);
1567 if (res != SQLITE_OK) {
1568 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1569 }
1570
1571 String s;
1572 res = sqlite3_step(pStmt);
1573 if(res == SQLITE_ROW) {
1574 s = ToString(sqlite3_column_text(pStmt, 0));
1575 } else if (res != SQLITE_DONE) {
1576 sqlite3_finalize(pStmt);
1577 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1578 }
1579
1580 sqlite3_finalize(pStmt);
1581
1582 return s;
1583 }
1584
1585 IntListPtr InstrumentsDb::ExecSqlIntList(String Sql) {
1586 dmsg(2,("InstrumentsDb: ExecSqlIntList(Sql=%s)\n", Sql.c_str()));
1587 std::vector<String> Params;
1588 return ExecSqlIntList(Sql, Params);
1589 }
1590
1591 IntListPtr InstrumentsDb::ExecSqlIntList(String Sql, String Param) {
1592 dmsg(2,("InstrumentsDb: ExecSqlIntList(Sql=%s,Param=%s)\n", Sql.c_str(), Param.c_str()));
1593 std::vector<String> Params;
1594 Params.push_back(Param);
1595 return ExecSqlIntList(Sql, Params);
1596 }
1597
1598 IntListPtr InstrumentsDb::ExecSqlIntList(String Sql, std::vector<String>& Params) {
1599 dmsg(2,("InstrumentsDb: ExecSqlIntList(Sql=%s)\n", Sql.c_str()));
1600 IntListPtr intList(new std::vector<int>);
1601
1602 sqlite3_stmt *pStmt = NULL;
1603
1604 int res = sqlite3_prepare(GetDb(), Sql.c_str(), -1, &pStmt, NULL);
1605 if (res != SQLITE_OK) {
1606 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1607 }
1608
1609 for(int i = 0; i < Params.size(); i++) {
1610 BindTextParam(pStmt, i + 1, Params[i]);
1611 }
1612
1613 res = sqlite3_step(pStmt);
1614 while(res == SQLITE_ROW) {
1615 intList->push_back(sqlite3_column_int(pStmt, 0));
1616 res = sqlite3_step(pStmt);
1617 }
1618
1619 if (res != SQLITE_DONE) {
1620 sqlite3_finalize(pStmt);
1621 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1622 }
1623
1624 sqlite3_finalize(pStmt);
1625
1626 return intList;
1627 }
1628
1629 StringListPtr InstrumentsDb::ExecSqlStringList(String Sql) {
1630 dmsg(2,("InstrumentsDb: ExecSqlStringList(Sql=%s)\n", Sql.c_str()));
1631 StringListPtr stringList(new std::vector<String>);
1632
1633 sqlite3_stmt *pStmt = NULL;
1634
1635 int res = sqlite3_prepare(GetDb(), Sql.c_str(), -1, &pStmt, NULL);
1636 if (res != SQLITE_OK) {
1637 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1638 }
1639
1640 res = sqlite3_step(pStmt);
1641 while(res == SQLITE_ROW) {
1642 stringList->push_back(ToString(sqlite3_column_text(pStmt, 0)));
1643 res = sqlite3_step(pStmt);
1644 }
1645
1646 if (res != SQLITE_DONE) {
1647 sqlite3_finalize(pStmt);
1648 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1649 }
1650
1651 sqlite3_finalize(pStmt);
1652
1653 return stringList;
1654 }
1655
1656 void InstrumentsDb::BindTextParam(sqlite3_stmt* pStmt, int Index, String Text) {
1657 if (pStmt == NULL) return;
1658 int res = sqlite3_bind_text(pStmt, Index, Text.c_str(), -1, SQLITE_STATIC);
1659 if (res != SQLITE_OK) {
1660 sqlite3_finalize(pStmt);
1661 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1662 }
1663 }
1664
1665 void InstrumentsDb::BindIntParam(sqlite3_stmt* pStmt, int Index, int Param) {
1666 if (pStmt == NULL) return;
1667 int res = sqlite3_bind_int(pStmt, Index, Param);
1668 if (res != SQLITE_OK) {
1669 sqlite3_finalize(pStmt);
1670 throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1671 }
1672 }
1673
1674 void InstrumentsDb::Regexp(sqlite3_context* pContext, int argc, sqlite3_value** ppValue) {
1675 if (argc != 2) return;
1676
1677 String pattern = ToString(sqlite3_value_text(ppValue[0]));
1678 String str = ToString(sqlite3_value_text(ppValue[1]));
1679
1680 if(!fnmatch(pattern.c_str(), str.c_str(), FNM_CASEFOLD)) {
1681 sqlite3_result_int(pContext, 1);
1682 }
1683 }
1684
1685 String InstrumentsDb::GetDirectoryPath(String File) {
1686 if (File.empty()) return String("");
1687 if (File.at(0) != '/') String("");
1688 if (File.length() == 1) return File;
1689 if (File.at(File.length() - 1) == '/') return File.substr(0, File.length() - 1);
1690 int i = File.rfind('/', File.length() - 1);
1691 if(i == std::string::npos) return String("");
1692 if(i == 0) return String("/");
1693 return File.substr(0, i);
1694 }
1695
1696 String InstrumentsDb::GetFileName(String Path) {
1697 if (Path.length() < 2) return String("");
1698 if (Path.at(0) != '/') String("");
1699 if (Path.at(Path.length() - 1) == '/') return String("");
1700 int i = Path.rfind('/', Path.length() - 1);
1701 return Path.substr(i + 1);
1702 }
1703
1704 void InstrumentsDb::CheckPathName(String Path) {
1705 if (Path.empty()) return;
1706
1707 int i = 0, j = Path.find('/', i);
1708
1709 while(j != std::string::npos) {
1710 if (j + 1 >= Path.length()) return;
1711 if (Path.at(j + 1) == '/') throw Exception("Invalid path name: " + Path);
1712
1713 i = j + 1;
1714 j = Path.find('/', i);
1715 }
1716 }
1717
1718 String InstrumentsDb::GetParentDirectory(String Dir) {
1719 if (Dir.length() < 2) return String("");
1720 if (Dir.at(0) != '/') String("");
1721 int i = Dir.rfind('/', Dir.length() - 2);
1722 if (i == 0) return "/";
1723 return Dir.substr(0, i);
1724 }
1725
1726 void InstrumentsDb::Format() {
1727 DbInstrumentsMutex.Lock();
1728 if (db != NULL) {
1729 sqlite3_close(db);
1730 db = NULL;
1731 }
1732
1733 if (DbFile.empty()) DbFile = CONFIG_DEFAULT_INSTRUMENTS_DB_LOCATION;
1734 String bkp = DbFile + ".bkp";
1735 remove(bkp.c_str());
1736 if (rename(DbFile.c_str(), bkp.c_str()) && errno != ENOENT) {
1737 DbInstrumentsMutex.Unlock();
1738 throw Exception(String("Failed to backup database: ") + strerror(errno));
1739 }
1740
1741 String f = DbFile;
1742 DbFile = "";
1743 try { CreateInstrumentsDb(f); }
1744 catch(Exception e) {
1745 DbInstrumentsMutex.Unlock();
1746 throw e;
1747 }
1748 DbInstrumentsMutex.Unlock();
1749
1750 FireDirectoryCountChanged("/");
1751 FireInstrumentCountChanged("/");
1752 }
1753
1754 void InstrumentsDb::CheckFileName(String File) {
1755 if (File.empty()) throw Exception("Invalid file name: " + File);
1756 }
1757
1758 String InstrumentsDb::GetUniqueInstrumentName(int DirId, String Name) {
1759 dmsg(2,("InstrumentsDb: GetUniqueInstrumentName(DirId=%d,Name=%s)\n", DirId, Name.c_str()));
1760
1761 if (GetInstrumentId(DirId, Name) == -1 && GetDirectoryId(DirId, Name) == -1) return Name;
1762 std::stringstream ss;
1763 for(int i = 2; i < 1001; i++) {
1764 ss.str("");
1765 ss << Name << '[' << i << ']';
1766 if (GetInstrumentId(DirId, ss.str()) == -1 && GetInstrumentId(DirId, ss.str()) == -1) {
1767 return ss.str();
1768 }
1769 }
1770
1771 throw Exception("Unable to find an unique name: " + Name);
1772 }
1773
1774 String InstrumentsDb::toDbName(String AbstractName) {
1775 for (int i = 0; i < AbstractName.length(); i++) {
1776 if (AbstractName.at(i) == '\0') AbstractName.at(i) = '/';
1777 }
1778 return AbstractName;
1779 }
1780
1781 String InstrumentsDb::toEscapedPath(String AbstractName) {
1782 for (int i = 0; i < AbstractName.length(); i++) {
1783 if (AbstractName.at(i) == '\0') AbstractName.replace(i++, 1, "\\x2f");
1784 else if (AbstractName.at(i) == '\\') AbstractName.replace(i++, 1, "\\\\");
1785 else if (AbstractName.at(i) == '\'') AbstractName.replace(i++, 1, "\\'");
1786 else if (AbstractName.at(i) == '"') AbstractName.replace(i++, 1, "\\\"");
1787 else if (AbstractName.at(i) == '\r') AbstractName.replace(i++, 1, "\\r");
1788 else if (AbstractName.at(i) == '\n') AbstractName.replace(i++, 1, "\\n");
1789 }
1790 return AbstractName;
1791 }
1792
1793 String InstrumentsDb::toEscapedText(String text) {
1794 for (int i = 0; i < text.length(); i++) {
1795 if (text.at(i) == '\\') text.replace(i++, 1, "\\\\");
1796 else if (text.at(i) == '\'') text.replace(i++, 1, "\\'");
1797 else if (text.at(i) == '"') text.replace(i++, 1, "\\\"");
1798 else if (text.at(i) == '\r') text.replace(i++, 1, "\\r");
1799 else if (text.at(i) == '\n') text.replace(i++, 1, "\\n");
1800 }
1801 return text;
1802 }
1803
1804 String InstrumentsDb::toNonEscapedText(String text) {
1805 String sb;
1806 for (int i = 0; i < text.length(); i++) {
1807 char c = text.at(i);
1808 if(c == '\\') {
1809 if(i >= text.length()) {
1810 std::cerr << "Broken escape sequence!" << std::endl;
1811 break;
1812 }
1813 char c2 = text.at(++i);
1814 if(c2 == '\'') sb.push_back('\'');
1815 else if(c2 == '"') sb.push_back('"');
1816 else if(c2 == '\\') sb.push_back('\\');
1817 else if(c2 == 'r') sb.push_back('\r');
1818 else if(c2 == 'n') sb.push_back('\n');
1819 else std::cerr << "Unknown escape sequence \\" << c2 << std::endl;
1820 } else {
1821 sb.push_back(c);
1822 }
1823 }
1824 return sb;
1825 }
1826
1827 String InstrumentsDb::toEscapedFsPath(String FsPath) {
1828 return toEscapedText(FsPath);
1829 }
1830
1831 String InstrumentsDb::toNonEscapedFsPath(String FsPath) {
1832 return toNonEscapedText(FsPath);
1833 }
1834
1835 String InstrumentsDb::toAbstractName(String DbName) {
1836 for (int i = 0; i < DbName.length(); i++) {
1837 if (DbName.at(i) == '/') DbName.at(i) = '\0';
1838 }
1839 return DbName;
1840 }
1841
1842 void InstrumentsDb::FireDirectoryCountChanged(String Dir) {
1843 for (int i = 0; i < llInstrumentsDbListeners.GetListenerCount(); i++) {
1844 llInstrumentsDbListeners.GetListener(i)->DirectoryCountChanged(Dir);
1845 }
1846 }
1847
1848 void InstrumentsDb::FireDirectoryInfoChanged(String Dir) {
1849 for (int i = 0; i < llInstrumentsDbListeners.GetListenerCount(); i++) {
1850 llInstrumentsDbListeners.GetListener(i)->DirectoryInfoChanged(Dir);
1851 }
1852 }
1853
1854 void InstrumentsDb::FireDirectoryNameChanged(String Dir, String NewName) {
1855 for (int i = 0; i < llInstrumentsDbListeners.GetListenerCount(); i++) {
1856 llInstrumentsDbListeners.GetListener(i)->DirectoryNameChanged(Dir, NewName);
1857 }
1858 }
1859
1860 void InstrumentsDb::FireInstrumentCountChanged(String Dir) {
1861 for (int i = 0; i < llInstrumentsDbListeners.GetListenerCount(); i++) {
1862 llInstrumentsDbListeners.GetListener(i)->InstrumentCountChanged(Dir);
1863 }
1864 }
1865
1866 void InstrumentsDb::FireInstrumentInfoChanged(String Instr) {
1867 for (int i = 0; i < llInstrumentsDbListeners.GetListenerCount(); i++) {
1868 llInstrumentsDbListeners.GetListener(i)->InstrumentInfoChanged(Instr);
1869 }
1870 }
1871
1872 void InstrumentsDb::FireInstrumentNameChanged(String Instr, String NewName) {
1873 for (int i = 0; i < llInstrumentsDbListeners.GetListenerCount(); i++) {
1874 llInstrumentsDbListeners.GetListener(i)->InstrumentNameChanged(Instr, NewName);
1875 }
1876 }
1877
1878 void InstrumentsDb::FireJobStatusChanged(int JobId) {
1879 for (int i = 0; i < llInstrumentsDbListeners.GetListenerCount(); i++) {
1880 llInstrumentsDbListeners.GetListener(i)->JobStatusChanged(JobId);
1881 }
1882 }
1883
1884 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC