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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 iliev 1200 /***************************************************************************
2     * *
3 iliev 1717 * Copyright (C) 2007, 2008 Grigor Iliev *
4 iliev 1200 * *
5     * This program is free software; you can redistribute it and/or modify *
6     * it under the terms of the GNU General Public License as published by *
7     * the Free Software Foundation; either version 2 of the License, or *
8     * (at your option) any later version. *
9     * *
10     * This program is distributed in the hope that it will be useful, *
11     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13     * GNU General Public License for more details. *
14     * *
15     * You should have received a copy of the GNU General Public License *
16     * along with this program; if not, write to the Free Software *
17     * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, *
18     * MA 02110-1301 USA *
19     ***************************************************************************/
20    
21     #include "InstrumentsDbUtilities.h"
22    
23 iliev 1717 #include "../common/File.h"
24 schoenebeck 1424 #include "../common/global_private.h"
25 iliev 1200
26     #include <errno.h>
27    
28     #include "../common/Exception.h"
29     #include "InstrumentsDb.h"
30    
31     namespace LinuxSampler {
32    
33     void DbInstrument::Copy(const DbInstrument& Instr) {
34     if (this == &Instr) return;
35    
36     InstrFile = Instr.InstrFile;
37     InstrNr = Instr.InstrNr;
38     FormatFamily = Instr.FormatFamily;
39     FormatVersion = Instr.FormatVersion;
40     Size = Instr.Size;
41     Created = Instr.Created;
42     Modified = Instr.Modified;
43     Description = Instr.Description;
44     IsDrum = Instr.IsDrum;
45     Product = Instr.Product;
46     Artists = Instr.Artists;
47     Keywords = Instr.Keywords;
48     }
49    
50    
51     void DbDirectory::Copy(const DbDirectory& Dir) {
52     if (this == &Dir) return;
53    
54     Created = Dir.Created;
55     Modified = Dir.Modified;
56     Description = Dir.Description;
57     }
58    
59     SearchQuery::SearchQuery() {
60     MinSize = -1;
61     MaxSize = -1;
62     InstrType = BOTH;
63     }
64    
65     void SearchQuery::SetFormatFamilies(String s) {
66     if (s.length() == 0) return;
67     int i = 0;
68     int j = s.find(',', 0);
69    
70     while (j != std::string::npos) {
71     FormatFamilies.push_back(s.substr(i, j - i));
72     i = j + 1;
73     j = s.find(',', i);
74     }
75    
76     if (i < s.length()) FormatFamilies.push_back(s.substr(i));
77     }
78    
79     void SearchQuery::SetSize(String s) {
80     String s2 = GetMin(s);
81     if (s2.length() > 0) MinSize = atoll(s2.c_str());
82     else MinSize = -1;
83    
84     s2 = GetMax(s);
85     if (s2.length() > 0) MaxSize = atoll(s2.c_str());
86     else MaxSize = -1;
87     }
88    
89     void SearchQuery::SetCreated(String s) {
90     CreatedAfter = GetMin(s);
91     CreatedBefore = GetMax(s);
92     }
93    
94     void SearchQuery::SetModified(String s) {
95     ModifiedAfter = GetMin(s);
96     ModifiedBefore = GetMax(s);
97     }
98    
99     String SearchQuery::GetMin(String s) {
100     if (s.length() < 3) return "";
101     if (s.at(0) == '.' && s.at(1) == '.') return "";
102     int i = s.find("..");
103     if (i == std::string::npos) return "";
104     return s.substr(0, i);
105     }
106    
107     String SearchQuery::GetMax(String s) {
108     if (s.length() < 3) return "";
109     if (s.find("..", s.length() - 2) != std::string::npos) return "";
110     int i = s.find("..");
111     if (i == std::string::npos) return "";
112     return s.substr(i + 2);
113     }
114    
115     void ScanJob::Copy(const ScanJob& Job) {
116     if (this == &Job) return;
117    
118     JobId = Job.JobId;
119     FilesTotal = Job.FilesTotal;
120     FilesScanned = Job.FilesScanned;
121     Scanning = Job.Scanning;
122     Status = Job.Status;
123     }
124    
125     int JobList::AddJob(ScanJob Job) {
126     if (Counter + 1 < Counter) Counter = 0;
127     else Counter++;
128     Job.JobId = Counter;
129     Jobs.push_back(Job);
130     if (Jobs.size() > 3) {
131     std::vector<ScanJob>::iterator iter = Jobs.begin();
132     Jobs.erase(iter);
133     }
134     return Job.JobId;
135     }
136    
137     ScanJob& JobList::GetJobById(int JobId) {
138     for (int i = 0; i < Jobs.size(); i++) {
139     if (Jobs.at(i).JobId == JobId) return Jobs.at(i);
140     }
141    
142     throw Exception("Invalid job ID: " + ToString(JobId));
143     }
144    
145     bool AbstractFinder::IsRegex(String Pattern) {
146     if(Pattern.find('?') != String::npos) return true;
147     if(Pattern.find('*') != String::npos) return true;
148     return false;
149     }
150    
151     void AbstractFinder::AddSql(String Col, String Pattern, std::stringstream& Sql) {
152     if (Pattern.length() == 0) return;
153    
154     if (IsRegex(Pattern)) {
155     Sql << " AND " << Col << " regexp ?";
156     Params.push_back(Pattern);
157     return;
158     }
159    
160     String buf;
161     std::vector<String> tokens;
162     std::vector<String> tokens2;
163     std::stringstream ss(Pattern);
164     while (ss >> buf) tokens.push_back(buf);
165    
166     if (tokens.size() == 0) {
167     Sql << " AND " << Col << " LIKE ?";
168     Params.push_back("%" + Pattern + "%");
169     return;
170     }
171    
172     bool b = false;
173     for (int i = 0; i < tokens.size(); i++) {
174     Sql << (i == 0 ? " AND (" : "");
175    
176     for (int j = 0; j < tokens.at(i).length(); j++) {
177     if (tokens.at(i).at(j) == '+') tokens.at(i).at(j) = ' ';
178     }
179    
180     ss.clear();
181     ss.str("");
182     ss << tokens.at(i);
183    
184     tokens2.clear();
185     while (ss >> buf) tokens2.push_back(buf);
186    
187     if (b && tokens2.size() > 0) Sql << " OR ";
188     if (tokens2.size() > 1) Sql << "(";
189     for (int j = 0; j < tokens2.size(); j++) {
190     if (j != 0) Sql << " AND ";
191     Sql << Col << " LIKE ?";
192     Params.push_back("%" + tokens2.at(j) + "%");
193     b = true;
194     }
195     if (tokens2.size() > 1) Sql << ")";
196     }
197     if (!b) Sql << "0)";
198     else Sql << ")";
199     }
200    
201     DirectoryFinder::DirectoryFinder(SearchQuery* pQuery) : pDirectories(new std::vector<String>) {
202     pStmt = NULL;
203     this->pQuery = pQuery;
204     std::stringstream sql;
205     sql << "SELECT dir_name from instr_dirs WHERE dir_id!=0 AND parent_dir_id=?";
206    
207     if (pQuery->CreatedAfter.length() != 0) {
208     sql << " AND created > ?";
209     Params.push_back(pQuery->CreatedAfter);
210     }
211     if (pQuery->CreatedBefore.length() != 0) {
212     sql << " AND created < ?";
213     Params.push_back(pQuery->CreatedBefore);
214     }
215     if (pQuery->ModifiedAfter.length() != 0) {
216     sql << " AND modified > ?";
217     Params.push_back(pQuery->ModifiedAfter);
218     }
219     if (pQuery->ModifiedBefore.length() != 0) {
220     sql << " AND modified < ?";
221     Params.push_back(pQuery->ModifiedBefore);
222     }
223    
224     AddSql("dir_name", pQuery->Name, sql);
225     AddSql("description", pQuery->Description, sql);
226     SqlQuery = sql.str();
227    
228     InstrumentsDb* idb = InstrumentsDb::GetInstrumentsDb();
229    
230     int res = sqlite3_prepare(idb->GetDb(), SqlQuery.c_str(), -1, &pStmt, NULL);
231     if (res != SQLITE_OK) {
232     throw Exception("DB error: " + ToString(sqlite3_errmsg(idb->GetDb())));
233     }
234    
235     for(int i = 0; i < Params.size(); i++) {
236     idb->BindTextParam(pStmt, i + 2, Params.at(i));
237     }
238     }
239    
240     DirectoryFinder::~DirectoryFinder() {
241     if (pStmt != NULL) sqlite3_finalize(pStmt);
242     }
243    
244     StringListPtr DirectoryFinder::GetDirectories() {
245     return pDirectories;
246     }
247    
248     void DirectoryFinder::ProcessDirectory(String Path, int DirId) {
249     InstrumentsDb* idb = InstrumentsDb::GetInstrumentsDb();
250     idb->BindIntParam(pStmt, 1, DirId);
251    
252     String s = Path;
253     if(Path.compare("/") != 0) s += "/";
254     int res = sqlite3_step(pStmt);
255     while(res == SQLITE_ROW) {
256 iliev 1345 pDirectories->push_back(s + idb->toAbstractName(ToString(sqlite3_column_text(pStmt, 0))));
257 iliev 1200 res = sqlite3_step(pStmt);
258     }
259    
260     if (res != SQLITE_DONE) {
261     sqlite3_finalize(pStmt);
262     throw Exception("DB error: " + ToString(sqlite3_errmsg(idb->GetDb())));
263     }
264    
265     res = sqlite3_reset(pStmt);
266     if (res != SQLITE_OK) {
267     sqlite3_finalize(pStmt);
268     throw Exception("DB error: " + ToString(sqlite3_errmsg(idb->GetDb())));
269     }
270     }
271    
272     InstrumentFinder::InstrumentFinder(SearchQuery* pQuery) : pInstruments(new std::vector<String>) {
273     pStmt = NULL;
274     this->pQuery = pQuery;
275     std::stringstream sql;
276     sql << "SELECT instr_name from instruments WHERE dir_id=?";
277    
278     if (pQuery->CreatedAfter.length() != 0) {
279     sql << " AND created > ?";
280     Params.push_back(pQuery->CreatedAfter);
281     }
282     if (pQuery->CreatedBefore.length() != 0) {
283     sql << " AND created < ?";
284     Params.push_back(pQuery->CreatedBefore);
285     }
286     if (pQuery->ModifiedAfter.length() != 0) {
287     sql << " AND modified > ?";
288     Params.push_back(pQuery->ModifiedAfter);
289     }
290     if (pQuery->ModifiedBefore.length() != 0) {
291     sql << " AND modified < ?";
292     Params.push_back(pQuery->ModifiedBefore);
293     }
294     if (pQuery->MinSize != -1) sql << " AND instr_size > " << pQuery->MinSize;
295     if (pQuery->MaxSize != -1) sql << " AND instr_size < " << pQuery->MaxSize;
296    
297     if (pQuery->InstrType == SearchQuery::CHROMATIC) sql << " AND is_drum = 0";
298     else if (pQuery->InstrType == SearchQuery::DRUM) sql << " AND is_drum != 0";
299    
300     if (pQuery->FormatFamilies.size() > 0) {
301     sql << " AND (format_family=?";
302     Params.push_back(pQuery->FormatFamilies.at(0));
303     for (int i = 1; i < pQuery->FormatFamilies.size(); i++) {
304     sql << "OR format_family=?";
305     Params.push_back(pQuery->FormatFamilies.at(i));
306     }
307     sql << ")";
308     }
309    
310     AddSql("instr_name", pQuery->Name, sql);
311     AddSql("description", pQuery->Description, sql);
312     AddSql("product", pQuery->Product, sql);
313     AddSql("artists", pQuery->Artists, sql);
314     AddSql("keywords", pQuery->Keywords, sql);
315     SqlQuery = sql.str();
316    
317     InstrumentsDb* idb = InstrumentsDb::GetInstrumentsDb();
318    
319     int res = sqlite3_prepare(idb->GetDb(), SqlQuery.c_str(), -1, &pStmt, NULL);
320     if (res != SQLITE_OK) {
321     throw Exception("DB error: " + ToString(sqlite3_errmsg(idb->GetDb())));
322     }
323    
324     for(int i = 0; i < Params.size(); i++) {
325     idb->BindTextParam(pStmt, i + 2, Params.at(i));
326     }
327     }
328    
329     InstrumentFinder::~InstrumentFinder() {
330     if (pStmt != NULL) sqlite3_finalize(pStmt);
331     }
332    
333     void InstrumentFinder::ProcessDirectory(String Path, int DirId) {
334     InstrumentsDb* idb = InstrumentsDb::GetInstrumentsDb();
335     idb->BindIntParam(pStmt, 1, DirId);
336    
337     String s = Path;
338     if(Path.compare("/") != 0) s += "/";
339     int res = sqlite3_step(pStmt);
340     while(res == SQLITE_ROW) {
341 iliev 1345 pInstruments->push_back(s + idb->toAbstractName(ToString(sqlite3_column_text(pStmt, 0))));
342 iliev 1200 res = sqlite3_step(pStmt);
343     }
344    
345     if (res != SQLITE_DONE) {
346     sqlite3_finalize(pStmt);
347     throw Exception("DB error: " + ToString(sqlite3_errmsg(idb->GetDb())));
348     }
349    
350     res = sqlite3_reset(pStmt);
351     if (res != SQLITE_OK) {
352     sqlite3_finalize(pStmt);
353     throw Exception("DB error: " + ToString(sqlite3_errmsg(idb->GetDb())));
354     }
355     }
356    
357     StringListPtr InstrumentFinder::GetInstruments() {
358     return pInstruments;
359     }
360    
361     void DirectoryCounter::ProcessDirectory(String Path, int DirId) {
362     count += InstrumentsDb::GetInstrumentsDb()->GetDirectoryCount(DirId);
363     }
364    
365     void InstrumentCounter::ProcessDirectory(String Path, int DirId) {
366     count += InstrumentsDb::GetInstrumentsDb()->GetInstrumentCount(DirId);
367     }
368    
369     DirectoryCopier::DirectoryCopier(String SrcParentDir, String DestDir) {
370     this->SrcParentDir = SrcParentDir;
371     this->DestDir = DestDir;
372    
373     if (DestDir.at(DestDir.length() - 1) != '/') {
374     this->DestDir.append("/");
375     }
376     if (SrcParentDir.at(SrcParentDir.length() - 1) != '/') {
377     this->SrcParentDir.append("/");
378     }
379     }
380    
381     void DirectoryCopier::ProcessDirectory(String Path, int DirId) {
382     InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
383    
384     String dir = DestDir;
385     String subdir = Path;
386     if(subdir.length() > SrcParentDir.length()) {
387     subdir = subdir.substr(SrcParentDir.length());
388     dir += subdir;
389     db->AddDirectory(dir);
390     }
391    
392     int dstDirId = db->GetDirectoryId(dir);
393 iliev 1345 if(dstDirId == -1) {
394     throw Exception("Unkown DB directory: " + InstrumentsDb::toEscapedPath(dir));
395     }
396 iliev 1200 IntListPtr ids = db->GetInstrumentIDs(DirId);
397     for (int i = 0; i < ids->size(); i++) {
398     String name = db->GetInstrumentName(ids->at(i));
399     db->CopyInstrument(ids->at(i), name, dstDirId, dir);
400     }
401     }
402    
403     ScanProgress::ScanProgress() {
404     TotalFileCount = ScannedFileCount = Status = 0;
405     CurrentFile = "";
406     GigFileProgress.custom = this;
407     GigFileProgress.callback = GigFileProgressCallback;
408     }
409    
410     void ScanProgress::StatusChanged() {
411     InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
412     db->Jobs.GetJobById(JobId).FilesTotal = GetTotalFileCount();
413     db->Jobs.GetJobById(JobId).FilesScanned = GetScannedFileCount();
414     db->Jobs.GetJobById(JobId).Scanning = CurrentFile;
415     db->Jobs.GetJobById(JobId).Status = GetStatus();
416    
417     InstrumentsDb::GetInstrumentsDb()->FireJobStatusChanged(JobId);
418     }
419    
420     int ScanProgress::GetTotalFileCount() {
421     return TotalFileCount;
422     }
423    
424     void ScanProgress::SetTotalFileCount(int Count) {
425     if (TotalFileCount == Count) return;
426     TotalFileCount = Count;
427     StatusChanged();
428     }
429    
430     int ScanProgress::GetScannedFileCount() {
431     return ScannedFileCount;
432     }
433    
434     void ScanProgress::SetScannedFileCount(int Count) {
435     if (ScannedFileCount == Count) return;
436     ScannedFileCount = Count;
437     if (Count > TotalFileCount) TotalFileCount = Count;
438     StatusChanged();
439     }
440    
441     int ScanProgress::GetStatus() {
442     return Status;
443     }
444    
445     void ScanProgress::SetStatus(int Status) {
446     if (this->Status == Status) return;
447     if (Status < 0) this->Status = 0;
448     else if (Status > 100) this->Status = 100;
449     else this->Status = Status;
450     StatusChanged();
451     }
452    
453     void ScanProgress::SetErrorStatus(int Err) {
454     if (Err > 0) Err *= -1;
455     Status = Err;
456     StatusChanged();
457     }
458    
459     void ScanProgress::GigFileProgressCallback(gig::progress_t* pProgress) {
460     if (pProgress == NULL) return;
461     ScanProgress* sp = static_cast<ScanProgress*> (pProgress->custom);
462    
463     sp->SetStatus((int)(pProgress->factor * 100));
464     }
465    
466     AddInstrumentsJob::AddInstrumentsJob(int JobId, ScanMode Mode, String DbDir, String FsDir) {
467     this->JobId = JobId;
468     Progress.JobId = JobId;
469     this->Mode = Mode;
470     this->DbDir = DbDir;
471     this->FsDir = FsDir;
472     }
473    
474     void AddInstrumentsJob::Run() {
475     try {
476     InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
477    
478     switch (Mode) {
479     case NON_RECURSIVE:
480     Progress.SetTotalFileCount(GetFileCount());
481     db->AddInstrumentsNonrecursive(DbDir, FsDir, &Progress);
482     break;
483     case RECURSIVE:
484     db->AddInstrumentsRecursive(DbDir, FsDir, false, &Progress);
485     break;
486     case FLAT:
487     db->AddInstrumentsRecursive(DbDir, FsDir, true, &Progress);
488     break;
489     default:
490     throw Exception("Unknown scan mode");
491     }
492 iliev 1208
493     // Just to be sure that the frontends will be notified about the job completion
494     if (Progress.GetTotalFileCount() != Progress.GetScannedFileCount()) {
495     Progress.SetTotalFileCount(Progress.GetScannedFileCount());
496     }
497     if (Progress.GetStatus() != 100) Progress.SetStatus(100);
498 iliev 1200 } catch(Exception e) {
499     Progress.SetErrorStatus(-1);
500     throw e;
501     }
502     }
503    
504     int AddInstrumentsJob::GetFileCount() {
505     int count = 0;
506    
507 iliev 1717 try {
508     FileListPtr fileList = File::GetFiles(FsDir);
509 iliev 1200
510 iliev 1717 for (int i = 0; i < fileList->size(); i++) {
511     String s = fileList->at(i);
512     if (s.length() < 4) continue;
513     if(!strcasecmp(".gig", s.substr(s.length() - 4).c_str())) count++;
514 iliev 1200 }
515 iliev 1717 } catch(Exception e) {
516     e.PrintMessage();
517     return 0;
518 iliev 1200 }
519    
520     return count;
521     }
522    
523     AddInstrumentsFromFileJob::AddInstrumentsFromFileJob(int JobId, String DbDir, String FilePath, int Index) {
524     this->JobId = JobId;
525     Progress.JobId = JobId;
526     Progress.SetTotalFileCount(1);
527    
528     this->DbDir = DbDir;
529     this->FilePath = FilePath;
530     this->Index = Index;
531     }
532    
533     void AddInstrumentsFromFileJob::Run() {
534 iliev 1208 try {
535     InstrumentsDb::GetInstrumentsDb()->AddInstruments(DbDir, FilePath, Index, &Progress);
536    
537     // Just to be sure that the frontends will be notified about the job completion
538     if (Progress.GetTotalFileCount() != Progress.GetScannedFileCount()) {
539     Progress.SetTotalFileCount(Progress.GetScannedFileCount());
540     }
541     if (Progress.GetStatus() != 100) Progress.SetStatus(100);
542     } catch(Exception e) {
543     Progress.SetErrorStatus(-1);
544     throw e;
545     }
546 iliev 1200 }
547    
548    
549     void DirectoryScanner::Scan(String DbDir, String FsDir, bool Flat, ScanProgress* pProgress) {
550     dmsg(2,("DirectoryScanner: Scan(DbDir=%s,FsDir=%s,Flat=%d)\n", DbDir.c_str(), FsDir.c_str(), Flat));
551     if (DbDir.empty() || FsDir.empty()) throw Exception("Directory expected");
552    
553 iliev 1717 this->DbDir = DbDir;
554     this->FsDir = FsDir;
555 iliev 1200 if (DbDir.at(DbDir.length() - 1) != '/') {
556 iliev 1717 this->DbDir.append("/");
557 iliev 1200 }
558 iliev 1717 if (FsDir.at(FsDir.length() - 1) != File::DirSeparator) {
559     this->FsDir.push_back(File::DirSeparator);
560 iliev 1200 }
561 iliev 1717 this->Flat = Flat;
562     this->pProgress = pProgress;
563 iliev 1200
564 iliev 1717 File::WalkDirectoryTree(FsDir, this);
565 iliev 1200 }
566    
567 iliev 1717 void DirectoryScanner::DirectoryEntry(std::string Path) {
568     dmsg(2,("DirectoryScanner: DirectoryEntry(Path=%s)\n", Path.c_str()));
569 iliev 1200
570     String dir = DbDir;
571     if (!Flat) {
572 iliev 1717 String subdir = Path;
573 iliev 1200 if(subdir.length() > FsDir.length()) {
574     subdir = subdir.substr(FsDir.length());
575     dir += subdir;
576     }
577     }
578    
579     InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
580    
581 iliev 1717 if (HasInstrumentFiles(Path)) {
582 iliev 1208 if (!db->DirectoryExist(dir)) db->AddDirectory(dir);
583 iliev 1717 db->AddInstrumentsNonrecursive(dir, Path, pProgress);
584 iliev 1208 }
585 iliev 1200 };
586    
587 iliev 1208 bool DirectoryScanner::HasInstrumentFiles(String Dir) {
588 iliev 1717 InstrumentFileCounter c;
589     return c.Count(Dir) > 0;
590 iliev 1208 }
591    
592 iliev 1200 int InstrumentFileCounter::Count(String FsDir) {
593     dmsg(2,("InstrumentFileCounter: Count(FsDir=%s)\n", FsDir.c_str()));
594     if (FsDir.empty()) throw Exception("Directory expected");
595     FileCount = 0;
596    
597 iliev 1717 File::WalkDirectoryTree(FsDir, this);
598 iliev 1200 return FileCount;
599     }
600    
601 iliev 1717 void InstrumentFileCounter::FileEntry(std::string Path) {
602     if(Path.length() < 4) return;
603     if(!strcasecmp(".gig", Path.substr(Path.length() - 4).c_str())) FileCount++;
604 iliev 1200 };
605    
606     } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC