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

Diff of /linuxsampler/trunk/src/db/InstrumentsDb.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1910 by senoner, Fri Jun 5 14:22:20 2009 UTC revision 3705 by schoenebeck, Wed Jan 8 20:26:53 2020 UTC
# Line 1  Line 1 
1  /***************************************************************************  /***************************************************************************
2   *                                                                         *   *                                                                         *
3   *   Copyright (C) 2007-2009 Grigor Iliev, Benno Senoner                   *   *   Copyright (C) 2007-2013 Grigor Iliev, Benno Senoner                   *
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  *
# Line 27  Line 27 
27  #include <iostream>  #include <iostream>
28  #include <sstream>  #include <sstream>
29  #include <vector>  #include <vector>
30    #include <algorithm>
31  #include <errno.h>  #include <errno.h>
32  #ifndef WIN32  #ifndef WIN32
33  #include <fnmatch.h>  #include <fnmatch.h>
34    #else
35    #include <direct.h>
36  #endif  #endif
   
37  #include "../common/Exception.h"  #include "../common/Exception.h"
38    
39  namespace LinuxSampler {  namespace LinuxSampler {
# Line 39  namespace LinuxSampler { Line 41  namespace LinuxSampler {
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 (                                      "
# Line 58  namespace LinuxSampler { Line 65  namespace LinuxSampler {
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 (                                "
# Line 84  namespace LinuxSampler { Line 91  namespace LinuxSampler {
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() {
# Line 93  namespace LinuxSampler { Line 100  namespace LinuxSampler {
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            
# Line 109  namespace LinuxSampler { Line 117  namespace LinuxSampler {
117      }      }
118            
119      void InstrumentsDb::SetDbFile(String File) {      void InstrumentsDb::SetDbFile(String File) {
120          DbInstrumentsMutex.Lock();          LockGuard lock(DbInstrumentsMutex);
121          if (File.empty() || DbFile.length() > 0) {          if (File.empty() || DbFile.length() > 0) {
             DbInstrumentsMutex.Unlock();  
122              throw Exception("Failed to set the database file");              throw Exception("Failed to set the database file");
123          }          }
124          DbFile = File;          DbFile = File;
         DbInstrumentsMutex.Unlock();  
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()) DbFile = CONFIG_DEFAULT_INSTRUMENTS_DB_LOCATION;      void InstrumentsDb::EnsureDBFileExists() {
149            if (DbFile.empty())
150                DbFile = GetDefaultDBLocation();
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);
# Line 175  namespace LinuxSampler { Line 245  namespace LinuxSampler {
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));
# Line 212  namespace LinuxSampler { Line 282  namespace LinuxSampler {
282              return pDirs;              return pDirs;
283          } catch (Exception e) {          } catch (Exception e) {
284              EndTransaction();              EndTransaction();
285              throw e;              throw; // re-throw
286          }          }
287      }      }
288            
# Line 243  namespace LinuxSampler { Line 313  namespace LinuxSampler {
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));
# Line 321  namespace LinuxSampler { Line 391  namespace LinuxSampler {
391              }              }
392          } catch (Exception e) {          } catch (Exception e) {
393              EndTransaction();              EndTransaction();
394              throw e;              throw; // re-throw
395          }          }
396          EndTransaction();          EndTransaction();
397                    
# Line 358  namespace LinuxSampler { Line 428  namespace LinuxSampler {
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();
# Line 381  namespace LinuxSampler { Line 451  namespace LinuxSampler {
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();
# Line 440  namespace LinuxSampler { Line 510  namespace LinuxSampler {
510    
511      bool InstrumentsDb::DirectoryExist(String Dir) {      bool InstrumentsDb::DirectoryExist(String Dir) {
512          dmsg(2,("InstrumentsDb: DirectoryExist(Dir=%s)\n", Dir.c_str()));          dmsg(2,("InstrumentsDb: DirectoryExist(Dir=%s)\n", Dir.c_str()));
513          bool b;          {
514                LockGuard lock(DbInstrumentsMutex);
515          DbInstrumentsMutex.Lock();              return GetDirectoryId(Dir) != -1;
         try { b = GetDirectoryId(Dir) != -1; }  
         catch (Exception e) {  
             DbInstrumentsMutex.Unlock();  
             throw e;  
516          }          }
         DbInstrumentsMutex.Unlock();  
   
         return b;  
517      }      }
518    
519      DbDirectory InstrumentsDb::GetDirectoryInfo(String Dir) {      DbDirectory InstrumentsDb::GetDirectoryInfo(String Dir) {
# Line 491  namespace LinuxSampler { Line 554  namespace LinuxSampler {
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();
# Line 528  namespace LinuxSampler { Line 591  namespace LinuxSampler {
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();
# Line 573  namespace LinuxSampler { Line 636  namespace LinuxSampler {
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();
# Line 617  namespace LinuxSampler { Line 680  namespace LinuxSampler {
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();
# Line 638  namespace LinuxSampler { Line 701  namespace LinuxSampler {
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                    
# Line 690  namespace LinuxSampler { Line 753  namespace LinuxSampler {
753          dmsg(2,("InstrumentsDb: AddInstruments(DbDir=%s,insDir=%d,FilePath=%s,Index=%d)\n", DbDir.c_str(), insDir, FilePath.c_str(), Index));          dmsg(2,("InstrumentsDb: AddInstruments(DbDir=%s,insDir=%d,FilePath=%s,Index=%d)\n", DbDir.c_str(), insDir, FilePath.c_str(), Index));
754          if (DbDir.empty() || FilePath.empty()) return;          if (DbDir.empty() || FilePath.empty()) return;
755                    
756          DbInstrumentsMutex.Lock();          {
757          try {              LockGuard lock(DbInstrumentsMutex);
758    
759              int dirId = GetDirectoryId(DbDir);              int dirId = GetDirectoryId(DbDir);
760              if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedText(DbDir));              if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedText(DbDir));
761    
# Line 710  namespace LinuxSampler { Line 774  namespace LinuxSampler {
774    
775              String dir = insDir ? PrepareSubdirectory(DbDir, FilePath) : DbDir;              String dir = insDir ? PrepareSubdirectory(DbDir, FilePath) : DbDir;
776              AddInstrumentsFromFile(dir, FilePath, Index, pProgress);              AddInstrumentsFromFile(dir, FilePath, Index, pProgress);
         } catch (Exception e) {  
             DbInstrumentsMutex.Unlock();  
             throw e;  
777          }          }
   
         DbInstrumentsMutex.Unlock();  
778      }      }
779    
780      void InstrumentsDb::AddInstrumentsNonrecursive(String DbDir, String FsDir, bool insDir, ScanProgress* pProgress) {      void InstrumentsDb::AddInstrumentsNonrecursive(String DbDir, String FsDir, bool insDir, ScanProgress* pProgress) {
781          dmsg(2,("InstrumentsDb: AddInstrumentsNonrecursive(DbDir=%s,FsDir=%s,insDir=%d)\n", DbDir.c_str(), FsDir.c_str(), insDir));          dmsg(2,("InstrumentsDb: AddInstrumentsNonrecursive(DbDir=%s,FsDir=%s,insDir=%d)\n", DbDir.c_str(), FsDir.c_str(), insDir));
782          if (DbDir.empty() || FsDir.empty()) return;          if (DbDir.empty() || FsDir.empty()) return;
783                    
784          DbInstrumentsMutex.Lock();          {
785          try {              LockGuard lock(DbInstrumentsMutex);
786    
787              int dirId = GetDirectoryId(DbDir);              int dirId = GetDirectoryId(DbDir);
788              if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedPath(DbDir));              if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedPath(DbDir));
789    
# Line 750  namespace LinuxSampler { Line 810  namespace LinuxSampler {
810                  }                  }
811              } catch(Exception e) {              } catch(Exception e) {
812                  e.PrintMessage();                  e.PrintMessage();
                 DbInstrumentsMutex.Unlock();  
                 return;  
813              }              }
         } catch (Exception e) {  
             DbInstrumentsMutex.Unlock();  
             throw e;  
814          }          }
   
         DbInstrumentsMutex.Unlock();  
815      }      }
816    
817      void InstrumentsDb::AddInstrumentsRecursive(String DbDir, String FsDir, bool Flat, bool insDir, ScanProgress* pProgress) {      void InstrumentsDb::AddInstrumentsRecursive(String DbDir, String FsDir, bool Flat, bool insDir, ScanProgress* pProgress) {
# Line 797  namespace LinuxSampler { Line 850  namespace LinuxSampler {
850              }              }
851          } catch (Exception e) {          } catch (Exception e) {
852              EndTransaction();              EndTransaction();
853              throw e;              throw; // re-throw
854          }          }
855          EndTransaction();          EndTransaction();
856    
# Line 842  namespace LinuxSampler { Line 895  namespace LinuxSampler {
895              return pInstrs;              return pInstrs;
896          } catch (Exception e) {          } catch (Exception e) {
897              EndTransaction();              EndTransaction();
898              throw e;              throw; // re-throw
899          }          }
900      }      }
901    
# Line 885  namespace LinuxSampler { Line 938  namespace LinuxSampler {
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);
# Line 919  namespace LinuxSampler { Line 972  namespace LinuxSampler {
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                    
# Line 994  namespace LinuxSampler { Line 1047  namespace LinuxSampler {
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));
# Line 1037  namespace LinuxSampler { Line 1090  namespace LinuxSampler {
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);
# Line 1068  namespace LinuxSampler { Line 1121  namespace LinuxSampler {
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                    
# Line 1133  namespace LinuxSampler { Line 1186  namespace LinuxSampler {
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                BindTextParam(pStmt, 4, fileInfo->formatName());
1266                BindTextParam(pStmt, 5, fileInfo->formatVersion());
1267    
1268                int instrIndex = (Index == -1) ? 0 : Index;
1269    
1270                // Assume that it's locked and should be unlocked at this point
1271                // to be able to use the database from another threads
1272                if (!InTransaction) {
1273                    DbInstrumentsMutex.Unlock();
1274                    unlocked = true;
1275                } else {
1276                    std::cerr << "Shouldn't be in transaction when adding instruments." << std::endl;
1277                }
1278    
1279              #if WIN32              optional<InstrumentInfo> info = fileInfo->getInstrumentInfo(0, pProgress);
1280              for (int i = 0; i < s.length(); i++) {              if (!InTransaction) DbInstrumentsMutex.Lock();
1281                  if (s[i] == '\\') s[i] = '/';              while (info) {
1282              }                  String instrumentName = info->instrumentName;
1283              #endif                  if (instrumentName.empty())
1284                        instrumentName = Path::getBaseName(FilePath);
1285              s = toEscapedFsPath(s);                  instrumentName = GetUniqueName(dirId, instrumentName);
1286              BindTextParam(pStmt, 2, s);  
1287              String ver = "";                  BindTextParam(pStmt, 8, info->product);
1288              if (gig->pVersion != NULL) ver = ToString(gig->pVersion->major);                  BindTextParam(pStmt, 9, info->artists);
1289              BindTextParam(pStmt, 4, ver);                  BindTextParam(pStmt, 10, info->keywords);
1290    
1291              if (Index == -1) {                  std::stringstream sql2;
1292                  int instrIndex = 0;                  sql2 << "SELECT COUNT(*) FROM instruments WHERE instr_file=? AND ";
1293                  // Assume that it's locked and should be unlocked at this point                  sql2 << "instr_nr=" << instrIndex;
1294                  // to be able to use the database from another threads                  String s = toEscapedFsPath(FilePath);
1295                  if (!InTransaction) {                  if (ExecSqlInt(sql2.str(), s) > 0) goto next;
                     DbInstrumentsMutex.Unlock();  
                     unlocked = true;  
                 } else {  
                     std::cerr << "Shouldn't be in transaction when adding instruments." << std::endl;  
                 }  
1296    
1297                  if (pProgress != NULL) gig->GetInstrument(0, &(pProgress->GigFileProgress)); // TODO: this workaround should be fixed                  BindTextParam(pStmt, 1, instrumentName);
1298                  gig::Instrument* pInstrument = gig->GetFirstInstrument();                  BindIntParam(pStmt, 3, instrIndex);
1299    
1300                  if (!InTransaction) DbInstrumentsMutex.Lock();                  BindTextParam(pStmt, 6, info->comments);
1301                  while (pInstrument) {                  BindIntParam(pStmt, 7, info->isDrum);
                     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);  
1302    
1303                      instrIndex++;                  res = sqlite3_step(pStmt);
1304                      pInstrument = gig->GetNextInstrument();                  if (res != SQLITE_DONE) {
1305                  }                      throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
             } 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);  
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) {
# Line 1349  namespace LinuxSampler { Line 1366  namespace LinuxSampler {
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    
# Line 1369  namespace LinuxSampler { Line 1386  namespace LinuxSampler {
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    
# Line 1387  namespace LinuxSampler { Line 1404  namespace LinuxSampler {
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) {
# Line 1407  namespace LinuxSampler { Line 1424  namespace LinuxSampler {
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                    
# Line 1449  namespace LinuxSampler { Line 1466  namespace LinuxSampler {
1466          }          }
1467          InTransaction = false;          InTransaction = false;
1468                    
1469          if(db == NULL) {          if (db == NULL) {
1470              DbInstrumentsMutex.Unlock();              DbInstrumentsMutex.Unlock();
1471              return;              return;
1472          }          }
# Line 1653  namespace LinuxSampler { Line 1670  namespace LinuxSampler {
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)));
# Line 1687  namespace LinuxSampler { Line 1704  namespace LinuxSampler {
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);
# Line 1697  namespace LinuxSampler { Line 1714  namespace LinuxSampler {
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      }      }
1742    
1743      void InstrumentsDb::Format() {      void InstrumentsDb::Format() {
1744          DbInstrumentsMutex.Lock();          {
1745          if (db != NULL) {              LockGuard lock(DbInstrumentsMutex);
             sqlite3_close(db);  
             db = NULL;  
         }  
1746    
1747          if (DbFile.empty()) DbFile = CONFIG_DEFAULT_INSTRUMENTS_DB_LOCATION;              if (db != NULL) {
1748          String bkp = DbFile + ".bkp";                  sqlite3_close(db);
1749          remove(bkp.c_str());                  db = NULL;
1750          if (rename(DbFile.c_str(), bkp.c_str()) && errno != ENOENT) {              }
1751              DbInstrumentsMutex.Unlock();  
1752              throw Exception(String("Failed to backup database: ") + strerror(errno));              if (DbFile.empty()) DbFile = GetDefaultDBLocation();
1753          }              String bkp = DbFile + ".bkp";
1754                remove(bkp.c_str());
1755                if (rename(DbFile.c_str(), bkp.c_str()) && errno != ENOENT) {
1756                    throw Exception(String("Failed to backup database: ") + strerror(errno));
1757                }
1758                    
1759          String f = DbFile;              String f = DbFile;
1760          DbFile = "";              DbFile = "";
1761          try { CreateInstrumentsDb(f); }              CreateInstrumentsDb(f);
         catch(Exception e) {  
             DbInstrumentsMutex.Unlock();  
             throw e;  
1762          }          }
         DbInstrumentsMutex.Unlock();  
           
1763          FireDirectoryCountChanged("/");          FireDirectoryCountChanged("/");
1764          FireInstrumentCountChanged("/");          FireInstrumentCountChanged("/");
1765      }      }
# Line 1841  namespace LinuxSampler { Line 1854  namespace LinuxSampler {
1854      }      }
1855            
1856      String InstrumentsDb::toEscapedFsPath(String FsPath) {      String InstrumentsDb::toEscapedFsPath(String FsPath) {
1857    #ifdef WIN32
1858            replace(FsPath.begin(), FsPath.end(), '\\', '/');
1859    #endif
1860          return toEscapedText(FsPath);          return toEscapedText(FsPath);
1861      }      }
1862            
1863      String InstrumentsDb::toNonEscapedFsPath(String FsPath) {      String InstrumentsDb::toNonEscapedFsPath(String FsPath) {
1864          return toNonEscapedText(FsPath);          FsPath = toNonEscapedText(FsPath);
1865    #ifdef WIN32
1866            replace(FsPath.begin(), FsPath.end(), '/', '\\');
1867    #endif
1868            return FsPath;
1869      }      }
1870            
1871      String InstrumentsDb::toAbstractName(String DbName) {      String InstrumentsDb::toAbstractName(String DbName) {

Legend:
Removed from v.1910  
changed lines
  Added in v.3705

  ViewVC Help
Powered by ViewVC