/[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 1644 by persson, Sat Jan 19 16:55:03 2008 UTC revision 1943 by persson, Tue Jul 14 18:25:11 2009 UTC
# Line 1  Line 1 
1  /***************************************************************************  /***************************************************************************
2   *                                                                         *   *                                                                         *
3   *   Copyright (C) 2007, 2008 Grigor Iliev                                 *   *   Copyright (C) 2007-2009 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 20  Line 20 
20    
21  #include "InstrumentsDb.h"  #include "InstrumentsDb.h"
22    
23    #include "../common/File.h"
24    #include "../common/Path.h"
25  #include "../common/global_private.h"  #include "../common/global_private.h"
26    
27  #include <iostream>  #include <iostream>
28  #include <sstream>  #include <sstream>
29  #include <vector>  #include <vector>
 #include <dirent.h>  
30  #include <errno.h>  #include <errno.h>
31    #ifndef WIN32
32  #include <fnmatch.h>  #include <fnmatch.h>
33    #else
34    #include <direct.h>
35    #endif
36  #include "../common/Exception.h"  #include "../common/Exception.h"
37    
38  namespace LinuxSampler {  namespace LinuxSampler {
39    
40      InstrumentsDb InstrumentsDb::instance;      InstrumentsDb InstrumentsDb::instance;
41    
42      void InstrumentsDb::CreateInstrumentsDb(String File) {      void InstrumentsDb::CreateInstrumentsDb(String FilePath) {
43          struct stat statBuf;          File f = File(FilePath);
44          int res = stat(File.c_str(), &statBuf);          if (f.Exist()) {
45          if (!res) {              throw Exception("File exists: " + FilePath);
             throw Exception("File exists: " + File);  
46          }          }
47                    
48          GetInstrumentsDb()->SetDbFile(File);          GetInstrumentsDb()->SetDbFile(FilePath);
49    
50          String sql =          String sql =
51              "  CREATE TABLE instr_dirs (                                      "              "  CREATE TABLE instr_dirs (                                      "
# Line 87  namespace LinuxSampler { Line 90  namespace LinuxSampler {
90    
91      InstrumentsDb::InstrumentsDb() {      InstrumentsDb::InstrumentsDb() {
92          db = NULL;          db = NULL;
         DbInstrumentsMutex = Mutex();  
93          InTransaction = false;          InTransaction = false;
94      }      }
95    
# Line 120  namespace LinuxSampler { Line 122  namespace LinuxSampler {
122      sqlite3* InstrumentsDb::GetDb() {      sqlite3* InstrumentsDb::GetDb() {
123          if ( db != NULL) return db;          if ( db != NULL) return db;
124    
125          if (DbFile.empty()) DbFile = CONFIG_DEFAULT_INSTRUMENTS_DB_LOCATION;          if (DbFile.empty()) {
126                        #ifndef WIN32
127                        DbFile = CONFIG_DEFAULT_INSTRUMENTS_DB_LOCATION;
128                            #else
129                            char *userprofile = getenv("USERPROFILE");
130                            if(userprofile) {
131                                String DbPath = userprofile;
132                                    DbPath += "\\.linuxsampler";
133                                DbFile = DbPath + "\\instruments.db";
134                                    File InstrumentsDbFile(DbFile);
135                                    // if no DB exists create the subdir and then the DB
136                                    if( !InstrumentsDbFile.Exist() ) {
137                                        _mkdir( DbPath.c_str() );
138                                            // formats the DB, which creates a new instruments.db file
139                                            Format();
140                                    }
141                        }
142                            else {
143                                // in case USERPROFILE is not set (which should not occur)
144                                DbFile = "instruments.db";
145                            }
146                            #endif
147                }
148                  #if defined(__APPLE__)  /* 20071224 Toshi Nagata  */                  #if defined(__APPLE__)  /* 20071224 Toshi Nagata  */
149                  if (DbFile.find("~") == 0)                  if (DbFile.find("~") == 0)
150                          DbFile.replace(0, 1, getenv("HOME"));                          DbFile.replace(0, 1, getenv("HOME"));
# Line 131  namespace LinuxSampler { Line 155  namespace LinuxSampler {
155              db = NULL;              db = NULL;
156              throw Exception("Cannot open instruments database: " + DbFile);              throw Exception("Cannot open instruments database: " + DbFile);
157          }          }
158    #ifndef WIN32
159          rc = sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8, NULL, Regexp, NULL, NULL);          rc = sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8, NULL, Regexp, NULL, NULL);
160          if (rc) { throw Exception("Failed to add user function for handling regular expressions."); }          if (rc) { throw Exception("Failed to add user function for handling regular expressions."); }
161    #endif
162    
163          // TODO: remove this in the next version          // TODO: remove this in the next version
164          try {          try {
# Line 261  namespace LinuxSampler { Line 287  namespace LinuxSampler {
287          return ExecSqlInt(sql.str(), DirName);          return ExecSqlInt(sql.str(), DirName);
288      }      }
289    
290        int InstrumentsDb::GetDirectoryId(int InstrId) {
291            dmsg(2,("InstrumentsDb: GetDirectoryId(InstrId=%d)\n", InstrId));
292            std::stringstream sql;
293            sql << "SELECT dir_id FROM instruments WHERE instr_id=" << InstrId;
294            return ExecSqlInt(sql.str());
295        }
296    
297      String InstrumentsDb::GetDirectoryName(int DirId) {      String InstrumentsDb::GetDirectoryName(int DirId) {
298          String sql = "SELECT dir_name FROM instr_dirs WHERE dir_id=" + ToString(DirId);          String sql = "SELECT dir_name FROM instr_dirs WHERE dir_id=" + ToString(DirId);
299          String name = ExecSqlString(sql);          String name = ExecSqlString(sql);
# Line 285  namespace LinuxSampler { Line 318  namespace LinuxSampler {
318                  path = "/" + path;                  path = "/" + path;
319                  break;                  break;
320              }              }
321              path = GetDirectoryName(DirId) + path;              path = GetDirectoryName(DirId) + "/" + path;
322              DirId = GetParentDirectoryId(DirId);              DirId = GetParentDirectoryId(DirId);
323          }          }
324    
# Line 293  namespace LinuxSampler { Line 326  namespace LinuxSampler {
326    
327          return path;          return path;
328      }      }
329        
330        StringListPtr InstrumentsDb::GetInstrumentsByFile(String File) {
331            dmsg(2,("InstrumentsDb: GetInstrumentsByFile(File=%s)\n", File.c_str()));
332    
333            StringListPtr instrs(new std::vector<String>);
334            
335            BeginTransaction();
336            try {
337                File = toEscapedFsPath(File);
338                IntListPtr ids = ExecSqlIntList("SELECT instr_id FROM instruments WHERE instr_file=?", File);
339                
340                for (int i = 0; i < ids->size(); i++) {
341                    String name = GetInstrumentName(ids->at(i));
342                    String dir = GetDirectoryPath(GetDirectoryId(ids->at(i)));
343                    instrs->push_back(dir + name);
344                }
345            } catch (Exception e) {
346                EndTransaction();
347                throw e;
348            }
349            EndTransaction();
350            
351            return instrs;
352        }
353    
354      void InstrumentsDb::AddDirectory(String Dir) {      void InstrumentsDb::AddDirectory(String Dir) {
355          dmsg(2,("InstrumentsDb: AddDirectory(Dir=%s)\n", Dir.c_str()));          dmsg(2,("InstrumentsDb: AddDirectory(Dir=%s)\n", Dir.c_str()));
# Line 611  namespace LinuxSampler { Line 668  namespace LinuxSampler {
668          FireDirectoryInfoChanged(Dir);          FireDirectoryInfoChanged(Dir);
669      }      }
670    
671      int InstrumentsDb::AddInstruments(ScanMode Mode, String DbDir, String FsDir, bool bBackground) {      int InstrumentsDb::AddInstruments(ScanMode Mode, String DbDir, String FsDir, bool bBackground, bool insDir) {
672          dmsg(2,("InstrumentsDb: AddInstruments(Mode=%d,DbDir=%s,FsDir=%s,bBackground=%d)\n", Mode, DbDir.c_str(), FsDir.c_str(), bBackground));          dmsg(2,("InstrumentsDb: AddInstruments(Mode=%d,DbDir=%s,FsDir=%s,bBackground=%d,insDir=%d)\n", Mode, DbDir.c_str(), FsDir.c_str(), bBackground, insDir));
673          if(!bBackground) {          if(!bBackground) {
674              switch (Mode) {              switch (Mode) {
675                  case NON_RECURSIVE:                  case NON_RECURSIVE:
676                      AddInstrumentsNonrecursive(DbDir, FsDir);                      AddInstrumentsNonrecursive(DbDir, FsDir, insDir);
677                      break;                      break;
678                  case RECURSIVE:                  case RECURSIVE:
679                      AddInstrumentsRecursive(DbDir, FsDir);                      AddInstrumentsRecursive(DbDir, FsDir, false, insDir);
680                      break;                      break;
681                  case FLAT:                  case FLAT:
682                      AddInstrumentsRecursive(DbDir, FsDir, true);                      AddInstrumentsRecursive(DbDir, FsDir, true, insDir);
683                      break;                      break;
684                  default:                  default:
685                      throw Exception("Unknown scan mode");                      throw Exception("Unknown scan mode");
# Line 633  namespace LinuxSampler { Line 690  namespace LinuxSampler {
690    
691          ScanJob job;          ScanJob job;
692          int jobId = Jobs.AddJob(job);          int jobId = Jobs.AddJob(job);
693          InstrumentsDbThread.Execute(new AddInstrumentsJob(jobId, Mode, DbDir, FsDir));          InstrumentsDbThread.Execute(new AddInstrumentsJob(jobId, Mode, DbDir, FsDir, insDir));
694    
695          return jobId;          return jobId;
696      }      }
# Line 641  namespace LinuxSampler { Line 698  namespace LinuxSampler {
698      int InstrumentsDb::AddInstruments(String DbDir, String FilePath, int Index, bool bBackground) {      int InstrumentsDb::AddInstruments(String DbDir, String FilePath, int Index, bool bBackground) {
699          dmsg(2,("InstrumentsDb: AddInstruments(DbDir=%s,FilePath=%s,Index=%d,bBackground=%d)\n", DbDir.c_str(), FilePath.c_str(), Index, bBackground));          dmsg(2,("InstrumentsDb: AddInstruments(DbDir=%s,FilePath=%s,Index=%d,bBackground=%d)\n", DbDir.c_str(), FilePath.c_str(), Index, bBackground));
700          if(!bBackground) {          if(!bBackground) {
701              AddInstruments(DbDir, FilePath, Index);              AddInstruments(DbDir, false, FilePath, Index);
702              return -1;              return -1;
703          }          }
704    
705          ScanJob job;          ScanJob job;
706          int jobId = Jobs.AddJob(job);          int jobId = Jobs.AddJob(job);
707          InstrumentsDbThread.Execute(new AddInstrumentsFromFileJob(jobId, DbDir, FilePath, Index));          InstrumentsDbThread.Execute(new AddInstrumentsFromFileJob(jobId, DbDir, FilePath, Index, false));
708    
709          return jobId;          return jobId;
710      }      }
711    
712      void InstrumentsDb::AddInstruments(String DbDir, String FilePath, int Index, ScanProgress* pProgress) {      void InstrumentsDb::AddInstruments(String DbDir, bool insDir, String FilePath, int Index, ScanProgress* pProgress) {
713          dmsg(2,("InstrumentsDb: AddInstruments(DbDir=%s,FilePath=%s,Index=%d)\n", DbDir.c_str(), 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));
714          if (DbDir.empty() || FilePath.empty()) return;          if (DbDir.empty() || FilePath.empty()) return;
715                    
716          DbInstrumentsMutex.Lock();          DbInstrumentsMutex.Lock();
# Line 661  namespace LinuxSampler { Line 718  namespace LinuxSampler {
718              int dirId = GetDirectoryId(DbDir);              int dirId = GetDirectoryId(DbDir);
719              if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedText(DbDir));              if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedText(DbDir));
720    
721              struct stat statBuf;              File f = File(FilePath);
722              int res = stat(FilePath.c_str(), &statBuf);              if (!f.Exist()) {
             if (res) {  
723                  std::stringstream ss;                  std::stringstream ss;
724                  ss << "Fail to stat `" << FilePath << "`: " << strerror(errno);                  ss << "Fail to stat `" << FilePath << "`: " << f.GetErrorMsg();
725                  throw Exception(ss.str());                  throw Exception(ss.str());
726              }              }
727    
728              if (!S_ISREG(statBuf.st_mode)) {              if (!f.IsFile()) {
729                  std::stringstream ss;                  std::stringstream ss;
730                  ss << "`" << FilePath << "` is not an instrument file";                  ss << "`" << FilePath << "` is not an instrument file";
731                  throw Exception(ss.str());                  throw Exception(ss.str());
732              }              }
733    
734              AddInstrumentsFromFile(DbDir, FilePath, Index, pProgress);              String dir = insDir ? PrepareSubdirectory(DbDir, FilePath) : DbDir;
735                AddInstrumentsFromFile(dir, FilePath, Index, pProgress);
736          } catch (Exception e) {          } catch (Exception e) {
737              DbInstrumentsMutex.Unlock();              DbInstrumentsMutex.Unlock();
738              throw e;              throw e;
# Line 684  namespace LinuxSampler { Line 741  namespace LinuxSampler {
741          DbInstrumentsMutex.Unlock();          DbInstrumentsMutex.Unlock();
742      }      }
743    
744      void InstrumentsDb::AddInstrumentsNonrecursive(String DbDir, String FsDir, ScanProgress* pProgress) {      void InstrumentsDb::AddInstrumentsNonrecursive(String DbDir, String FsDir, bool insDir, ScanProgress* pProgress) {
745          dmsg(2,("InstrumentsDb: AddInstrumentsNonrecursive(DbDir=%s,FsDir=%s)\n", DbDir.c_str(), FsDir.c_str()));          dmsg(2,("InstrumentsDb: AddInstrumentsNonrecursive(DbDir=%s,FsDir=%s,insDir=%d)\n", DbDir.c_str(), FsDir.c_str(), insDir));
746          if (DbDir.empty() || FsDir.empty()) return;          if (DbDir.empty() || FsDir.empty()) return;
747                    
748          DbInstrumentsMutex.Lock();          DbInstrumentsMutex.Lock();
# Line 693  namespace LinuxSampler { Line 750  namespace LinuxSampler {
750              int dirId = GetDirectoryId(DbDir);              int dirId = GetDirectoryId(DbDir);
751              if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedPath(DbDir));              if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedPath(DbDir));
752    
753              struct stat statBuf;              File f = File(FsDir);
754              int res = stat(FsDir.c_str(), &statBuf);              if (!f.Exist()) {
             if (res) {  
755                  std::stringstream ss;                  std::stringstream ss;
756                  ss << "Fail to stat `" << FsDir << "`: " << strerror(errno);                  ss << "Fail to stat `" << FsDir << "`: " << f.GetErrorMsg();
757                  throw Exception(ss.str());                  throw Exception(ss.str());
758              }              }
759    
760              if (!S_ISDIR(statBuf.st_mode)) {              if (!f.IsDirectory()) {
761                  throw Exception("Directory expected");                  throw Exception("Directory expected: " + FsDir);
762              }              }
763                            
764              if (FsDir.at(FsDir.length() - 1) != '/') FsDir.append("/");              if (FsDir.at(FsDir.length() - 1) != File::DirSeparator) {
765                    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;  
766              }              }
767                
768              struct dirent* pEnt = readdir(pDir);              try {
769              while (pEnt != NULL) {                  FileListPtr fileList = File::GetFiles(FsDir);
770                  if (pEnt->d_type != DT_REG) {                  for (int i = 0; i < fileList->size(); i++) {
771                      pEnt = readdir(pDir);                      String dir = insDir ? PrepareSubdirectory(DbDir, fileList->at(i)) : DbDir;
772                      continue;                                          AddInstrumentsFromFile(dir, FsDir + fileList->at(i), -1, pProgress);
773                  }                  }
774                } catch(Exception e) {
775                  AddInstrumentsFromFile(DbDir, FsDir + String(pEnt->d_name), -1, pProgress);                  e.PrintMessage();
776                  pEnt = readdir(pDir);                  DbInstrumentsMutex.Unlock();
777              }                  return;
   
             if (closedir(pDir)) {  
                 std::stringstream ss;  
                 ss << "Failed to close directory `" << FsDir << "`: ";  
                 ss << strerror(errno);  
                 std::cerr << ss.str();  
778              }              }
779          } catch (Exception e) {          } catch (Exception e) {
780              DbInstrumentsMutex.Unlock();              DbInstrumentsMutex.Unlock();
# Line 742  namespace LinuxSampler { Line 784  namespace LinuxSampler {
784          DbInstrumentsMutex.Unlock();          DbInstrumentsMutex.Unlock();
785      }      }
786    
787      void InstrumentsDb::AddInstrumentsRecursive(String DbDir, String FsDir, bool Flat, ScanProgress* pProgress) {      void InstrumentsDb::AddInstrumentsRecursive(String DbDir, String FsDir, bool Flat, bool insDir, ScanProgress* pProgress) {
788          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,insDir=%d)\n", DbDir.c_str(), FsDir.c_str(), Flat, insDir));
789          if (pProgress != NULL) {          if (pProgress != NULL) {
790              pProgress->SetTotalFileCount(InstrumentFileCounter::Count(FsDir));              InstrumentFileCounter c;
791                pProgress->SetTotalFileCount(c.Count(FsDir));
792          }          }
793    
794          DirectoryScanner::Scan(DbDir, FsDir, Flat, pProgress);          DirectoryScanner d;
795            d.Scan(DbDir, FsDir, Flat, insDir, pProgress);
796      }      }
797    
798      int InstrumentsDb::GetInstrumentCount(int DirId) {      int InstrumentsDb::GetInstrumentCount(int DirId) {
# Line 1137  namespace LinuxSampler { Line 1181  namespace LinuxSampler {
1181                  }                  }
1182              }              }
1183          } catch(Exception e) {          } catch(Exception e) {
1184              std::cerr << e.Message() << std::endl;              e.PrintMessage();
1185          }          }
1186      }      }
1187    
1188      void InstrumentsDb::AddGigInstruments(String DbDir, String File, int Index, ScanProgress* pProgress) {      void InstrumentsDb::AddGigInstruments(String DbDir, String FilePath, int Index, ScanProgress* pProgress) {
1189          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));
1190          int dirId = GetDirectoryId(DbDir);          int dirId = GetDirectoryId(DbDir);
1191          if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedPath(DbDir));          if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedPath(DbDir));
1192    
1193          struct stat statBuf;          File f = File(FilePath);
1194          int res = stat(File.c_str(), &statBuf);          if (!f.Exist()) {
         if (res) {  
1195              std::stringstream ss;              std::stringstream ss;
1196              ss << "Fail to stat `" << File << "`: " << strerror(errno);              ss << "Fail to stat `" << FilePath << "`: " << f.GetErrorMsg();
1197              throw Exception(ss.str());              throw Exception(ss.str());
1198          }          }
1199    
1200          if (!S_ISREG(statBuf.st_mode)) {          if (!f.IsFile()) {
1201              std::stringstream ss;              std::stringstream ss;
1202              ss << "`" << File << "` is not a regular file";              ss << "`" << FilePath << "` is not a regular file";
1203              throw Exception(ss.str());              throw Exception(ss.str());
1204          }          }
1205    
1206            bool unlocked = false;
1207          RIFF::File* riff = NULL;          RIFF::File* riff = NULL;
1208          gig::File* gig = NULL;          gig::File* gig = NULL;
1209          try {          try {
1210              riff = new RIFF::File(File);              riff = new RIFF::File(FilePath);
1211              gig::File* gig = new gig::File(riff);              gig::File* gig = new gig::File(riff);
1212              gig->SetAutoLoad(false); // avoid time consuming samples scanning              gig->SetAutoLoad(false); // avoid time consuming samples scanning
1213    
# Line 1171  namespace LinuxSampler { Line 1215  namespace LinuxSampler {
1215              sql << "INSERT INTO instruments (dir_id,instr_name,instr_file,";              sql << "INSERT INTO instruments (dir_id,instr_name,instr_file,";
1216              sql << "instr_nr,format_family,format_version,instr_size,";              sql << "instr_nr,format_family,format_version,instr_size,";
1217              sql << "description,is_drum,product,artists,keywords) VALUES (";              sql << "description,is_drum,product,artists,keywords) VALUES (";
1218              sql << dirId << ",?,?,?,'GIG',?," << statBuf.st_size << ",?,?,?,?,?)";              sql << dirId << ",?,?,?,'GIG',?," << f.GetSize() << ",?,?,?,?,?)";
1219    
1220              sqlite3_stmt* pStmt = NULL;              sqlite3_stmt* pStmt = NULL;
1221    
# Line 1180  namespace LinuxSampler { Line 1224  namespace LinuxSampler {
1224                  throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));                  throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1225              }              }
1226    
1227              String s = toEscapedFsPath(File);              String s = FilePath;
1228                s = toEscapedFsPath(s);
1229              BindTextParam(pStmt, 2, s);              BindTextParam(pStmt, 2, s);
1230              String ver = "";              String ver = "";
1231              if (gig->pVersion != NULL) ver = ToString(gig->pVersion->major);              if (gig->pVersion != NULL) ver = ToString(gig->pVersion->major);
# Line 1188  namespace LinuxSampler { Line 1233  namespace LinuxSampler {
1233    
1234              if (Index == -1) {              if (Index == -1) {
1235                  int instrIndex = 0;                  int instrIndex = 0;
1236                    // Assume that it's locked and should be unlocked at this point
1237                    // to be able to use the database from another threads
1238                    if (!InTransaction) {
1239                        DbInstrumentsMutex.Unlock();
1240                        unlocked = true;
1241                    } else {
1242                        std::cerr << "Shouldn't be in transaction when adding instruments." << std::endl;
1243                    }
1244    
1245                  if (pProgress != NULL) gig->GetInstrument(0, &(pProgress->GigFileProgress)); // TODO: this workaround should be fixed                  if (pProgress != NULL) gig->GetInstrument(0, &(pProgress->GigFileProgress)); // TODO: this workaround should be fixed
1246                  gig::Instrument* pInstrument = gig->GetFirstInstrument();                  gig::Instrument* pInstrument = gig->GetFirstInstrument();
1247    
1248                    if (!InTransaction) DbInstrumentsMutex.Lock();
1249                  while (pInstrument) {                  while (pInstrument) {
1250                      BindTextParam(pStmt, 7, gig->pInfo->Product);                      BindTextParam(pStmt, 7, gig->pInfo->Product);
1251                      BindTextParam(pStmt, 8, gig->pInfo->Artists);                      BindTextParam(pStmt, 8, gig->pInfo->Artists);
1252                      BindTextParam(pStmt, 9, gig->pInfo->Keywords);                      BindTextParam(pStmt, 9, gig->pInfo->Keywords);
1253                      AddGigInstrument(pStmt, DbDir, dirId, File, pInstrument, instrIndex);                      AddGigInstrument(pStmt, DbDir, dirId, FilePath, pInstrument, instrIndex);
1254    
1255                      instrIndex++;                      instrIndex++;
1256                      pInstrument = gig->GetNextInstrument();                      pInstrument = gig->GetNextInstrument();
# Line 1207  namespace LinuxSampler { Line 1263  namespace LinuxSampler {
1263                      BindTextParam(pStmt, 7, gig->pInfo->Product);                      BindTextParam(pStmt, 7, gig->pInfo->Product);
1264                      BindTextParam(pStmt, 8, gig->pInfo->Artists);                      BindTextParam(pStmt, 8, gig->pInfo->Artists);
1265                      BindTextParam(pStmt, 9, gig->pInfo->Keywords);                      BindTextParam(pStmt, 9, gig->pInfo->Keywords);
1266                      AddGigInstrument(pStmt, DbDir, dirId, File, pInstrument, Index);                      AddGigInstrument(pStmt, DbDir, dirId, FilePath, pInstrument, Index);
1267                  }                  }
1268              }              }
1269    
# Line 1217  namespace LinuxSampler { Line 1273  namespace LinuxSampler {
1273          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
1274              if (gig != NULL) delete gig;              if (gig != NULL) delete gig;
1275              if (riff != NULL) delete riff;              if (riff != NULL) delete riff;
1276                if (unlocked) DbInstrumentsMutex.Lock();
1277              std::stringstream ss;              std::stringstream ss;
1278              ss << "Failed to scan `" << File << "`: " << e.Message;              ss << "Failed to scan `" << FilePath << "`: " << e.Message;
1279                            
1280              throw Exception(ss.str());              throw Exception(ss.str());
1281          } catch (Exception e) {          } catch (Exception e) {
1282              if (gig != NULL) delete gig;              if (gig != NULL) delete gig;
1283              if (riff != NULL) delete riff;              if (riff != NULL) delete riff;
1284                if (unlocked) DbInstrumentsMutex.Lock();
1285              throw e;              throw e;
1286          } catch (...) {          } catch (...) {
1287              if (gig != NULL) delete gig;              if (gig != NULL) delete gig;
1288              if (riff != NULL) delete riff;              if (riff != NULL) delete riff;
1289              throw Exception("Failed to scan `" + File + "`");              if (unlocked) DbInstrumentsMutex.Lock();
1290                throw Exception("Failed to scan `" + FilePath + "`");
1291          }          }
1292      }      }
1293    
1294      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) {
1295            dmsg(2,("InstrumentsDb: AddGigInstrument(DbDir=%s,DirId=%d,File=%s,Index=%d)\n", DbDir.c_str(), DirId, File.c_str(), Index));
1296          String name = pInstrument->pInfo->Name;          String name = pInstrument->pInfo->Name;
1297          if (name == "") return;          if (name == "") return;
1298          name = GetUniqueInstrumentName(DirId, name);          name = GetUniqueName(DirId, name);
1299                    
1300          std::stringstream sql2;          std::stringstream sql2;
1301          sql2 << "SELECT COUNT(*) FROM instruments WHERE instr_file=? AND ";          sql2 << "SELECT COUNT(*) FROM instruments WHERE instr_file=? AND ";
# Line 1331  namespace LinuxSampler { Line 1391  namespace LinuxSampler {
1391    
1392          return instrumentFinder.GetInstruments();          return instrumentFinder.GetInstruments();
1393      }      }
1394        
1395        StringListPtr InstrumentsDb::FindLostInstrumentFiles() {
1396            dmsg(2,("InstrumentsDb: FindLostInstrumentFiles()\n"));
1397    
1398            BeginTransaction();
1399            try {
1400                StringListPtr files = ExecSqlStringList("SELECT DISTINCT instr_file FROM instruments");
1401                StringListPtr result(new std::vector<String>);
1402                for (int i = 0; i < files->size(); i++) {
1403                    File f(toNonEscapedFsPath(files->at(i)));
1404                    if (!f.Exist()) result->push_back(files->at(i));
1405                }
1406                return result;
1407            } catch (Exception e) {
1408                EndTransaction();
1409                throw e;
1410            }
1411            EndTransaction();
1412        }
1413        
1414        void InstrumentsDb::SetInstrumentFilePath(String OldPath, String NewPath) {
1415            if (OldPath == NewPath) return;
1416            StringListPtr instrs;
1417            BeginTransaction();
1418            try {
1419                std::vector<String> params(2);
1420                params[0] = toEscapedFsPath(NewPath);
1421                params[1] = toEscapedFsPath(OldPath);
1422                instrs = GetInstrumentsByFile(OldPath);
1423                ExecSql("UPDATE instruments SET instr_file=? WHERE instr_file=?", params);
1424            } catch (Exception e) {
1425                EndTransaction();
1426                throw e;
1427            }
1428            EndTransaction();
1429            
1430            for (int i = 0; i < instrs->size(); i++) {
1431                FireInstrumentInfoChanged(instrs->at(i));
1432            }
1433        }
1434    
1435      void InstrumentsDb::BeginTransaction() {      void InstrumentsDb::BeginTransaction() {
1436          dmsg(2,("InstrumentsDb: BeginTransaction(InTransaction=%d)\n", InTransaction));          dmsg(2,("InstrumentsDb: BeginTransaction(InTransaction=%d)\n", InTransaction));
# Line 1392  namespace LinuxSampler { Line 1492  namespace LinuxSampler {
1492    
1493      void InstrumentsDb::ExecSql(String Sql) {      void InstrumentsDb::ExecSql(String Sql) {
1494          dmsg(2,("InstrumentsDb: ExecSql(Sql=%s)\n", Sql.c_str()));          dmsg(2,("InstrumentsDb: ExecSql(Sql=%s)\n", Sql.c_str()));
1495          sqlite3_stmt *pStmt = NULL;          std::vector<String> Params;
1496                    ExecSql(Sql, Params);
         int res = sqlite3_prepare(GetDb(), Sql.c_str(), -1, &pStmt, NULL);  
         if (res != SQLITE_OK) {  
             throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));  
         }  
           
         res = sqlite3_step(pStmt);  
         if(res != SQLITE_DONE) {  
             sqlite3_finalize(pStmt);  
             throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));  
         }  
   
         sqlite3_finalize(pStmt);  
1497      }      }
1498    
1499      void InstrumentsDb::ExecSql(String Sql, String Param) {      void InstrumentsDb::ExecSql(String Sql, String Param) {
1500          dmsg(2,("InstrumentsDb: ExecSql(Sql=%s,Param=%s)\n", Sql.c_str(), Param.c_str()));          dmsg(2,("InstrumentsDb: ExecSql(Sql=%s,Param=%s)\n", Sql.c_str(), Param.c_str()));
1501            std::vector<String> Params;
1502            Params.push_back(Param);
1503            ExecSql(Sql, Params);
1504        }
1505    
1506        void InstrumentsDb::ExecSql(String Sql, std::vector<String>& Params) {
1507            dmsg(2,("InstrumentsDb: ExecSql(Sql=%s,Params)\n", Sql.c_str()));
1508          sqlite3_stmt *pStmt = NULL;          sqlite3_stmt *pStmt = NULL;
1509                    
1510          int res = sqlite3_prepare(GetDb(), Sql.c_str(), -1, &pStmt, NULL);          int res = sqlite3_prepare(GetDb(), Sql.c_str(), -1, &pStmt, NULL);
# Line 1418  namespace LinuxSampler { Line 1513  namespace LinuxSampler {
1513              throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));              throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1514          }          }
1515    
1516          BindTextParam(pStmt, 1, Param);          for(int i = 0; i < Params.size(); i++) {
1517                BindTextParam(pStmt, i + 1, Params[i]);
1518            }
1519    
1520          res = sqlite3_step(pStmt);          res = sqlite3_step(pStmt);
1521          if (res != SQLITE_DONE) {          if (res != SQLITE_DONE) {
# Line 1500  namespace LinuxSampler { Line 1597  namespace LinuxSampler {
1597      }      }
1598    
1599      IntListPtr InstrumentsDb::ExecSqlIntList(String Sql) {      IntListPtr InstrumentsDb::ExecSqlIntList(String Sql) {
1600            dmsg(2,("InstrumentsDb: ExecSqlIntList(Sql=%s)\n", Sql.c_str()));
1601            std::vector<String> Params;
1602            return ExecSqlIntList(Sql, Params);
1603        }
1604    
1605        IntListPtr InstrumentsDb::ExecSqlIntList(String Sql, String Param) {
1606            dmsg(2,("InstrumentsDb: ExecSqlIntList(Sql=%s,Param=%s)\n", Sql.c_str(), Param.c_str()));
1607            std::vector<String> Params;
1608            Params.push_back(Param);
1609            return ExecSqlIntList(Sql, Params);
1610        }
1611    
1612        IntListPtr InstrumentsDb::ExecSqlIntList(String Sql, std::vector<String>& Params) {
1613            dmsg(2,("InstrumentsDb: ExecSqlIntList(Sql=%s)\n", Sql.c_str()));
1614          IntListPtr intList(new std::vector<int>);          IntListPtr intList(new std::vector<int>);
1615                    
1616          sqlite3_stmt *pStmt = NULL;          sqlite3_stmt *pStmt = NULL;
# Line 1509  namespace LinuxSampler { Line 1620  namespace LinuxSampler {
1620              throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));              throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1621          }          }
1622                    
1623            for(int i = 0; i < Params.size(); i++) {
1624                BindTextParam(pStmt, i + 1, Params[i]);
1625            }
1626            
1627          res = sqlite3_step(pStmt);          res = sqlite3_step(pStmt);
1628          while(res == SQLITE_ROW) {          while(res == SQLITE_ROW) {
1629              intList->push_back(sqlite3_column_int(pStmt, 0));              intList->push_back(sqlite3_column_int(pStmt, 0));
# Line 1526  namespace LinuxSampler { Line 1641  namespace LinuxSampler {
1641      }      }
1642            
1643      StringListPtr InstrumentsDb::ExecSqlStringList(String Sql) {      StringListPtr InstrumentsDb::ExecSqlStringList(String Sql) {
1644            dmsg(2,("InstrumentsDb: ExecSqlStringList(Sql=%s)\n", Sql.c_str()));
1645          StringListPtr stringList(new std::vector<String>);          StringListPtr stringList(new std::vector<String>);
1646                    
1647          sqlite3_stmt *pStmt = NULL;          sqlite3_stmt *pStmt = NULL;
# Line 1569  namespace LinuxSampler { Line 1685  namespace LinuxSampler {
1685          }          }
1686      }      }
1687    
1688    #ifndef WIN32
1689      void InstrumentsDb::Regexp(sqlite3_context* pContext, int argc, sqlite3_value** ppValue) {      void InstrumentsDb::Regexp(sqlite3_context* pContext, int argc, sqlite3_value** ppValue) {
1690          if (argc != 2) return;          if (argc != 2) return;
1691    
# Line 1579  namespace LinuxSampler { Line 1696  namespace LinuxSampler {
1696              sqlite3_result_int(pContext, 1);              sqlite3_result_int(pContext, 1);
1697          }          }
1698      }      }
1699    #endif
1700    
1701      String InstrumentsDb::GetDirectoryPath(String File) {      String InstrumentsDb::GetDirectoryPath(String File) {
1702          if (File.empty()) return String("");          if (File.empty()) return String("");
# Line 1653  namespace LinuxSampler { Line 1771  namespace LinuxSampler {
1771          if (File.empty()) throw Exception("Invalid file name: " + File);          if (File.empty()) throw Exception("Invalid file name: " + File);
1772      }      }
1773    
1774      String InstrumentsDb::GetUniqueInstrumentName(int DirId, String Name) {      String InstrumentsDb::GetUniqueName(int DirId, String Name) {
1775          dmsg(2,("InstrumentsDb: GetUniqueInstrumentName(DirId=%d,Name=%s)\n", DirId, Name.c_str()));          dmsg(2,("InstrumentsDb: GetUniqueInstrumentName(DirId=%d,Name=%s)\n", DirId, Name.c_str()));
1776    
1777          if (GetInstrumentId(DirId, Name) == -1 && GetDirectoryId(DirId, Name) == -1) return Name;          if (GetInstrumentId(DirId, Name) == -1 && GetDirectoryId(DirId, Name) == -1) return Name;
# Line 1668  namespace LinuxSampler { Line 1786  namespace LinuxSampler {
1786    
1787          throw Exception("Unable to find an unique name: " + Name);          throw Exception("Unable to find an unique name: " + Name);
1788      }      }
1789        
1790        String InstrumentsDb::PrepareSubdirectory(String DbDir, String FsPath) {
1791            std::string dir = Path::getBaseName(FsPath);
1792            dir = toAbstractName(dir);
1793            if(dir.empty()) dir = "New Directory";
1794            dir = GetUniqueName(GetDirectoryId(DbDir), dir);
1795            dir = AppendNode(DbDir, dir);
1796            AddDirectory(dir);
1797            return dir;
1798        }
1799    
1800        String InstrumentsDb::AppendNode(String DbDir, String Node) {
1801            if(DbDir.length() == 1 && DbDir.at(0) == '/') return DbDir + Node;
1802            if(DbDir.at(DbDir.length() - 1) == '/') return DbDir + Node;
1803            return DbDir + "/" + Node;
1804        }
1805    
1806      String InstrumentsDb::toDbName(String AbstractName) {      String InstrumentsDb::toDbName(String AbstractName) {
1807          for (int i = 0; i < AbstractName.length(); i++) {          for (int i = 0; i < AbstractName.length(); i++) {
# Line 1699  namespace LinuxSampler { Line 1833  namespace LinuxSampler {
1833          return text;          return text;
1834      }      }
1835            
1836        String InstrumentsDb::toNonEscapedText(String text) {
1837            String sb;
1838            for (int i = 0; i < text.length(); i++) {
1839                char c = text.at(i);
1840                            if(c == '\\') {
1841                                    if(i >= text.length()) {
1842                                            std::cerr << "Broken escape sequence!" << std::endl;
1843                                            break;
1844                                    }
1845                                    char c2 = text.at(++i);
1846                                    if(c2 == '\'')      sb.push_back('\'');
1847                                    else if(c2 == '"')  sb.push_back('"');
1848                                    else if(c2 == '\\') sb.push_back('\\');
1849                                    else if(c2 == 'r')  sb.push_back('\r');
1850                                    else if(c2 == 'n')  sb.push_back('\n');
1851                                    else std::cerr << "Unknown escape sequence \\" << c2 << std::endl;
1852                            } else {
1853                                    sb.push_back(c);
1854                            }
1855            }
1856            return sb;
1857        }
1858        
1859      String InstrumentsDb::toEscapedFsPath(String FsPath) {      String InstrumentsDb::toEscapedFsPath(String FsPath) {
1860    #ifdef WIN32
1861            replace(FsPath.begin(), FsPath.end(), '\\', '/');
1862    #endif
1863          return toEscapedText(FsPath);          return toEscapedText(FsPath);
1864      }      }
1865            
1866        String InstrumentsDb::toNonEscapedFsPath(String FsPath) {
1867            FsPath = toNonEscapedText(FsPath);
1868    #ifdef WIN32
1869            replace(FsPath.begin(), FsPath.end(), '/', '\\');
1870    #endif
1871            return FsPath;
1872        }
1873        
1874      String InstrumentsDb::toAbstractName(String DbName) {      String InstrumentsDb::toAbstractName(String DbName) {
1875          for (int i = 0; i < DbName.length(); i++) {          for (int i = 0; i < DbName.length(); i++) {
1876              if (DbName.at(i) == '/') DbName.at(i) = '\0';              if (DbName.at(i) == '/') DbName.at(i) = '\0';

Legend:
Removed from v.1644  
changed lines
  Added in v.1943

  ViewVC Help
Powered by ViewVC