20 |
|
|
21 |
#include "InstrumentsDb.h" |
#include "InstrumentsDb.h" |
22 |
|
|
23 |
|
#include "../common/File.h" |
24 |
#include "../common/global_private.h" |
#include "../common/global_private.h" |
25 |
|
|
26 |
#include <iostream> |
#include <iostream> |
27 |
#include <sstream> |
#include <sstream> |
28 |
#include <vector> |
#include <vector> |
|
#include <dirent.h> |
|
29 |
#include <errno.h> |
#include <errno.h> |
30 |
#include <fnmatch.h> |
#include <fnmatch.h> |
31 |
|
|
35 |
|
|
36 |
InstrumentsDb InstrumentsDb::instance; |
InstrumentsDb InstrumentsDb::instance; |
37 |
|
|
38 |
void InstrumentsDb::CreateInstrumentsDb(String File) { |
void InstrumentsDb::CreateInstrumentsDb(String FilePath) { |
39 |
struct stat statBuf; |
File f = File(FilePath); |
40 |
int res = stat(File.c_str(), &statBuf); |
if (f.Exist()) { |
41 |
if (!res) { |
throw Exception("File exists: " + FilePath); |
|
throw Exception("File exists: " + File); |
|
42 |
} |
} |
43 |
|
|
44 |
GetInstrumentsDb()->SetDbFile(File); |
GetInstrumentsDb()->SetDbFile(FilePath); |
45 |
|
|
46 |
String sql = |
String sql = |
47 |
" CREATE TABLE instr_dirs ( " |
" CREATE TABLE instr_dirs ( " |
660 |
int dirId = GetDirectoryId(DbDir); |
int dirId = GetDirectoryId(DbDir); |
661 |
if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedText(DbDir)); |
if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedText(DbDir)); |
662 |
|
|
663 |
struct stat statBuf; |
File f = File(FilePath); |
664 |
int res = stat(FilePath.c_str(), &statBuf); |
if (!f.Exist()) { |
|
if (res) { |
|
665 |
std::stringstream ss; |
std::stringstream ss; |
666 |
ss << "Fail to stat `" << FilePath << "`: " << strerror(errno); |
ss << "Fail to stat `" << FilePath << "`: " << f.GetErrorMsg(); |
667 |
throw Exception(ss.str()); |
throw Exception(ss.str()); |
668 |
} |
} |
669 |
|
|
670 |
if (!S_ISREG(statBuf.st_mode)) { |
if (!f.IsFile()) { |
671 |
std::stringstream ss; |
std::stringstream ss; |
672 |
ss << "`" << FilePath << "` is not an instrument file"; |
ss << "`" << FilePath << "` is not an instrument file"; |
673 |
throw Exception(ss.str()); |
throw Exception(ss.str()); |
691 |
int dirId = GetDirectoryId(DbDir); |
int dirId = GetDirectoryId(DbDir); |
692 |
if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedPath(DbDir)); |
if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedPath(DbDir)); |
693 |
|
|
694 |
struct stat statBuf; |
File f = File(FsDir); |
695 |
int res = stat(FsDir.c_str(), &statBuf); |
if (!f.Exist()) { |
|
if (res) { |
|
696 |
std::stringstream ss; |
std::stringstream ss; |
697 |
ss << "Fail to stat `" << FsDir << "`: " << strerror(errno); |
ss << "Fail to stat `" << FsDir << "`: " << f.GetErrorMsg(); |
698 |
throw Exception(ss.str()); |
throw Exception(ss.str()); |
699 |
} |
} |
700 |
|
|
701 |
if (!S_ISDIR(statBuf.st_mode)) { |
if (!f.IsDirectory()) { |
702 |
throw Exception("Directory expected"); |
throw Exception("Directory expected: " + FsDir); |
703 |
} |
} |
704 |
|
|
705 |
if (FsDir.at(FsDir.length() - 1) != '/') FsDir.append("/"); |
if (FsDir.at(FsDir.length() - 1) != File::DirSeparator) { |
706 |
|
FsDir.push_back(File::DirSeparator); |
|
DIR* pDir = opendir(FsDir.c_str()); |
|
|
if (pDir == NULL) { |
|
|
std::stringstream ss; |
|
|
ss << "The scanning of directory `" << FsDir << "` failed: "; |
|
|
ss << strerror(errno); |
|
|
std::cerr << ss.str(); |
|
|
DbInstrumentsMutex.Unlock(); |
|
|
return; |
|
707 |
} |
} |
708 |
|
|
709 |
struct dirent* pEnt = readdir(pDir); |
try { |
710 |
while (pEnt != NULL) { |
FileListPtr fileList = File::GetFiles(FsDir); |
711 |
if (pEnt->d_type != DT_REG) { |
for (int i = 0; i < fileList->size(); i++) { |
712 |
pEnt = readdir(pDir); |
AddInstrumentsFromFile(DbDir, FsDir + fileList->at(i), -1, pProgress); |
|
continue; |
|
713 |
} |
} |
714 |
|
} catch(Exception e) { |
715 |
AddInstrumentsFromFile(DbDir, FsDir + String(pEnt->d_name), -1, pProgress); |
e.PrintMessage(); |
716 |
pEnt = readdir(pDir); |
DbInstrumentsMutex.Unlock(); |
717 |
} |
return; |
|
|
|
|
if (closedir(pDir)) { |
|
|
std::stringstream ss; |
|
|
ss << "Failed to close directory `" << FsDir << "`: "; |
|
|
ss << strerror(errno); |
|
|
std::cerr << ss.str(); |
|
718 |
} |
} |
719 |
} catch (Exception e) { |
} catch (Exception e) { |
720 |
DbInstrumentsMutex.Unlock(); |
DbInstrumentsMutex.Unlock(); |
727 |
void InstrumentsDb::AddInstrumentsRecursive(String DbDir, String FsDir, bool Flat, ScanProgress* pProgress) { |
void InstrumentsDb::AddInstrumentsRecursive(String DbDir, String FsDir, bool Flat, ScanProgress* pProgress) { |
728 |
dmsg(2,("InstrumentsDb: AddInstrumentsRecursive(DbDir=%s,FsDir=%s,Flat=%d)\n", DbDir.c_str(), FsDir.c_str(), Flat)); |
dmsg(2,("InstrumentsDb: AddInstrumentsRecursive(DbDir=%s,FsDir=%s,Flat=%d)\n", DbDir.c_str(), FsDir.c_str(), Flat)); |
729 |
if (pProgress != NULL) { |
if (pProgress != NULL) { |
730 |
pProgress->SetTotalFileCount(InstrumentFileCounter::Count(FsDir)); |
InstrumentFileCounter c; |
731 |
|
pProgress->SetTotalFileCount(c.Count(FsDir)); |
732 |
} |
} |
733 |
|
|
734 |
DirectoryScanner::Scan(DbDir, FsDir, Flat, pProgress); |
DirectoryScanner d; |
735 |
|
d.Scan(DbDir, FsDir, Flat, pProgress); |
736 |
} |
} |
737 |
|
|
738 |
int InstrumentsDb::GetInstrumentCount(int DirId) { |
int InstrumentsDb::GetInstrumentCount(int DirId) { |
1121 |
} |
} |
1122 |
} |
} |
1123 |
} catch(Exception e) { |
} catch(Exception e) { |
1124 |
std::cerr << e.Message() << std::endl; |
e.PrintMessage(); |
1125 |
} |
} |
1126 |
} |
} |
1127 |
|
|
1128 |
void InstrumentsDb::AddGigInstruments(String DbDir, String File, int Index, ScanProgress* pProgress) { |
void InstrumentsDb::AddGigInstruments(String DbDir, String FilePath, int Index, ScanProgress* pProgress) { |
1129 |
dmsg(2,("InstrumentsDb: AddGigInstruments(DbDir=%s,File=%s,Index=%d)\n", DbDir.c_str(), File.c_str(), Index)); |
dmsg(2,("InstrumentsDb: AddGigInstruments(DbDir=%s,FilePath=%s,Index=%d)\n", DbDir.c_str(), FilePath.c_str(), Index)); |
1130 |
int dirId = GetDirectoryId(DbDir); |
int dirId = GetDirectoryId(DbDir); |
1131 |
if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedPath(DbDir)); |
if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedPath(DbDir)); |
1132 |
|
|
1133 |
struct stat statBuf; |
File f = File(FilePath); |
1134 |
int res = stat(File.c_str(), &statBuf); |
if (!f.Exist()) { |
|
if (res) { |
|
1135 |
std::stringstream ss; |
std::stringstream ss; |
1136 |
ss << "Fail to stat `" << File << "`: " << strerror(errno); |
ss << "Fail to stat `" << FilePath << "`: " << f.GetErrorMsg(); |
1137 |
throw Exception(ss.str()); |
throw Exception(ss.str()); |
1138 |
} |
} |
1139 |
|
|
1140 |
if (!S_ISREG(statBuf.st_mode)) { |
if (!f.IsFile()) { |
1141 |
std::stringstream ss; |
std::stringstream ss; |
1142 |
ss << "`" << File << "` is not a regular file"; |
ss << "`" << FilePath << "` is not a regular file"; |
1143 |
throw Exception(ss.str()); |
throw Exception(ss.str()); |
1144 |
} |
} |
1145 |
|
|
1146 |
RIFF::File* riff = NULL; |
RIFF::File* riff = NULL; |
1147 |
gig::File* gig = NULL; |
gig::File* gig = NULL; |
1148 |
try { |
try { |
1149 |
riff = new RIFF::File(File); |
riff = new RIFF::File(FilePath); |
1150 |
gig::File* gig = new gig::File(riff); |
gig::File* gig = new gig::File(riff); |
1151 |
gig->SetAutoLoad(false); // avoid time consuming samples scanning |
gig->SetAutoLoad(false); // avoid time consuming samples scanning |
1152 |
|
|
1154 |
sql << "INSERT INTO instruments (dir_id,instr_name,instr_file,"; |
sql << "INSERT INTO instruments (dir_id,instr_name,instr_file,"; |
1155 |
sql << "instr_nr,format_family,format_version,instr_size,"; |
sql << "instr_nr,format_family,format_version,instr_size,"; |
1156 |
sql << "description,is_drum,product,artists,keywords) VALUES ("; |
sql << "description,is_drum,product,artists,keywords) VALUES ("; |
1157 |
sql << dirId << ",?,?,?,'GIG',?," << statBuf.st_size << ",?,?,?,?,?)"; |
sql << dirId << ",?,?,?,'GIG',?," << f.GetSize() << ",?,?,?,?,?)"; |
1158 |
|
|
1159 |
sqlite3_stmt* pStmt = NULL; |
sqlite3_stmt* pStmt = NULL; |
1160 |
|
|
1163 |
throw Exception("DB error: " + ToString(sqlite3_errmsg(db))); |
throw Exception("DB error: " + ToString(sqlite3_errmsg(db))); |
1164 |
} |
} |
1165 |
|
|
1166 |
String s = toEscapedFsPath(File); |
String s = toEscapedFsPath(FilePath); |
1167 |
BindTextParam(pStmt, 2, s); |
BindTextParam(pStmt, 2, s); |
1168 |
String ver = ""; |
String ver = ""; |
1169 |
if (gig->pVersion != NULL) ver = ToString(gig->pVersion->major); |
if (gig->pVersion != NULL) ver = ToString(gig->pVersion->major); |
1177 |
BindTextParam(pStmt, 7, gig->pInfo->Product); |
BindTextParam(pStmt, 7, gig->pInfo->Product); |
1178 |
BindTextParam(pStmt, 8, gig->pInfo->Artists); |
BindTextParam(pStmt, 8, gig->pInfo->Artists); |
1179 |
BindTextParam(pStmt, 9, gig->pInfo->Keywords); |
BindTextParam(pStmt, 9, gig->pInfo->Keywords); |
1180 |
AddGigInstrument(pStmt, DbDir, dirId, File, pInstrument, instrIndex); |
AddGigInstrument(pStmt, DbDir, dirId, FilePath, pInstrument, instrIndex); |
1181 |
|
|
1182 |
instrIndex++; |
instrIndex++; |
1183 |
pInstrument = gig->GetNextInstrument(); |
pInstrument = gig->GetNextInstrument(); |
1190 |
BindTextParam(pStmt, 7, gig->pInfo->Product); |
BindTextParam(pStmt, 7, gig->pInfo->Product); |
1191 |
BindTextParam(pStmt, 8, gig->pInfo->Artists); |
BindTextParam(pStmt, 8, gig->pInfo->Artists); |
1192 |
BindTextParam(pStmt, 9, gig->pInfo->Keywords); |
BindTextParam(pStmt, 9, gig->pInfo->Keywords); |
1193 |
AddGigInstrument(pStmt, DbDir, dirId, File, pInstrument, Index); |
AddGigInstrument(pStmt, DbDir, dirId, FilePath, pInstrument, Index); |
1194 |
} |
} |
1195 |
} |
} |
1196 |
|
|
1201 |
if (gig != NULL) delete gig; |
if (gig != NULL) delete gig; |
1202 |
if (riff != NULL) delete riff; |
if (riff != NULL) delete riff; |
1203 |
std::stringstream ss; |
std::stringstream ss; |
1204 |
ss << "Failed to scan `" << File << "`: " << e.Message; |
ss << "Failed to scan `" << FilePath << "`: " << e.Message; |
1205 |
|
|
1206 |
throw Exception(ss.str()); |
throw Exception(ss.str()); |
1207 |
} catch (Exception e) { |
} catch (Exception e) { |
1211 |
} catch (...) { |
} catch (...) { |
1212 |
if (gig != NULL) delete gig; |
if (gig != NULL) delete gig; |
1213 |
if (riff != NULL) delete riff; |
if (riff != NULL) delete riff; |
1214 |
throw Exception("Failed to scan `" + File + "`"); |
throw Exception("Failed to scan `" + FilePath + "`"); |
1215 |
} |
} |
1216 |
} |
} |
1217 |
|
|
1218 |
void InstrumentsDb::AddGigInstrument(sqlite3_stmt* pStmt, String DbDir, int DirId, String File, gig::Instrument* pInstrument, int Index) { |
void InstrumentsDb::AddGigInstrument(sqlite3_stmt* pStmt, String DbDir, int DirId, String File, gig::Instrument* pInstrument, int Index) { |
1219 |
|
dmsg(2,("InstrumentsDb: AddGigInstrument(DbDir=%s,DirId=%d,File=%s,Index=%d)\n", DbDir.c_str(), DirId, File.c_str(), Index)); |
1220 |
String name = pInstrument->pInfo->Name; |
String name = pInstrument->pInfo->Name; |
1221 |
if (name == "") return; |
if (name == "") return; |
1222 |
name = GetUniqueInstrumentName(DirId, name); |
name = GetUniqueInstrumentName(DirId, name); |