1 |
/*************************************************************************** |
/*************************************************************************** |
2 |
* * |
* * |
3 |
* Copyright (C) 2007 Grigor Iliev * |
* Copyright (C) 2007 - 2009 Grigor Iliev * |
4 |
* * |
* * |
5 |
* This program is free software; you can redistribute it and/or modify * |
* 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 * |
* it under the terms of the GNU General Public License as published by * |
20 |
|
|
21 |
#include "InstrumentsDbUtilities.h" |
#include "InstrumentsDbUtilities.h" |
22 |
|
|
23 |
#if HAVE_SQLITE3 |
#include "../common/File.h" |
24 |
|
#include "../common/global_private.h" |
25 |
|
|
26 |
#include <dirent.h> |
#include <algorithm> |
27 |
#include <errno.h> |
#include <errno.h> |
|
#include <ftw.h> |
|
28 |
|
|
29 |
#include "../common/Exception.h" |
#include "../common/Exception.h" |
30 |
#include "InstrumentsDb.h" |
#include "InstrumentsDb.h" |
153 |
if (Pattern.length() == 0) return; |
if (Pattern.length() == 0) return; |
154 |
|
|
155 |
if (IsRegex(Pattern)) { |
if (IsRegex(Pattern)) { |
156 |
|
#ifndef WIN32 |
157 |
Sql << " AND " << Col << " regexp ?"; |
Sql << " AND " << Col << " regexp ?"; |
158 |
|
#else |
159 |
|
for (int i = 0; i < Pattern.length(); i++) { |
160 |
|
if (Pattern.at(i) == '?') Pattern.at(i) = '_'; |
161 |
|
else if (Pattern.at(i) == '*') Pattern.at(i) = '%'; |
162 |
|
} |
163 |
|
Sql << " AND " << Col << " LIKE ?"; |
164 |
|
#endif |
165 |
Params.push_back(Pattern); |
Params.push_back(Pattern); |
166 |
return; |
return; |
167 |
} |
} |
262 |
if(Path.compare("/") != 0) s += "/"; |
if(Path.compare("/") != 0) s += "/"; |
263 |
int res = sqlite3_step(pStmt); |
int res = sqlite3_step(pStmt); |
264 |
while(res == SQLITE_ROW) { |
while(res == SQLITE_ROW) { |
265 |
pDirectories->push_back(s + ToString(sqlite3_column_text(pStmt, 0))); |
pDirectories->push_back(s + idb->toAbstractName(ToString(sqlite3_column_text(pStmt, 0)))); |
266 |
res = sqlite3_step(pStmt); |
res = sqlite3_step(pStmt); |
267 |
} |
} |
268 |
|
|
347 |
if(Path.compare("/") != 0) s += "/"; |
if(Path.compare("/") != 0) s += "/"; |
348 |
int res = sqlite3_step(pStmt); |
int res = sqlite3_step(pStmt); |
349 |
while(res == SQLITE_ROW) { |
while(res == SQLITE_ROW) { |
350 |
pInstruments->push_back(s + ToString(sqlite3_column_text(pStmt, 0))); |
pInstruments->push_back(s + idb->toAbstractName(ToString(sqlite3_column_text(pStmt, 0)))); |
351 |
res = sqlite3_step(pStmt); |
res = sqlite3_step(pStmt); |
352 |
} |
} |
353 |
|
|
399 |
} |
} |
400 |
|
|
401 |
int dstDirId = db->GetDirectoryId(dir); |
int dstDirId = db->GetDirectoryId(dir); |
402 |
if(dstDirId == -1) throw Exception("Unkown DB directory: " + dir); |
if(dstDirId == -1) { |
403 |
|
throw Exception("Unkown DB directory: " + InstrumentsDb::toEscapedPath(dir)); |
404 |
|
} |
405 |
IntListPtr ids = db->GetInstrumentIDs(DirId); |
IntListPtr ids = db->GetInstrumentIDs(DirId); |
406 |
for (int i = 0; i < ids->size(); i++) { |
for (int i = 0; i < ids->size(); i++) { |
407 |
String name = db->GetInstrumentName(ids->at(i)); |
String name = db->GetInstrumentName(ids->at(i)); |
472 |
sp->SetStatus((int)(pProgress->factor * 100)); |
sp->SetStatus((int)(pProgress->factor * 100)); |
473 |
} |
} |
474 |
|
|
475 |
AddInstrumentsJob::AddInstrumentsJob(int JobId, ScanMode Mode, String DbDir, String FsDir) { |
AddInstrumentsJob::AddInstrumentsJob(int JobId, ScanMode Mode, String DbDir, String FsDir, bool insDir) { |
476 |
this->JobId = JobId; |
this->JobId = JobId; |
477 |
Progress.JobId = JobId; |
Progress.JobId = JobId; |
478 |
this->Mode = Mode; |
this->Mode = Mode; |
479 |
this->DbDir = DbDir; |
this->DbDir = DbDir; |
480 |
this->FsDir = FsDir; |
this->FsDir = FsDir; |
481 |
|
this->insDir = insDir; |
482 |
} |
} |
483 |
|
|
484 |
void AddInstrumentsJob::Run() { |
void AddInstrumentsJob::Run() { |
488 |
switch (Mode) { |
switch (Mode) { |
489 |
case NON_RECURSIVE: |
case NON_RECURSIVE: |
490 |
Progress.SetTotalFileCount(GetFileCount()); |
Progress.SetTotalFileCount(GetFileCount()); |
491 |
db->AddInstrumentsNonrecursive(DbDir, FsDir, &Progress); |
db->AddInstrumentsNonrecursive(DbDir, FsDir, insDir, &Progress); |
492 |
break; |
break; |
493 |
case RECURSIVE: |
case RECURSIVE: |
494 |
db->AddInstrumentsRecursive(DbDir, FsDir, false, &Progress); |
db->AddInstrumentsRecursive(DbDir, FsDir, false, insDir, &Progress); |
495 |
break; |
break; |
496 |
case FLAT: |
case FLAT: |
497 |
db->AddInstrumentsRecursive(DbDir, FsDir, true, &Progress); |
db->AddInstrumentsRecursive(DbDir, FsDir, true, insDir, &Progress); |
498 |
break; |
break; |
499 |
default: |
default: |
500 |
throw Exception("Unknown scan mode"); |
throw Exception("Unknown scan mode"); |
501 |
} |
} |
502 |
|
|
503 |
|
// Just to be sure that the frontends will be notified about the job completion |
504 |
|
if (Progress.GetTotalFileCount() != Progress.GetScannedFileCount()) { |
505 |
|
Progress.SetTotalFileCount(Progress.GetScannedFileCount()); |
506 |
|
} |
507 |
|
if (Progress.GetStatus() != 100) Progress.SetStatus(100); |
508 |
} catch(Exception e) { |
} catch(Exception e) { |
509 |
Progress.SetErrorStatus(-1); |
Progress.SetErrorStatus(-1); |
510 |
throw e; |
throw e; |
514 |
int AddInstrumentsJob::GetFileCount() { |
int AddInstrumentsJob::GetFileCount() { |
515 |
int count = 0; |
int count = 0; |
516 |
|
|
517 |
DIR* pDir = opendir(FsDir.c_str()); |
try { |
518 |
if (pDir == NULL) { |
FileListPtr fileList = File::GetFiles(FsDir); |
|
std::stringstream ss; |
|
|
ss << "The scanning of directory `" << FsDir << "` failed: "; |
|
|
ss << strerror(errno); |
|
|
std::cerr << ss.str(); |
|
|
return 0; |
|
|
} |
|
519 |
|
|
520 |
struct dirent* pEnt = readdir(pDir); |
for (int i = 0; i < fileList->size(); i++) { |
521 |
while (pEnt != NULL) { |
String s = fileList->at(i); |
522 |
if (pEnt->d_type != DT_REG) { |
if (s.length() < 4) continue; |
523 |
pEnt = readdir(pDir); |
if(!strcasecmp(".gig", s.substr(s.length() - 4).c_str())) count++; |
|
continue; |
|
524 |
} |
} |
525 |
|
} catch(Exception e) { |
526 |
count++; |
e.PrintMessage(); |
527 |
pEnt = readdir(pDir); |
return 0; |
|
} |
|
|
|
|
|
if (closedir(pDir)) { |
|
|
std::stringstream ss; |
|
|
ss << "Failed to close directory `" << FsDir << "`: "; |
|
|
ss << strerror(errno); |
|
|
std::cerr << ss.str(); |
|
528 |
} |
} |
529 |
|
|
530 |
return count; |
return count; |
531 |
} |
} |
532 |
|
|
533 |
AddInstrumentsFromFileJob::AddInstrumentsFromFileJob(int JobId, String DbDir, String FilePath, int Index) { |
AddInstrumentsFromFileJob::AddInstrumentsFromFileJob(int JobId, String DbDir, String FilePath, int Index, bool insDir) { |
534 |
this->JobId = JobId; |
this->JobId = JobId; |
535 |
Progress.JobId = JobId; |
Progress.JobId = JobId; |
536 |
Progress.SetTotalFileCount(1); |
Progress.SetTotalFileCount(1); |
538 |
this->DbDir = DbDir; |
this->DbDir = DbDir; |
539 |
this->FilePath = FilePath; |
this->FilePath = FilePath; |
540 |
this->Index = Index; |
this->Index = Index; |
541 |
|
this->insDir = insDir; |
542 |
} |
} |
543 |
|
|
544 |
void AddInstrumentsFromFileJob::Run() { |
void AddInstrumentsFromFileJob::Run() { |
545 |
InstrumentsDb::GetInstrumentsDb()->AddInstruments(DbDir, FilePath, Index, &Progress); |
try { |
546 |
} |
InstrumentsDb::GetInstrumentsDb()->AddInstruments(DbDir, insDir, FilePath, Index, &Progress); |
547 |
|
|
548 |
|
// Just to be sure that the frontends will be notified about the job completion |
549 |
|
if (Progress.GetTotalFileCount() != Progress.GetScannedFileCount()) { |
550 |
|
Progress.SetTotalFileCount(Progress.GetScannedFileCount()); |
551 |
|
} |
552 |
|
if (Progress.GetStatus() != 100) Progress.SetStatus(100); |
553 |
|
} catch(Exception e) { |
554 |
|
Progress.SetErrorStatus(-1); |
555 |
|
throw e; |
556 |
|
} |
557 |
|
} |
558 |
|
|
|
String DirectoryScanner::DbDir; |
|
|
String DirectoryScanner::FsDir; |
|
|
bool DirectoryScanner::Flat; |
|
|
ScanProgress* DirectoryScanner::pProgress; |
|
559 |
|
|
560 |
void DirectoryScanner::Scan(String DbDir, String FsDir, bool Flat, ScanProgress* pProgress) { |
void DirectoryScanner::Scan(String DbDir, String FsDir, bool Flat, bool insDir, ScanProgress* pProgress) { |
561 |
dmsg(2,("DirectoryScanner: Scan(DbDir=%s,FsDir=%s,Flat=%d)\n", DbDir.c_str(), FsDir.c_str(), Flat)); |
dmsg(2,("DirectoryScanner: Scan(DbDir=%s,FsDir=%s,Flat=%d,insDir=%d)\n", DbDir.c_str(), FsDir.c_str(), Flat, insDir)); |
562 |
if (DbDir.empty() || FsDir.empty()) throw Exception("Directory expected"); |
if (DbDir.empty() || FsDir.empty()) throw Exception("Directory expected"); |
563 |
|
|
564 |
struct stat statBuf; |
this->DbDir = DbDir; |
565 |
int res = stat(FsDir.c_str(), &statBuf); |
this->FsDir = FsDir; |
566 |
if (res) { |
this->insDir = insDir; |
|
std::stringstream ss; |
|
|
ss << "Fail to stat `" << FsDir << "`: " << strerror(errno); |
|
|
throw Exception(ss.str()); |
|
|
} |
|
|
|
|
|
if (!S_ISDIR(statBuf.st_mode)) { |
|
|
throw Exception("Directory expected"); |
|
|
} |
|
|
|
|
|
DirectoryScanner::DbDir = DbDir; |
|
|
DirectoryScanner::FsDir = FsDir; |
|
567 |
if (DbDir.at(DbDir.length() - 1) != '/') { |
if (DbDir.at(DbDir.length() - 1) != '/') { |
568 |
DirectoryScanner::DbDir.append("/"); |
this->DbDir.append("/"); |
569 |
} |
} |
570 |
if (FsDir.at(FsDir.length() - 1) != '/') { |
if (FsDir.at(FsDir.length() - 1) != File::DirSeparator) { |
571 |
DirectoryScanner::FsDir.append("/"); |
this->FsDir.push_back(File::DirSeparator); |
572 |
} |
} |
573 |
DirectoryScanner::Flat = Flat; |
this->Flat = Flat; |
574 |
DirectoryScanner::pProgress = pProgress; |
this->pProgress = pProgress; |
575 |
|
|
576 |
ftw(FsDir.c_str(), FtwCallback, 10); |
File::WalkDirectoryTree(FsDir, this); |
577 |
} |
} |
578 |
|
|
579 |
int DirectoryScanner::FtwCallback(const char* fpath, const struct stat* sb, int typeflag) { |
void DirectoryScanner::DirectoryEntry(std::string Path) { |
580 |
dmsg(2,("DirectoryScanner: FtwCallback(fpath=%s)\n", fpath)); |
dmsg(2,("DirectoryScanner: DirectoryEntry(Path=%s)\n", Path.c_str())); |
|
if (typeflag != FTW_D) return 0; |
|
581 |
|
|
582 |
String dir = DbDir; |
String dir = DbDir; |
583 |
if (!Flat) { |
if (!Flat) { |
584 |
String subdir = fpath; |
String subdir = Path; |
585 |
if(subdir.length() > FsDir.length()) { |
if(subdir.length() > FsDir.length()) { |
586 |
subdir = subdir.substr(FsDir.length()); |
subdir = subdir.substr(FsDir.length()); |
587 |
|
#ifdef WIN32 |
588 |
|
replace(subdir.begin(), subdir.end(), '\\', '/'); |
589 |
|
#endif |
590 |
dir += subdir; |
dir += subdir; |
591 |
} |
} |
592 |
} |
} |
593 |
|
|
594 |
InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb(); |
InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb(); |
|
if (!db->DirectoryExist(dir)) db->AddDirectory(dir); |
|
595 |
|
|
596 |
db->AddInstrumentsNonrecursive(dir, String(fpath), pProgress); |
if (HasInstrumentFiles(Path)) { |
597 |
|
if (!db->DirectoryExist(dir)) db->AddDirectory(dir); |
598 |
return 0; |
db->AddInstrumentsNonrecursive(dir, Path, insDir, pProgress); |
599 |
|
} |
600 |
}; |
}; |
601 |
|
|
602 |
int InstrumentFileCounter::FileCount; |
bool DirectoryScanner::HasInstrumentFiles(String Dir) { |
603 |
|
InstrumentFileCounter c; |
604 |
|
return c.Count(Dir) > 0; |
605 |
|
} |
606 |
|
|
607 |
int InstrumentFileCounter::Count(String FsDir) { |
int InstrumentFileCounter::Count(String FsDir) { |
608 |
dmsg(2,("InstrumentFileCounter: Count(FsDir=%s)\n", FsDir.c_str())); |
dmsg(2,("InstrumentFileCounter: Count(FsDir=%s)\n", FsDir.c_str())); |
609 |
if (FsDir.empty()) throw Exception("Directory expected"); |
if (FsDir.empty()) throw Exception("Directory expected"); |
610 |
FileCount = 0; |
FileCount = 0; |
611 |
|
|
612 |
struct stat statBuf; |
File::WalkDirectoryTree(FsDir, this); |
|
int res = stat(FsDir.c_str(), &statBuf); |
|
|
if (res) { |
|
|
std::stringstream ss; |
|
|
ss << "Fail to stat `" << FsDir << "`: " << strerror(errno); |
|
|
throw Exception(ss.str()); |
|
|
} |
|
|
|
|
|
if (!S_ISDIR(statBuf.st_mode)) { |
|
|
throw Exception("Directory expected"); |
|
|
} |
|
|
|
|
|
ftw(FsDir.c_str(), FtwCallback, 10); |
|
613 |
return FileCount; |
return FileCount; |
614 |
} |
} |
615 |
|
|
616 |
int InstrumentFileCounter::FtwCallback(const char* fpath, const struct stat* sb, int typeflag) { |
void InstrumentFileCounter::FileEntry(std::string Path) { |
617 |
if (typeflag != FTW_F) return 0; |
dmsg(2,("InstrumentFileCounter: FileEntry(Path=%s)\n", Path.c_str())); |
618 |
String s = fpath; |
if(Path.length() < 4) return; |
619 |
if(s.length() < 4) return 0; |
if(!strcasecmp(".gig", Path.substr(Path.length() - 4).c_str())) FileCount++; |
|
if(!strcasecmp(".gig", s.substr(s.length() - 4).c_str())) FileCount++; |
|
|
return 0; |
|
620 |
}; |
}; |
621 |
|
|
622 |
} // namespace LinuxSampler |
} // namespace LinuxSampler |
|
|
|
|
#endif // HAVE_SQLITE3 |
|