/[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 1161 - (hide annotations) (download)
Mon Apr 16 15:51:18 2007 UTC (17 years ago) by iliev
File size: 46259 byte(s)
* Implemented instruments database

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

  ViewVC Help
Powered by ViewVC