1191 |
FireInstrumentInfoChanged(Instr); |
FireInstrumentInfoChanged(Instr); |
1192 |
} |
} |
1193 |
|
|
1194 |
void InstrumentsDb::AddInstrumentsFromFile(String DbDir, String File, int Index, ScanProgress* pProgress) { |
void InstrumentsDb::AddInstrumentsFromFile(String DbDir, String file, int Index, ScanProgress* pProgress) { |
1195 |
dmsg(2,("InstrumentsDb: AddInstrumentsFromFile(DbDir=%s,File=%s,Index=%d)\n", DbDir.c_str(), File.c_str(), Index)); |
dmsg(2,("InstrumentsDb: AddInstrumentsFromFile(DbDir=%s,File=%s,Index=%d)\n", DbDir.c_str(), file.c_str(), Index)); |
1196 |
|
|
1197 |
if(File.length() < 4) return; |
if (!InstrumentFileInfo::isSupportedFile(file)) return; |
1198 |
|
|
1199 |
try { |
try { |
1200 |
if(!strcasecmp(".gig", File.substr(File.length() - 4).c_str())) { |
if (pProgress != NULL) { |
1201 |
if (pProgress != NULL) { |
pProgress->SetStatus(0); |
1202 |
pProgress->SetStatus(0); |
pProgress->CurrentFile = file; |
1203 |
pProgress->CurrentFile = File; |
} |
|
} |
|
1204 |
|
|
1205 |
AddGigInstruments(DbDir, File, Index, pProgress); |
int dirId = GetDirectoryId(DbDir); |
1206 |
|
if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedPath(DbDir)); |
1207 |
|
|
1208 |
if (pProgress != NULL) { |
File f = File(file); |
1209 |
pProgress->SetScannedFileCount(pProgress->GetScannedFileCount() + 1); |
if (!f.Exist()) { |
1210 |
} |
std::stringstream ss; |
1211 |
|
ss << "Fail to stat `" << file << "`: " << f.GetErrorMsg(); |
1212 |
|
throw Exception(ss.str()); |
1213 |
|
} |
1214 |
|
|
1215 |
|
if (!f.IsFile()) { |
1216 |
|
std::stringstream ss; |
1217 |
|
ss << "`" << file << "` is not a regular file"; |
1218 |
|
throw Exception(ss.str()); |
1219 |
|
} |
1220 |
|
|
1221 |
|
AddInstrumentsFromFilePriv(DbDir, dirId, file, f, Index, pProgress); |
1222 |
|
|
1223 |
|
if (pProgress != NULL) { |
1224 |
|
pProgress->SetScannedFileCount(pProgress->GetScannedFileCount() + 1); |
1225 |
} |
} |
1226 |
} catch(Exception e) { |
} catch(Exception e) { |
1227 |
e.PrintMessage(); |
e.PrintMessage(); |
1228 |
} |
} |
1229 |
} |
} |
1230 |
|
|
1231 |
void InstrumentsDb::AddGigInstruments(String DbDir, String FilePath, int Index, ScanProgress* pProgress) { |
void InstrumentsDb::AddInstrumentsFromFilePriv(String DbDir, const int dirId, String FilePath, File file, int Index, ScanProgress* pProgress) { |
1232 |
dmsg(2,("InstrumentsDb: AddGigInstruments(DbDir=%s,FilePath=%s,Index=%d)\n", DbDir.c_str(), FilePath.c_str(), Index)); |
dmsg(2,("InstrumentsDb: AddGigInstruments(DbDir=%s,FilePath=%s,Index=%d)\n", DbDir.c_str(), FilePath.c_str(), Index)); |
|
int dirId = GetDirectoryId(DbDir); |
|
|
if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedPath(DbDir)); |
|
|
|
|
|
File f = File(FilePath); |
|
|
if (!f.Exist()) { |
|
|
std::stringstream ss; |
|
|
ss << "Fail to stat `" << FilePath << "`: " << f.GetErrorMsg(); |
|
|
throw Exception(ss.str()); |
|
|
} |
|
|
|
|
|
if (!f.IsFile()) { |
|
|
std::stringstream ss; |
|
|
ss << "`" << FilePath << "` is not a regular file"; |
|
|
throw Exception(ss.str()); |
|
|
} |
|
1233 |
|
|
1234 |
bool unlocked = false; |
bool unlocked = false; |
1235 |
RIFF::File* riff = NULL; |
InstrumentFileInfo* fileInfo = NULL; |
1236 |
gig::File* gig = NULL; |
sqlite3_stmt* pStmt = NULL; |
1237 |
try { |
try { |
1238 |
riff = new RIFF::File(FilePath); |
fileInfo = InstrumentFileInfo::getFileInfoFor(FilePath); |
1239 |
gig::File* gig = new gig::File(riff); |
if (!fileInfo) return; |
|
gig->SetAutoLoad(false); // avoid time consuming samples scanning |
|
1240 |
|
|
1241 |
std::stringstream sql; |
std::stringstream sql; |
1242 |
sql << "INSERT INTO instruments (dir_id,instr_name,instr_file,"; |
sql << "INSERT INTO instruments (dir_id,instr_name,instr_file,"; |
1243 |
sql << "instr_nr,format_family,format_version,instr_size,"; |
sql << "instr_nr,format_family,format_version,instr_size,"; |
1244 |
sql << "description,is_drum,product,artists,keywords) VALUES ("; |
sql << "description,is_drum,product,artists,keywords) VALUES ("; |
1245 |
sql << dirId << ",?,?,?,'GIG',?," << f.GetSize() << ",?,?,?,?,?)"; |
sql << dirId << ",?,?,?,?,?," << file.GetSize() << ",?,?,?,?,?)"; |
1246 |
|
|
1247 |
sqlite3_stmt* pStmt = NULL; |
// instr_name 1 |
1248 |
|
// instr_file 2 |
1249 |
|
// instr_nr 3 |
1250 |
|
// format_family 4 |
1251 |
|
// format_version 5 |
1252 |
|
// description 6 |
1253 |
|
// is_drum 7 |
1254 |
|
// product 8 |
1255 |
|
// artists 9 |
1256 |
|
// keywords 10 |
1257 |
|
|
1258 |
int res = sqlite3_prepare(GetDb(), sql.str().c_str(), -1, &pStmt, NULL); |
int res = sqlite3_prepare(GetDb(), sql.str().c_str(), -1, &pStmt, NULL); |
1259 |
if (res != SQLITE_OK) { |
if (res != SQLITE_OK) { |
1260 |
throw Exception("DB error: " + ToString(sqlite3_errmsg(db))); |
throw Exception("DB error: " + ToString(sqlite3_errmsg(db))); |
1261 |
} |
} |
1262 |
|
|
1263 |
String s = FilePath; |
BindTextParam(pStmt, 2, toEscapedFsPath(FilePath)); |
1264 |
s = toEscapedFsPath(s); |
BindTextParam(pStmt, 4, fileInfo->formatName()); |
1265 |
BindTextParam(pStmt, 2, s); |
BindTextParam(pStmt, 5, fileInfo->formatVersion()); |
1266 |
String ver = ""; |
|
1267 |
if (gig->pVersion != NULL) ver = ToString(gig->pVersion->major); |
int instrIndex = (Index == -1) ? 0 : Index; |
1268 |
BindTextParam(pStmt, 4, ver); |
|
1269 |
|
// Assume that it's locked and should be unlocked at this point |
1270 |
if (Index == -1) { |
// to be able to use the database from another threads |
1271 |
int instrIndex = 0; |
if (!InTransaction) { |
1272 |
// Assume that it's locked and should be unlocked at this point |
DbInstrumentsMutex.Unlock(); |
1273 |
// to be able to use the database from another threads |
unlocked = true; |
1274 |
if (!InTransaction) { |
} else { |
1275 |
DbInstrumentsMutex.Unlock(); |
std::cerr << "Shouldn't be in transaction when adding instruments." << std::endl; |
1276 |
unlocked = true; |
} |
|
} else { |
|
|
std::cerr << "Shouldn't be in transaction when adding instruments." << std::endl; |
|
|
} |
|
1277 |
|
|
1278 |
if (pProgress != NULL) gig->GetInstrument(0, &(pProgress->GigFileProgress)); // TODO: this workaround should be fixed |
optional<InstrumentInfo> info = fileInfo->getInstrumentInfo(0, pProgress); |
1279 |
gig::Instrument* pInstrument = gig->GetFirstInstrument(); |
if (!InTransaction) DbInstrumentsMutex.Lock(); |
1280 |
|
while (info) { |
1281 |
|
String instrumentName = info->instrumentName; |
1282 |
|
if (instrumentName.empty()) |
1283 |
|
instrumentName = Path::getBaseName(FilePath); |
1284 |
|
instrumentName = GetUniqueName(dirId, instrumentName); |
1285 |
|
|
1286 |
|
BindTextParam(pStmt, 8, info->product); |
1287 |
|
BindTextParam(pStmt, 9, info->artists); |
1288 |
|
BindTextParam(pStmt, 10, info->keywords); |
1289 |
|
|
1290 |
|
std::stringstream sql2; |
1291 |
|
sql2 << "SELECT COUNT(*) FROM instruments WHERE instr_file=? AND "; |
1292 |
|
sql2 << "instr_nr=" << instrIndex; |
1293 |
|
String s = toEscapedFsPath(FilePath); |
1294 |
|
if (ExecSqlInt(sql2.str(), s) > 0) goto next; |
1295 |
|
|
1296 |
|
BindTextParam(pStmt, 1, instrumentName); |
1297 |
|
BindIntParam(pStmt, 3, instrIndex); |
1298 |
|
|
1299 |
|
BindTextParam(pStmt, 6, info->comments); |
1300 |
|
BindIntParam(pStmt, 7, info->isDrum); |
1301 |
|
|
1302 |
|
res = sqlite3_step(pStmt); |
1303 |
|
if (res != SQLITE_DONE) { |
1304 |
|
throw Exception("DB error: " + ToString(sqlite3_errmsg(db))); |
1305 |
|
} |
1306 |
|
res = sqlite3_reset(pStmt); |
1307 |
|
FireInstrumentCountChanged(DbDir); |
1308 |
|
|
1309 |
if (!InTransaction) DbInstrumentsMutex.Lock(); |
next: |
1310 |
while (pInstrument) { |
if (Index != -1) break; |
|
BindTextParam(pStmt, 7, gig->pInfo->Product); |
|
|
BindTextParam(pStmt, 8, gig->pInfo->Artists); |
|
|
BindTextParam(pStmt, 9, gig->pInfo->Keywords); |
|
|
AddGigInstrument(pStmt, DbDir, dirId, FilePath, pInstrument, instrIndex); |
|
1311 |
|
|
1312 |
instrIndex++; |
instrIndex++; |
1313 |
pInstrument = gig->GetNextInstrument(); |
info = fileInfo->getInstrumentInfo(instrIndex, pProgress); |
|
} |
|
|
} else { |
|
|
gig::Instrument* pInstrument; |
|
|
if (pProgress == NULL) pInstrument = gig->GetInstrument(Index); |
|
|
else pInstrument = gig->GetInstrument(Index, &(pProgress->GigFileProgress)); |
|
|
if (pInstrument != NULL) { |
|
|
BindTextParam(pStmt, 7, gig->pInfo->Product); |
|
|
BindTextParam(pStmt, 8, gig->pInfo->Artists); |
|
|
BindTextParam(pStmt, 9, gig->pInfo->Keywords); |
|
|
AddGigInstrument(pStmt, DbDir, dirId, FilePath, pInstrument, Index); |
|
|
} |
|
1314 |
} |
} |
1315 |
|
} catch (Exception e) { |
1316 |
sqlite3_finalize(pStmt); |
if (pStmt) sqlite3_finalize(pStmt); |
1317 |
delete gig; |
if (fileInfo) delete fileInfo; |
|
delete riff; |
|
|
} catch (RIFF::Exception e) { |
|
|
if (gig != NULL) delete gig; |
|
|
if (riff != NULL) delete riff; |
|
1318 |
if (unlocked) DbInstrumentsMutex.Lock(); |
if (unlocked) DbInstrumentsMutex.Lock(); |
1319 |
std::stringstream ss; |
std::stringstream ss; |
1320 |
ss << "Failed to scan `" << FilePath << "`: " << e.Message; |
ss << "Failed to scan `" << FilePath << "`: " << e.Message(); |
|
|
|
1321 |
throw Exception(ss.str()); |
throw Exception(ss.str()); |
|
} catch (Exception e) { |
|
|
if (gig != NULL) delete gig; |
|
|
if (riff != NULL) delete riff; |
|
|
if (unlocked) DbInstrumentsMutex.Lock(); |
|
|
throw e; |
|
1322 |
} catch (...) { |
} catch (...) { |
1323 |
if (gig != NULL) delete gig; |
if (pStmt) sqlite3_finalize(pStmt); |
1324 |
if (riff != NULL) delete riff; |
if (fileInfo) delete fileInfo; |
1325 |
if (unlocked) DbInstrumentsMutex.Lock(); |
if (unlocked) DbInstrumentsMutex.Lock(); |
1326 |
throw Exception("Failed to scan `" + FilePath + "`"); |
throw Exception("Failed to scan `" + FilePath + "`"); |
1327 |
} |
} |
1328 |
} |
if (pStmt) sqlite3_finalize(pStmt); |
1329 |
|
if (fileInfo) delete fileInfo; |
1330 |
void InstrumentsDb::AddGigInstrument(sqlite3_stmt* pStmt, String DbDir, int DirId, String File, gig::Instrument* pInstrument, int Index) { |
if (unlocked) DbInstrumentsMutex.Lock(); |
|
dmsg(2,("InstrumentsDb: AddGigInstrument(DbDir=%s,DirId=%d,File=%s,Index=%d)\n", DbDir.c_str(), DirId, File.c_str(), Index)); |
|
|
String name = pInstrument->pInfo->Name; |
|
|
if (name == "") return; |
|
|
name = GetUniqueName(DirId, name); |
|
|
|
|
|
std::stringstream sql2; |
|
|
sql2 << "SELECT COUNT(*) FROM instruments WHERE instr_file=? AND "; |
|
|
sql2 << "instr_nr=" << Index; |
|
|
String s = toEscapedFsPath(File); |
|
|
if (ExecSqlInt(sql2.str(), s) > 0) return; |
|
|
|
|
|
BindTextParam(pStmt, 1, name); |
|
|
BindIntParam(pStmt, 3, Index); |
|
|
|
|
|
BindTextParam(pStmt, 5, pInstrument->pInfo->Comments); |
|
|
BindIntParam(pStmt, 6, pInstrument->IsDrum); |
|
|
|
|
|
if (!pInstrument->pInfo->Product.empty()) { |
|
|
BindTextParam(pStmt, 7, pInstrument->pInfo->Product); |
|
|
} |
|
|
if (!pInstrument->pInfo->Artists.empty()) { |
|
|
BindTextParam(pStmt, 8, pInstrument->pInfo->Artists); |
|
|
} |
|
|
|
|
|
if (!pInstrument->pInfo->Keywords.empty()) { |
|
|
BindTextParam(pStmt, 9, pInstrument->pInfo->Keywords); |
|
|
} |
|
|
|
|
|
int res = sqlite3_step(pStmt); |
|
|
if(res != SQLITE_DONE) { |
|
|
sqlite3_finalize(pStmt); |
|
|
throw Exception("DB error: " + ToString(sqlite3_errmsg(db))); |
|
|
} |
|
|
|
|
|
res = sqlite3_reset(pStmt); |
|
|
FireInstrumentCountChanged(DbDir); |
|
1331 |
} |
} |
1332 |
|
|
1333 |
void InstrumentsDb::DirectoryTreeWalk(String AbstractPath, DirectoryHandler* pHandler) { |
void InstrumentsDb::DirectoryTreeWalk(String AbstractPath, DirectoryHandler* pHandler) { |