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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1717 - (hide annotations) (download)
Sun Mar 16 17:43:20 2008 UTC (16 years, 1 month ago) by iliev
File size: 65520 byte(s)
* moved all OS dependent file operation to File class

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

  ViewVC Help
Powered by ViewVC