41 |
InstrumentsDb InstrumentsDb::instance; |
InstrumentsDb InstrumentsDb::instance; |
42 |
|
|
43 |
void InstrumentsDb::CreateInstrumentsDb(String FilePath) { |
void InstrumentsDb::CreateInstrumentsDb(String FilePath) { |
44 |
|
if (FilePath.empty()) { |
45 |
|
FilePath = GetDefaultDBLocation(); |
46 |
|
dmsg(0,("InstrumentsDb: Creating database at default location '%s'\n", FilePath.c_str())); |
47 |
|
} |
48 |
|
|
49 |
File f = File(FilePath); |
File f = File(FilePath); |
50 |
if (f.Exist()) { |
if (f.Exist()) { |
51 |
throw Exception("File exists: " + FilePath); |
throw Exception("File exists: " + FilePath); |
52 |
} |
} |
53 |
|
|
54 |
GetInstrumentsDb()->SetDbFile(FilePath); |
SetDbFile(FilePath); |
55 |
|
|
56 |
String sql = |
String sql = |
57 |
" CREATE TABLE instr_dirs ( " |
" CREATE TABLE instr_dirs ( " |
65 |
" UNIQUE (parent_dir_id,dir_name) " |
" UNIQUE (parent_dir_id,dir_name) " |
66 |
" ); "; |
" ); "; |
67 |
|
|
68 |
GetInstrumentsDb()->ExecSql(sql); |
ExecSql(sql); |
69 |
|
|
70 |
sql = "INSERT INTO instr_dirs (dir_id, parent_dir_id, dir_name) VALUES (0, -2, '/');"; |
sql = "INSERT INTO instr_dirs (dir_id, parent_dir_id, dir_name) VALUES (0, -2, '/');"; |
71 |
GetInstrumentsDb()->ExecSql(sql); |
ExecSql(sql); |
72 |
|
|
73 |
sql = |
sql = |
74 |
" CREATE TABLE instruments ( " |
" CREATE TABLE instruments ( " |
91 |
" UNIQUE (dir_id,instr_name) " |
" UNIQUE (dir_id,instr_name) " |
92 |
" ); "; |
" ); "; |
93 |
|
|
94 |
GetInstrumentsDb()->ExecSql(sql); |
ExecSql(sql); |
95 |
} |
} |
96 |
|
|
97 |
InstrumentsDb::InstrumentsDb() { |
InstrumentsDb::InstrumentsDb() { |
100 |
} |
} |
101 |
|
|
102 |
InstrumentsDb::~InstrumentsDb() { |
InstrumentsDb::~InstrumentsDb() { |
103 |
|
InstrumentsDbThread.StopThread(); |
104 |
if (db != NULL) sqlite3_close(db); |
if (db != NULL) sqlite3_close(db); |
105 |
} |
} |
106 |
|
|
124 |
DbFile = File; |
DbFile = File; |
125 |
} |
} |
126 |
|
|
127 |
sqlite3* InstrumentsDb::GetDb() { |
String InstrumentsDb::GetDefaultDBLocation() { |
128 |
if ( db != NULL) return db; |
#ifdef WIN32 |
129 |
|
char* userprofile = getenv("USERPROFILE"); |
130 |
|
if (userprofile) { |
131 |
|
String s = userprofile; |
132 |
|
s += "\\.linuxsampler\\instruments.db"; |
133 |
|
return s; |
134 |
|
} else { |
135 |
|
// in case USERPROFILE is not set (which should not occur) |
136 |
|
return "instruments.db"; |
137 |
|
} |
138 |
|
#else // POSIX ... |
139 |
|
String s = CONFIG_DEFAULT_INSTRUMENTS_DB_LOCATION; |
140 |
|
# if defined(__APPLE__) |
141 |
|
if (s.find("~") == 0) |
142 |
|
s.replace(0, 1, getenv("HOME")); |
143 |
|
# endif |
144 |
|
return s; |
145 |
|
#endif |
146 |
|
} |
147 |
|
|
148 |
if (DbFile.empty()) { |
void InstrumentsDb::EnsureDBFileExists() { |
149 |
#ifndef WIN32 |
if (DbFile.empty()) |
150 |
DbFile = CONFIG_DEFAULT_INSTRUMENTS_DB_LOCATION; |
DbFile = GetDefaultDBLocation(); |
|
#else |
|
|
char *userprofile = getenv("USERPROFILE"); |
|
|
if(userprofile) { |
|
|
String DbPath = userprofile; |
|
|
DbPath += "\\.linuxsampler"; |
|
|
DbFile = DbPath + "\\instruments.db"; |
|
|
File InstrumentsDbFile(DbFile); |
|
|
// if no DB exists create the subdir and then the DB |
|
|
if( !InstrumentsDbFile.Exist() ) { |
|
|
_mkdir( DbPath.c_str() ); |
|
|
// formats the DB, which creates a new instruments.db file |
|
|
Format(); |
|
|
} |
|
|
} |
|
|
else { |
|
|
// in case USERPROFILE is not set (which should not occur) |
|
|
DbFile = "instruments.db"; |
|
|
} |
|
|
#endif |
|
|
} |
|
151 |
#if defined(__APPLE__) /* 20071224 Toshi Nagata */ |
#if defined(__APPLE__) /* 20071224 Toshi Nagata */ |
152 |
if (DbFile.find("~") == 0) |
if (DbFile.find("~") == 0) |
153 |
DbFile.replace(0, 1, getenv("HOME")); |
DbFile.replace(0, 1, getenv("HOME")); |
154 |
#endif |
#endif |
155 |
|
Path DbPath(DbFile); |
156 |
|
String DbDir = DbPath.stripLastName(); |
157 |
|
// create directory if it does not exist yet |
158 |
|
if (!DbPath.nodes().empty()) { |
159 |
|
File d(DbDir); |
160 |
|
if (!d.Exist()) { |
161 |
|
#ifdef WIN32 |
162 |
|
if (_mkdir(DbDir.c_str())) |
163 |
|
throw Exception("Could not create instruments DB directory '" + DbDir + "'"); |
164 |
|
#else |
165 |
|
if (mkdir(DbDir.c_str(), S_IRWXU)) |
166 |
|
throw Exception("Could not create instruments DB directory '" + DbDir + "'"); |
167 |
|
#endif |
168 |
|
} |
169 |
|
} |
170 |
|
// create database file if it does not exist yet |
171 |
|
File f(DbFile); |
172 |
|
if (!f.Exist()) { |
173 |
|
// formats the DB, which creates a new instruments.db file |
174 |
|
Format(); |
175 |
|
} |
176 |
|
} |
177 |
|
|
178 |
|
sqlite3* InstrumentsDb::GetDb() { |
179 |
|
if ( db != NULL) return db; |
180 |
|
|
181 |
|
if (DbFile.empty()) |
182 |
|
DbFile = GetDefaultDBLocation(); |
183 |
|
|
184 |
|
{ |
185 |
|
// first check if the instruments DB's directory exists, if not give up |
186 |
|
Path path(DbFile); |
187 |
|
String sDir = path.stripLastName(); |
188 |
|
File d(sDir); |
189 |
|
if (!d.Exist()) |
190 |
|
throw Exception("Instruments DB directory '" + sDir + "' does not exist!"); |
191 |
|
|
192 |
|
// just to give the user a notice about the DB file being created in case it does not exist yet |
193 |
|
File f(DbFile); |
194 |
|
if (!f.Exist()) |
195 |
|
dmsg(0,("Instruments DB file '%s' does not exist yet. Trying to create it now.\n", DbFile.c_str())); |
196 |
|
} |
197 |
|
|
198 |
|
dmsg(0,("Opening instruments DB at '%s'\n", DbFile.c_str())); |
199 |
int rc = sqlite3_open(DbFile.c_str(), &db); |
int rc = sqlite3_open(DbFile.c_str(), &db); |
200 |
if (rc) { |
if (rc) { |
201 |
sqlite3_close(db); |
sqlite3_close(db); |
245 |
} |
} |
246 |
} catch (Exception e) { |
} catch (Exception e) { |
247 |
EndTransaction(); |
EndTransaction(); |
248 |
throw e; |
throw; // re-throw |
249 |
} |
} |
250 |
EndTransaction(); |
EndTransaction(); |
251 |
if (i == -1) throw Exception("Unkown DB directory: " + toEscapedPath(Dir)); |
if (i == -1) throw Exception("Unkown DB directory: " + toEscapedPath(Dir)); |
282 |
return pDirs; |
return pDirs; |
283 |
} catch (Exception e) { |
} catch (Exception e) { |
284 |
EndTransaction(); |
EndTransaction(); |
285 |
throw e; |
throw; // re-throw |
286 |
} |
} |
287 |
} |
} |
288 |
|
|
313 |
} |
} |
314 |
|
|
315 |
int id = 0, i = 1; |
int id = 0, i = 1; |
316 |
int j = Dir.find('/', i); |
int j = (int) Dir.find('/', i); |
317 |
|
|
318 |
while(j != std::string::npos) { |
while(j != std::string::npos) { |
319 |
id = GetDirectoryId(id, Dir.substr(i, j - i)); |
id = GetDirectoryId(id, Dir.substr(i, j - i)); |
320 |
i = j + 1; |
i = j + 1; |
321 |
if (i >= Dir.length()) return id; |
if (i >= Dir.length()) return id; |
322 |
j = Dir.find('/', i); |
j = (int) Dir.find('/', i); |
323 |
} |
} |
324 |
|
|
325 |
return GetDirectoryId(id, Dir.substr(i)); |
return GetDirectoryId(id, Dir.substr(i)); |
391 |
} |
} |
392 |
} catch (Exception e) { |
} catch (Exception e) { |
393 |
EndTransaction(); |
EndTransaction(); |
394 |
throw e; |
throw; // re-throw |
395 |
} |
} |
396 |
EndTransaction(); |
EndTransaction(); |
397 |
|
|
428 |
ExecSql(sql.str(), toDbName(dirName)); |
ExecSql(sql.str(), toDbName(dirName)); |
429 |
} catch (Exception e) { |
} catch (Exception e) { |
430 |
EndTransaction(); |
EndTransaction(); |
431 |
throw e; |
throw; // re-throw |
432 |
} |
} |
433 |
|
|
434 |
EndTransaction(); |
EndTransaction(); |
451 |
RemoveDirectory(dirId); |
RemoveDirectory(dirId); |
452 |
} catch (Exception e) { |
} catch (Exception e) { |
453 |
EndTransaction(); |
EndTransaction(); |
454 |
throw e; |
throw; // re-throw |
455 |
} |
} |
456 |
|
|
457 |
EndTransaction(); |
EndTransaction(); |
554 |
sqlite3_finalize(pStmt); |
sqlite3_finalize(pStmt); |
555 |
} catch (Exception e) { |
} catch (Exception e) { |
556 |
EndTransaction(); |
EndTransaction(); |
557 |
throw e; |
throw; // re-throw |
558 |
} |
} |
559 |
|
|
560 |
EndTransaction(); |
EndTransaction(); |
591 |
ExecSql(sql.str(), dbName); |
ExecSql(sql.str(), dbName); |
592 |
} catch (Exception e) { |
} catch (Exception e) { |
593 |
EndTransaction(); |
EndTransaction(); |
594 |
throw e; |
throw; // re-throw |
595 |
} |
} |
596 |
|
|
597 |
EndTransaction(); |
EndTransaction(); |
636 |
ExecSql(sql.str()); |
ExecSql(sql.str()); |
637 |
} catch (Exception e) { |
} catch (Exception e) { |
638 |
EndTransaction(); |
EndTransaction(); |
639 |
throw e; |
throw; // re-throw |
640 |
} |
} |
641 |
|
|
642 |
EndTransaction(); |
EndTransaction(); |
680 |
DirectoryTreeWalk(Dir, &directoryCopier); |
DirectoryTreeWalk(Dir, &directoryCopier); |
681 |
} catch (Exception e) { |
} catch (Exception e) { |
682 |
EndTransaction(); |
EndTransaction(); |
683 |
throw e; |
throw; // re-throw |
684 |
} |
} |
685 |
|
|
686 |
EndTransaction(); |
EndTransaction(); |
701 |
ExecSql(sql.str(), Desc); |
ExecSql(sql.str(), Desc); |
702 |
} catch (Exception e) { |
} catch (Exception e) { |
703 |
EndTransaction(); |
EndTransaction(); |
704 |
throw e; |
throw; // re-throw |
705 |
} |
} |
706 |
EndTransaction(); |
EndTransaction(); |
707 |
|
|
850 |
} |
} |
851 |
} catch (Exception e) { |
} catch (Exception e) { |
852 |
EndTransaction(); |
EndTransaction(); |
853 |
throw e; |
throw; // re-throw |
854 |
} |
} |
855 |
EndTransaction(); |
EndTransaction(); |
856 |
|
|
895 |
return pInstrs; |
return pInstrs; |
896 |
} catch (Exception e) { |
} catch (Exception e) { |
897 |
EndTransaction(); |
EndTransaction(); |
898 |
throw e; |
throw; // re-throw |
899 |
} |
} |
900 |
} |
} |
901 |
|
|
938 |
RemoveInstrument(instrId); |
RemoveInstrument(instrId); |
939 |
} catch (Exception e) { |
} catch (Exception e) { |
940 |
EndTransaction(); |
EndTransaction(); |
941 |
throw e; |
throw; // re-throw |
942 |
} |
} |
943 |
EndTransaction(); |
EndTransaction(); |
944 |
FireInstrumentCountChanged(ParentDir); |
FireInstrumentCountChanged(ParentDir); |
972 |
i = GetInstrumentInfo(id); |
i = GetInstrumentInfo(id); |
973 |
} catch (Exception e) { |
} catch (Exception e) { |
974 |
EndTransaction(); |
EndTransaction(); |
975 |
throw e; |
throw; // re-throw |
976 |
} |
} |
977 |
EndTransaction(); |
EndTransaction(); |
978 |
|
|
1047 |
ExecSql(sql.str(), toDbName(Name)); |
ExecSql(sql.str(), toDbName(Name)); |
1048 |
} catch (Exception e) { |
} catch (Exception e) { |
1049 |
EndTransaction(); |
EndTransaction(); |
1050 |
throw e; |
throw; // re-throw |
1051 |
} |
} |
1052 |
EndTransaction(); |
EndTransaction(); |
1053 |
FireInstrumentNameChanged(Instr, toAbstractName(Name)); |
FireInstrumentNameChanged(Instr, toAbstractName(Name)); |
1090 |
ExecSql(sql.str()); |
ExecSql(sql.str()); |
1091 |
} catch (Exception e) { |
} catch (Exception e) { |
1092 |
EndTransaction(); |
EndTransaction(); |
1093 |
throw e; |
throw; // re-throw |
1094 |
} |
} |
1095 |
EndTransaction(); |
EndTransaction(); |
1096 |
FireInstrumentCountChanged(ParentDir); |
FireInstrumentCountChanged(ParentDir); |
1121 |
CopyInstrument(instrId, instrName, dstId, Dst); |
CopyInstrument(instrId, instrName, dstId, Dst); |
1122 |
} catch (Exception e) { |
} catch (Exception e) { |
1123 |
EndTransaction(); |
EndTransaction(); |
1124 |
throw e; |
throw; // re-throw |
1125 |
} |
} |
1126 |
EndTransaction(); |
EndTransaction(); |
1127 |
|
|
1186 |
ExecSql(sql.str(), Desc); |
ExecSql(sql.str(), Desc); |
1187 |
} catch (Exception e) { |
} catch (Exception e) { |
1188 |
EndTransaction(); |
EndTransaction(); |
1189 |
throw e; |
throw; // re-throw |
1190 |
} |
} |
1191 |
EndTransaction(); |
EndTransaction(); |
1192 |
FireInstrumentInfoChanged(Instr); |
FireInstrumentInfoChanged(Instr); |
1193 |
} |
} |
1194 |
|
|
1195 |
void InstrumentsDb::AddInstrumentsFromFile(String DbDir, String File, int Index, ScanProgress* pProgress) { |
void InstrumentsDb::AddInstrumentsFromFile(String DbDir, String file, int Index, ScanProgress* pProgress) { |
1196 |
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)); |
1197 |
|
|
1198 |
if(File.length() < 4) return; |
if (!InstrumentFileInfo::isSupportedFile(file)) return; |
1199 |
|
|
1200 |
try { |
try { |
1201 |
if(!strcasecmp(".gig", File.substr(File.length() - 4).c_str())) { |
if (pProgress != NULL) { |
1202 |
if (pProgress != NULL) { |
pProgress->SetStatus(0); |
1203 |
pProgress->SetStatus(0); |
pProgress->CurrentFile = file; |
1204 |
pProgress->CurrentFile = File; |
} |
|
} |
|
1205 |
|
|
1206 |
AddGigInstruments(DbDir, File, Index, pProgress); |
int dirId = GetDirectoryId(DbDir); |
1207 |
|
if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedPath(DbDir)); |
1208 |
|
|
1209 |
if (pProgress != NULL) { |
File f = File(file); |
1210 |
pProgress->SetScannedFileCount(pProgress->GetScannedFileCount() + 1); |
if (!f.Exist()) { |
1211 |
} |
std::stringstream ss; |
1212 |
|
ss << "Fail to stat `" << file << "`: " << f.GetErrorMsg(); |
1213 |
|
throw Exception(ss.str()); |
1214 |
|
} |
1215 |
|
|
1216 |
|
if (!f.IsFile()) { |
1217 |
|
std::stringstream ss; |
1218 |
|
ss << "`" << file << "` is not a regular file"; |
1219 |
|
throw Exception(ss.str()); |
1220 |
|
} |
1221 |
|
|
1222 |
|
AddInstrumentsFromFilePriv(DbDir, dirId, file, f, Index, pProgress); |
1223 |
|
|
1224 |
|
if (pProgress != NULL) { |
1225 |
|
pProgress->SetScannedFileCount(pProgress->GetScannedFileCount() + 1); |
1226 |
} |
} |
1227 |
} catch(Exception e) { |
} catch(Exception e) { |
1228 |
e.PrintMessage(); |
e.PrintMessage(); |
1229 |
} |
} |
1230 |
} |
} |
1231 |
|
|
1232 |
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) { |
1233 |
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()); |
|
|
} |
|
1234 |
|
|
1235 |
bool unlocked = false; |
bool unlocked = false; |
1236 |
RIFF::File* riff = NULL; |
InstrumentFileInfo* fileInfo = NULL; |
1237 |
gig::File* gig = NULL; |
sqlite3_stmt* pStmt = NULL; |
1238 |
try { |
try { |
1239 |
riff = new RIFF::File(FilePath); |
fileInfo = InstrumentFileInfo::getFileInfoFor(FilePath); |
1240 |
gig::File* gig = new gig::File(riff); |
if (!fileInfo) return; |
|
gig->SetAutoLoad(false); // avoid time consuming samples scanning |
|
1241 |
|
|
1242 |
std::stringstream sql; |
std::stringstream sql; |
1243 |
sql << "INSERT INTO instruments (dir_id,instr_name,instr_file,"; |
sql << "INSERT INTO instruments (dir_id,instr_name,instr_file,"; |
1244 |
sql << "instr_nr,format_family,format_version,instr_size,"; |
sql << "instr_nr,format_family,format_version,instr_size,"; |
1245 |
sql << "description,is_drum,product,artists,keywords) VALUES ("; |
sql << "description,is_drum,product,artists,keywords) VALUES ("; |
1246 |
sql << dirId << ",?,?,?,'GIG',?," << f.GetSize() << ",?,?,?,?,?)"; |
sql << dirId << ",?,?,?,?,?," << file.GetSize() << ",?,?,?,?,?)"; |
1247 |
|
|
1248 |
sqlite3_stmt* pStmt = NULL; |
// instr_name 1 |
1249 |
|
// instr_file 2 |
1250 |
|
// instr_nr 3 |
1251 |
|
// format_family 4 |
1252 |
|
// format_version 5 |
1253 |
|
// description 6 |
1254 |
|
// is_drum 7 |
1255 |
|
// product 8 |
1256 |
|
// artists 9 |
1257 |
|
// keywords 10 |
1258 |
|
|
1259 |
int res = sqlite3_prepare(GetDb(), sql.str().c_str(), -1, &pStmt, NULL); |
int res = sqlite3_prepare(GetDb(), sql.str().c_str(), -1, &pStmt, NULL); |
1260 |
if (res != SQLITE_OK) { |
if (res != SQLITE_OK) { |
1261 |
throw Exception("DB error: " + ToString(sqlite3_errmsg(db))); |
throw Exception("DB error: " + ToString(sqlite3_errmsg(db))); |
1262 |
} |
} |
1263 |
|
|
1264 |
String s = FilePath; |
BindTextParam(pStmt, 2, toEscapedFsPath(FilePath)); |
1265 |
s = toEscapedFsPath(s); |
BindTextParam(pStmt, 4, fileInfo->formatName()); |
1266 |
BindTextParam(pStmt, 2, s); |
BindTextParam(pStmt, 5, fileInfo->formatVersion()); |
1267 |
String ver = ""; |
|
1268 |
if (gig->pVersion != NULL) ver = ToString(gig->pVersion->major); |
int instrIndex = (Index == -1) ? 0 : Index; |
1269 |
BindTextParam(pStmt, 4, ver); |
|
1270 |
|
// Assume that it's locked and should be unlocked at this point |
1271 |
if (Index == -1) { |
// to be able to use the database from another threads |
1272 |
int instrIndex = 0; |
if (!InTransaction) { |
1273 |
// Assume that it's locked and should be unlocked at this point |
DbInstrumentsMutex.Unlock(); |
1274 |
// to be able to use the database from another threads |
unlocked = true; |
1275 |
if (!InTransaction) { |
} else { |
1276 |
DbInstrumentsMutex.Unlock(); |
std::cerr << "Shouldn't be in transaction when adding instruments." << std::endl; |
1277 |
unlocked = true; |
} |
|
} else { |
|
|
std::cerr << "Shouldn't be in transaction when adding instruments." << std::endl; |
|
|
} |
|
1278 |
|
|
1279 |
if (pProgress != NULL) gig->GetInstrument(0, &(pProgress->GigFileProgress)); // TODO: this workaround should be fixed |
optional<InstrumentInfo> info = fileInfo->getInstrumentInfo(0, pProgress); |
1280 |
gig::Instrument* pInstrument = gig->GetFirstInstrument(); |
if (!InTransaction) DbInstrumentsMutex.Lock(); |
1281 |
|
while (info) { |
1282 |
|
String instrumentName = info->instrumentName; |
1283 |
|
if (instrumentName.empty()) |
1284 |
|
instrumentName = Path::getBaseName(FilePath); |
1285 |
|
instrumentName = GetUniqueName(dirId, instrumentName); |
1286 |
|
|
1287 |
|
BindTextParam(pStmt, 8, info->product); |
1288 |
|
BindTextParam(pStmt, 9, info->artists); |
1289 |
|
BindTextParam(pStmt, 10, info->keywords); |
1290 |
|
|
1291 |
|
std::stringstream sql2; |
1292 |
|
sql2 << "SELECT COUNT(*) FROM instruments WHERE instr_file=? AND "; |
1293 |
|
sql2 << "instr_nr=" << instrIndex; |
1294 |
|
String s = toEscapedFsPath(FilePath); |
1295 |
|
if (ExecSqlInt(sql2.str(), s) > 0) goto next; |
1296 |
|
|
1297 |
if (!InTransaction) DbInstrumentsMutex.Lock(); |
BindTextParam(pStmt, 1, instrumentName); |
1298 |
while (pInstrument) { |
BindIntParam(pStmt, 3, instrIndex); |
|
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); |
|
1299 |
|
|
1300 |
instrIndex++; |
BindTextParam(pStmt, 6, info->comments); |
1301 |
pInstrument = gig->GetNextInstrument(); |
BindIntParam(pStmt, 7, info->isDrum); |
1302 |
} |
|
1303 |
} else { |
res = sqlite3_step(pStmt); |
1304 |
gig::Instrument* pInstrument; |
if (res != SQLITE_DONE) { |
1305 |
if (pProgress == NULL) pInstrument = gig->GetInstrument(Index); |
throw Exception("DB error: " + ToString(sqlite3_errmsg(db))); |
|
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); |
|
1306 |
} |
} |
1307 |
} |
res = sqlite3_reset(pStmt); |
1308 |
|
FireInstrumentCountChanged(DbDir); |
1309 |
|
|
1310 |
sqlite3_finalize(pStmt); |
next: |
1311 |
delete gig; |
if (Index != -1) break; |
1312 |
delete riff; |
|
1313 |
} catch (RIFF::Exception e) { |
instrIndex++; |
1314 |
if (gig != NULL) delete gig; |
info = fileInfo->getInstrumentInfo(instrIndex, pProgress); |
1315 |
if (riff != NULL) delete riff; |
} |
1316 |
|
} catch (Exception e) { |
1317 |
|
if (pStmt) sqlite3_finalize(pStmt); |
1318 |
|
if (fileInfo) delete fileInfo; |
1319 |
if (unlocked) DbInstrumentsMutex.Lock(); |
if (unlocked) DbInstrumentsMutex.Lock(); |
1320 |
std::stringstream ss; |
std::stringstream ss; |
1321 |
ss << "Failed to scan `" << FilePath << "`: " << e.Message; |
ss << "Failed to scan `" << FilePath << "`: " << e.Message(); |
|
|
|
1322 |
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; |
|
1323 |
} catch (...) { |
} catch (...) { |
1324 |
if (gig != NULL) delete gig; |
if (pStmt) sqlite3_finalize(pStmt); |
1325 |
if (riff != NULL) delete riff; |
if (fileInfo) delete fileInfo; |
1326 |
if (unlocked) DbInstrumentsMutex.Lock(); |
if (unlocked) DbInstrumentsMutex.Lock(); |
1327 |
throw Exception("Failed to scan `" + FilePath + "`"); |
throw Exception("Failed to scan `" + FilePath + "`"); |
1328 |
} |
} |
1329 |
} |
if (pStmt) sqlite3_finalize(pStmt); |
1330 |
|
if (fileInfo) delete fileInfo; |
1331 |
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); |
|
1332 |
} |
} |
1333 |
|
|
1334 |
void InstrumentsDb::DirectoryTreeWalk(String AbstractPath, DirectoryHandler* pHandler) { |
void InstrumentsDb::DirectoryTreeWalk(String AbstractPath, DirectoryHandler* pHandler) { |
1366 |
else directoryFinder.ProcessDirectory(Dir, DirId); |
else directoryFinder.ProcessDirectory(Dir, DirId); |
1367 |
} catch (Exception e) { |
} catch (Exception e) { |
1368 |
EndTransaction(); |
EndTransaction(); |
1369 |
throw e; |
throw; // re-throw |
1370 |
} |
} |
1371 |
EndTransaction(); |
EndTransaction(); |
1372 |
|
|
1386 |
else instrumentFinder.ProcessDirectory(Dir, DirId); |
else instrumentFinder.ProcessDirectory(Dir, DirId); |
1387 |
} catch (Exception e) { |
} catch (Exception e) { |
1388 |
EndTransaction(); |
EndTransaction(); |
1389 |
throw e; |
throw; // re-throw |
1390 |
} |
} |
1391 |
EndTransaction(); |
EndTransaction(); |
1392 |
|
|
1404 |
File f(toNonEscapedFsPath(files->at(i))); |
File f(toNonEscapedFsPath(files->at(i))); |
1405 |
if (!f.Exist()) result->push_back(files->at(i)); |
if (!f.Exist()) result->push_back(files->at(i)); |
1406 |
} |
} |
1407 |
|
EndTransaction(); |
1408 |
return result; |
return result; |
1409 |
} catch (Exception e) { |
} catch (Exception e) { |
1410 |
EndTransaction(); |
EndTransaction(); |
1411 |
throw e; |
throw; // re-throw |
1412 |
} |
} |
|
EndTransaction(); |
|
1413 |
} |
} |
1414 |
|
|
1415 |
void InstrumentsDb::SetInstrumentFilePath(String OldPath, String NewPath) { |
void InstrumentsDb::SetInstrumentFilePath(String OldPath, String NewPath) { |
1424 |
ExecSql("UPDATE instruments SET instr_file=? WHERE instr_file=?", params); |
ExecSql("UPDATE instruments SET instr_file=? WHERE instr_file=?", params); |
1425 |
} catch (Exception e) { |
} catch (Exception e) { |
1426 |
EndTransaction(); |
EndTransaction(); |
1427 |
throw e; |
throw; // re-throw |
1428 |
} |
} |
1429 |
EndTransaction(); |
EndTransaction(); |
1430 |
|
|
1670 |
|
|
1671 |
void InstrumentsDb::BindTextParam(sqlite3_stmt* pStmt, int Index, String Text) { |
void InstrumentsDb::BindTextParam(sqlite3_stmt* pStmt, int Index, String Text) { |
1672 |
if (pStmt == NULL) return; |
if (pStmt == NULL) return; |
1673 |
int res = sqlite3_bind_text(pStmt, Index, Text.c_str(), -1, SQLITE_STATIC); |
int res = sqlite3_bind_text(pStmt, Index, Text.c_str(), -1, SQLITE_TRANSIENT); |
1674 |
if (res != SQLITE_OK) { |
if (res != SQLITE_OK) { |
1675 |
sqlite3_finalize(pStmt); |
sqlite3_finalize(pStmt); |
1676 |
throw Exception("DB error: " + ToString(sqlite3_errmsg(db))); |
throw Exception("DB error: " + ToString(sqlite3_errmsg(db))); |
1704 |
if (File.at(0) != '/') String(""); |
if (File.at(0) != '/') String(""); |
1705 |
if (File.length() == 1) return File; |
if (File.length() == 1) return File; |
1706 |
if (File.at(File.length() - 1) == '/') return File.substr(0, File.length() - 1); |
if (File.at(File.length() - 1) == '/') return File.substr(0, File.length() - 1); |
1707 |
int i = File.rfind('/', File.length() - 1); |
int i = (int) File.rfind('/', File.length() - 1); |
1708 |
if(i == std::string::npos) return String(""); |
if(i == std::string::npos) return String(""); |
1709 |
if(i == 0) return String("/"); |
if(i == 0) return String("/"); |
1710 |
return File.substr(0, i); |
return File.substr(0, i); |
1714 |
if (Path.length() < 2) return String(""); |
if (Path.length() < 2) return String(""); |
1715 |
if (Path.at(0) != '/') String(""); |
if (Path.at(0) != '/') String(""); |
1716 |
if (Path.at(Path.length() - 1) == '/') return String(""); |
if (Path.at(Path.length() - 1) == '/') return String(""); |
1717 |
int i = Path.rfind('/', Path.length() - 1); |
int i = (int) Path.rfind('/', Path.length() - 1); |
1718 |
return Path.substr(i + 1); |
return Path.substr(i + 1); |
1719 |
} |
} |
1720 |
|
|
1721 |
void InstrumentsDb::CheckPathName(String Path) { |
void InstrumentsDb::CheckPathName(String Path) { |
1722 |
if (Path.empty()) return; |
if (Path.empty()) return; |
1723 |
|
|
1724 |
int i = 0, j = Path.find('/', i); |
int i = 0, j = (int)Path.find('/', i); |
1725 |
|
|
1726 |
while(j != std::string::npos) { |
while(j != std::string::npos) { |
1727 |
if (j + 1 >= Path.length()) return; |
if (j + 1 >= Path.length()) return; |
1728 |
if (Path.at(j + 1) == '/') throw Exception("Invalid path name: " + Path); |
if (Path.at(j + 1) == '/') throw Exception("Invalid path name: " + Path); |
1729 |
|
|
1730 |
i = j + 1; |
i = j + 1; |
1731 |
j = Path.find('/', i); |
j = (int) Path.find('/', i); |
1732 |
} |
} |
1733 |
} |
} |
1734 |
|
|
1735 |
String InstrumentsDb::GetParentDirectory(String Dir) { |
String InstrumentsDb::GetParentDirectory(String Dir) { |
1736 |
if (Dir.length() < 2) return String(""); |
if (Dir.length() < 2) return String(""); |
1737 |
if (Dir.at(0) != '/') String(""); |
if (Dir.at(0) != '/') String(""); |
1738 |
int i = Dir.rfind('/', Dir.length() - 2); |
int i = (int) Dir.rfind('/', Dir.length() - 2); |
1739 |
if (i == 0) return "/"; |
if (i == 0) return "/"; |
1740 |
return Dir.substr(0, i); |
return Dir.substr(0, i); |
1741 |
} |
} |
1749 |
db = NULL; |
db = NULL; |
1750 |
} |
} |
1751 |
|
|
1752 |
if (DbFile.empty()) DbFile = CONFIG_DEFAULT_INSTRUMENTS_DB_LOCATION; |
if (DbFile.empty()) DbFile = GetDefaultDBLocation(); |
1753 |
String bkp = DbFile + ".bkp"; |
String bkp = DbFile + ".bkp"; |
1754 |
remove(bkp.c_str()); |
remove(bkp.c_str()); |
1755 |
if (rename(DbFile.c_str(), bkp.c_str()) && errno != ENOENT) { |
if (rename(DbFile.c_str(), bkp.c_str()) && errno != ENOENT) { |