/[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 1350 by iliev, Sun Sep 16 23:06:10 2007 UTC revision 1781 by iliev, Mon Sep 29 18:21:21 2008 UTC
# Line 1  Line 1 
1  /***************************************************************************  /***************************************************************************
2   *                                                                         *   *                                                                         *
3   *   Copyright (C) 2007 Grigor Iliev                                       *   *   Copyright (C) 2007, 2008 Grigor Iliev                                 *
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  #if HAVE_SQLITE3  #include "../common/File.h"
24    #include "../common/global_private.h"
25    
26  #include <iostream>  #include <iostream>
27  #include <sstream>  #include <sstream>
28  #include <vector>  #include <vector>
 #include <dirent.h>  
29  #include <errno.h>  #include <errno.h>
30  #include <fnmatch.h>  #include <fnmatch.h>
31    
# Line 33  Line 33 
33    
34  namespace LinuxSampler {  namespace LinuxSampler {
35    
36      InstrumentsDb* InstrumentsDb::pInstrumentsDb = new InstrumentsDb;      InstrumentsDb InstrumentsDb::instance;
37    
38      void InstrumentsDb::CreateInstrumentsDb(String File) {      void InstrumentsDb::CreateInstrumentsDb(String FilePath) {
39          struct stat statBuf;          File f = File(FilePath);
40          int res = stat(File.c_str(), &statBuf);          if (f.Exist()) {
41          if (!res) {              throw Exception("File exists: " + FilePath);
             throw Exception("File exists: " + File);  
42          }          }
43                    
44          GetInstrumentsDb()->SetDbFile(File);          GetInstrumentsDb()->SetDbFile(FilePath);
45    
46          String sql =          String sql =
47              "  CREATE TABLE instr_dirs (                                      "              "  CREATE TABLE instr_dirs (                                      "
# Line 95  namespace LinuxSampler { Line 94  namespace LinuxSampler {
94          if (db != NULL) sqlite3_close(db);          if (db != NULL) sqlite3_close(db);
95      }      }
96            
     void InstrumentsDb::Destroy() {  
         if (pInstrumentsDb != NULL) {  
             delete pInstrumentsDb;  
             pInstrumentsDb = NULL;  
         }  
     }  
   
97      void InstrumentsDb::AddInstrumentsDbListener(InstrumentsDb::Listener* l) {      void InstrumentsDb::AddInstrumentsDbListener(InstrumentsDb::Listener* l) {
98          llInstrumentsDbListeners.AddListener(l);          llInstrumentsDbListeners.AddListener(l);
99      }      }
# Line 111  namespace LinuxSampler { Line 103  namespace LinuxSampler {
103      }      }
104            
105      InstrumentsDb* InstrumentsDb::GetInstrumentsDb() {      InstrumentsDb* InstrumentsDb::GetInstrumentsDb() {
106          return pInstrumentsDb;          return &instance;
107      }      }
108            
109      void InstrumentsDb::SetDbFile(String File) {      void InstrumentsDb::SetDbFile(String File) {
# Line 127  namespace LinuxSampler { Line 119  namespace LinuxSampler {
119      sqlite3* InstrumentsDb::GetDb() {      sqlite3* InstrumentsDb::GetDb() {
120          if ( db != NULL) return db;          if ( db != NULL) return db;
121    
122          if (DbFile.empty()) DbFile = "/var/lib/linuxsampler/instruments.db";          if (DbFile.empty()) DbFile = CONFIG_DEFAULT_INSTRUMENTS_DB_LOCATION;
123                    #if defined(__APPLE__)  /* 20071224 Toshi Nagata  */
124                    if (DbFile.find("~") == 0)
125                            DbFile.replace(0, 1, getenv("HOME"));
126                    #endif
127          int rc = sqlite3_open(DbFile.c_str(), &db);          int rc = sqlite3_open(DbFile.c_str(), &db);
128          if (rc) {          if (rc) {
129              sqlite3_close(db);              sqlite3_close(db);
# Line 264  namespace LinuxSampler { Line 260  namespace LinuxSampler {
260          return ExecSqlInt(sql.str(), DirName);          return ExecSqlInt(sql.str(), DirName);
261      }      }
262    
263        int InstrumentsDb::GetDirectoryId(int InstrId) {
264            dmsg(2,("InstrumentsDb: GetDirectoryId(InstrId=%d)\n", InstrId));
265            std::stringstream sql;
266            sql << "SELECT dir_id FROM instruments WHERE instr_id=" << InstrId;
267            return ExecSqlInt(sql.str());
268        }
269    
270      String InstrumentsDb::GetDirectoryName(int DirId) {      String InstrumentsDb::GetDirectoryName(int DirId) {
271          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);
272          String name = ExecSqlString(sql);          String name = ExecSqlString(sql);
# Line 288  namespace LinuxSampler { Line 291  namespace LinuxSampler {
291                  path = "/" + path;                  path = "/" + path;
292                  break;                  break;
293              }              }
294              path = GetDirectoryName(DirId) + path;              path = GetDirectoryName(DirId) + "/" + path;
295              DirId = GetParentDirectoryId(DirId);              DirId = GetParentDirectoryId(DirId);
296          }          }
297    
# Line 296  namespace LinuxSampler { Line 299  namespace LinuxSampler {
299    
300          return path;          return path;
301      }      }
302        
303        StringListPtr InstrumentsDb::GetInstrumentsByFile(String File) {
304            dmsg(2,("InstrumentsDb: GetInstrumentsByFile(File=%s)\n", File.c_str()));
305    
306            StringListPtr instrs(new std::vector<String>);
307            
308            BeginTransaction();
309            try {
310                File = toEscapedFsPath(File);
311                IntListPtr ids = ExecSqlIntList("SELECT instr_id FROM instruments WHERE instr_file=?", File);
312                
313                for (int i = 0; i < ids->size(); i++) {
314                    String name = GetInstrumentName(ids->at(i));
315                    String dir = GetDirectoryPath(GetDirectoryId(ids->at(i)));
316                    instrs->push_back(dir + name);
317                }
318            } catch (Exception e) {
319                EndTransaction();
320                throw e;
321            }
322            EndTransaction();
323            
324            return instrs;
325        }
326    
327      void InstrumentsDb::AddDirectory(String Dir) {      void InstrumentsDb::AddDirectory(String Dir) {
328          dmsg(2,("InstrumentsDb: AddDirectory(Dir=%s)\n", Dir.c_str()));          dmsg(2,("InstrumentsDb: AddDirectory(Dir=%s)\n", Dir.c_str()));
# Line 614  namespace LinuxSampler { Line 641  namespace LinuxSampler {
641          FireDirectoryInfoChanged(Dir);          FireDirectoryInfoChanged(Dir);
642      }      }
643    
644      int InstrumentsDb::AddInstruments(ScanMode Mode, String DbDir, String FsDir, bool bBackground) {      int InstrumentsDb::AddInstruments(ScanMode Mode, String DbDir, String FsDir, bool bBackground, bool insDir) {
645          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));
646          if(!bBackground) {          if(!bBackground) {
647              switch (Mode) {              switch (Mode) {
648                  case NON_RECURSIVE:                  case NON_RECURSIVE:
649                      AddInstrumentsNonrecursive(DbDir, FsDir);                      AddInstrumentsNonrecursive(DbDir, FsDir, insDir);
650                      break;                      break;
651                  case RECURSIVE:                  case RECURSIVE:
652                      AddInstrumentsRecursive(DbDir, FsDir);                      AddInstrumentsRecursive(DbDir, FsDir, false, insDir);
653                      break;                      break;
654                  case FLAT:                  case FLAT:
655                      AddInstrumentsRecursive(DbDir, FsDir, true);                      AddInstrumentsRecursive(DbDir, FsDir, true, insDir);
656                      break;                      break;
657                  default:                  default:
658                      throw Exception("Unknown scan mode");                      throw Exception("Unknown scan mode");
# Line 636  namespace LinuxSampler { Line 663  namespace LinuxSampler {
663    
664          ScanJob job;          ScanJob job;
665          int jobId = Jobs.AddJob(job);          int jobId = Jobs.AddJob(job);
666          InstrumentsDbThread.Execute(new AddInstrumentsJob(jobId, Mode, DbDir, FsDir));          InstrumentsDbThread.Execute(new AddInstrumentsJob(jobId, Mode, DbDir, FsDir, insDir));
667    
668          return jobId;          return jobId;
669      }      }
# Line 644  namespace LinuxSampler { Line 671  namespace LinuxSampler {
671      int InstrumentsDb::AddInstruments(String DbDir, String FilePath, int Index, bool bBackground) {      int InstrumentsDb::AddInstruments(String DbDir, String FilePath, int Index, bool bBackground) {
672          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));
673          if(!bBackground) {          if(!bBackground) {
674              AddInstruments(DbDir, FilePath, Index);              AddInstruments(DbDir, false, FilePath, Index);
675              return -1;              return -1;
676          }          }
677    
678          ScanJob job;          ScanJob job;
679          int jobId = Jobs.AddJob(job);          int jobId = Jobs.AddJob(job);
680          InstrumentsDbThread.Execute(new AddInstrumentsFromFileJob(jobId, DbDir, FilePath, Index));          InstrumentsDbThread.Execute(new AddInstrumentsFromFileJob(jobId, DbDir, FilePath, Index, false));
681    
682          return jobId;          return jobId;
683      }      }
684    
685      void InstrumentsDb::AddInstruments(String DbDir, String FilePath, int Index, ScanProgress* pProgress) {      void InstrumentsDb::AddInstruments(String DbDir, bool insDir, String FilePath, int Index, ScanProgress* pProgress) {
686          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));
687          if (DbDir.empty() || FilePath.empty()) return;          if (DbDir.empty() || FilePath.empty()) return;
688                    
689          DbInstrumentsMutex.Lock();          DbInstrumentsMutex.Lock();
# Line 664  namespace LinuxSampler { Line 691  namespace LinuxSampler {
691              int dirId = GetDirectoryId(DbDir);              int dirId = GetDirectoryId(DbDir);
692              if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedText(DbDir));              if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedText(DbDir));
693    
694              struct stat statBuf;              File f = File(FilePath);
695              int res = stat(FilePath.c_str(), &statBuf);              if (!f.Exist()) {
             if (res) {  
696                  std::stringstream ss;                  std::stringstream ss;
697                  ss << "Fail to stat `" << FilePath << "`: " << strerror(errno);                  ss << "Fail to stat `" << FilePath << "`: " << f.GetErrorMsg();
698                  throw Exception(ss.str());                  throw Exception(ss.str());
699              }              }
700    
701              if (!S_ISREG(statBuf.st_mode)) {              if (!f.IsFile()) {
702                  std::stringstream ss;                  std::stringstream ss;
703                  ss << "`" << FilePath << "` is not an instrument file";                  ss << "`" << FilePath << "` is not an instrument file";
704                  throw Exception(ss.str());                  throw Exception(ss.str());
705              }              }
706    
707              AddInstrumentsFromFile(DbDir, FilePath, Index, pProgress);                          if(insDir) {
708                                    std::string tmp = f.basename(FilePath, ".");
709                                    String gigDir;
710                                    if(DbDir.length() == 1 && DbDir.at(0) == '/') //DbDir is /
711                                            gigDir = DbDir + (String)tmp + "/";
712                                    else
713                                            gigDir = DbDir +"/"+ (String)tmp + "/";
714                                    dmsg(2,("InstrumentsDb: AddInstrumentsNonrecursive(Dir from file mode=%d, Created SubDir=%s)\n",insDir, gigDir.c_str()));
715                    DbInstrumentsMutex.Unlock();
716                                    AddDirectory(gigDir);//TODO: Add some error checking here to make sure the dir is created
717                    DbInstrumentsMutex.Lock();
718                    AddInstrumentsFromFile(gigDir, FilePath, Index, pProgress);
719                            } else {
720                    AddInstrumentsFromFile(DbDir, FilePath, Index, pProgress);
721                            }
722          } catch (Exception e) {          } catch (Exception e) {
723              DbInstrumentsMutex.Unlock();              DbInstrumentsMutex.Unlock();
724              throw e;              throw e;
# Line 687  namespace LinuxSampler { Line 727  namespace LinuxSampler {
727          DbInstrumentsMutex.Unlock();          DbInstrumentsMutex.Unlock();
728      }      }
729    
730      void InstrumentsDb::AddInstrumentsNonrecursive(String DbDir, String FsDir, ScanProgress* pProgress) {      void InstrumentsDb::AddInstrumentsNonrecursive(String DbDir, String FsDir, bool insDir, ScanProgress* pProgress) {
731          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));
732          if (DbDir.empty() || FsDir.empty()) return;          if (DbDir.empty() || FsDir.empty()) return;
733                    
734          DbInstrumentsMutex.Lock();          DbInstrumentsMutex.Lock();
# Line 696  namespace LinuxSampler { Line 736  namespace LinuxSampler {
736              int dirId = GetDirectoryId(DbDir);              int dirId = GetDirectoryId(DbDir);
737              if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedPath(DbDir));              if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedPath(DbDir));
738    
739              struct stat statBuf;              File f = File(FsDir);
740              int res = stat(FsDir.c_str(), &statBuf);              if (!f.Exist()) {
             if (res) {  
741                  std::stringstream ss;                  std::stringstream ss;
742                  ss << "Fail to stat `" << FsDir << "`: " << strerror(errno);                  ss << "Fail to stat `" << FsDir << "`: " << f.GetErrorMsg();
743                  throw Exception(ss.str());                  throw Exception(ss.str());
744              }              }
745    
746              if (!S_ISDIR(statBuf.st_mode)) {              if (!f.IsDirectory()) {
747                  throw Exception("Directory expected");                  throw Exception("Directory expected: " + FsDir);
748              }              }
749                            
750              if (FsDir.at(FsDir.length() - 1) != '/') FsDir.append("/");              if (FsDir.at(FsDir.length() - 1) != File::DirSeparator) {
751                    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;  
752              }              }
753                
754              struct dirent* pEnt = readdir(pDir);              try {
755              while (pEnt != NULL) {                  FileListPtr fileList = File::GetFiles(FsDir);
756                  if (pEnt->d_type != DT_REG) {                  for (int i = 0; i < fileList->size(); i++) {
757                      pEnt = readdir(pDir);                                          if(insDir)
758                      continue;                                          {
759                                                    //File gFile = File(fileList->at(i));
760                                                    String gigDir;
761                                                    if(DbDir.length() == 1 && DbDir.at(0) == '/') //DbDir is /
762                                                            gigDir  = DbDir + f.basename(fileList->at(i),".") + "/";
763                                                    else
764                                                            gigDir  = DbDir +"/"+ f.basename(fileList->at(i),".") + "/";
765                                                    dmsg(2,("InstrumentsDb: AddInstrumentsNonrecursive(Dir from file mode=%d, Created SubDir=%s)\n",insDir, gigDir.c_str()));
766                                    DbInstrumentsMutex.Unlock(); // UnLock the db so we can add our extra directory
767                                                    AddDirectory(gigDir);//TODO: Add some error checking here to make sure the dir is created
768                                            DbInstrumentsMutex.Lock(); //Lock and carry on
769                            AddInstrumentsFromFile(gigDir, FsDir + fileList->at(i), -1, pProgress);
770                                            }
771                                            else
772                                            {
773                            AddInstrumentsFromFile(DbDir, FsDir + fileList->at(i), -1, pProgress);
774                                            }
775                  }                  }
776                } catch(Exception e) {
777                  AddInstrumentsFromFile(DbDir, FsDir + String(pEnt->d_name), -1, pProgress);                  e.PrintMessage();
778                  pEnt = readdir(pDir);                  DbInstrumentsMutex.Unlock();
779              }                  return;
   
             if (closedir(pDir)) {  
                 std::stringstream ss;  
                 ss << "Failed to close directory `" << FsDir << "`: ";  
                 ss << strerror(errno);  
                 std::cerr << ss.str();  
780              }              }
781          } catch (Exception e) {          } catch (Exception e) {
782              DbInstrumentsMutex.Unlock();              DbInstrumentsMutex.Unlock();
# Line 745  namespace LinuxSampler { Line 786  namespace LinuxSampler {
786          DbInstrumentsMutex.Unlock();          DbInstrumentsMutex.Unlock();
787      }      }
788    
789      void InstrumentsDb::AddInstrumentsRecursive(String DbDir, String FsDir, bool Flat, ScanProgress* pProgress) {      void InstrumentsDb::AddInstrumentsRecursive(String DbDir, String FsDir, bool Flat, bool insDir, ScanProgress* pProgress) {
790          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));
791          if (pProgress != NULL) {          if (pProgress != NULL) {
792              pProgress->SetTotalFileCount(InstrumentFileCounter::Count(FsDir));              InstrumentFileCounter c;
793                pProgress->SetTotalFileCount(c.Count(FsDir));
794          }          }
795    
796          DirectoryScanner::Scan(DbDir, FsDir, Flat, pProgress);          DirectoryScanner d;
797            d.Scan(DbDir, FsDir, Flat, insDir, pProgress);
798      }      }
799    
800      int InstrumentsDb::GetInstrumentCount(int DirId) {      int InstrumentsDb::GetInstrumentCount(int DirId) {
# Line 1140  namespace LinuxSampler { Line 1183  namespace LinuxSampler {
1183                  }                  }
1184              }              }
1185          } catch(Exception e) {          } catch(Exception e) {
1186              std::cerr << e.Message() << std::endl;              e.PrintMessage();
1187          }          }
1188      }      }
1189    
1190      void InstrumentsDb::AddGigInstruments(String DbDir, String File, int Index, ScanProgress* pProgress) {      void InstrumentsDb::AddGigInstruments(String DbDir, String FilePath, int Index, ScanProgress* pProgress) {
1191          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));
1192          int dirId = GetDirectoryId(DbDir);          int dirId = GetDirectoryId(DbDir);
1193          if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedPath(DbDir));          if (dirId == -1) throw Exception("Invalid DB directory: " + toEscapedPath(DbDir));
1194    
1195          struct stat statBuf;          File f = File(FilePath);
1196          int res = stat(File.c_str(), &statBuf);          if (!f.Exist()) {
         if (res) {  
1197              std::stringstream ss;              std::stringstream ss;
1198              ss << "Fail to stat `" << File << "`: " << strerror(errno);              ss << "Fail to stat `" << FilePath << "`: " << f.GetErrorMsg();
1199              throw Exception(ss.str());              throw Exception(ss.str());
1200          }          }
1201    
1202          if (!S_ISREG(statBuf.st_mode)) {          if (!f.IsFile()) {
1203              std::stringstream ss;              std::stringstream ss;
1204              ss << "`" << File << "` is not a regular file";              ss << "`" << FilePath << "` is not a regular file";
1205              throw Exception(ss.str());              throw Exception(ss.str());
1206          }          }
1207    
1208          RIFF::File* riff = NULL;          RIFF::File* riff = NULL;
1209          gig::File* gig = NULL;          gig::File* gig = NULL;
1210          try {          try {
1211              riff = new RIFF::File(File);              riff = new RIFF::File(FilePath);
1212              gig::File* gig = new gig::File(riff);              gig::File* gig = new gig::File(riff);
1213                gig->SetAutoLoad(false); // avoid time consuming samples scanning
1214    
1215              std::stringstream sql;              std::stringstream sql;
1216              sql << "INSERT INTO instruments (dir_id,instr_name,instr_file,";              sql << "INSERT INTO instruments (dir_id,instr_name,instr_file,";
1217              sql << "instr_nr,format_family,format_version,instr_size,";              sql << "instr_nr,format_family,format_version,instr_size,";
1218              sql << "description,is_drum,product,artists,keywords) VALUES (";              sql << "description,is_drum,product,artists,keywords) VALUES (";
1219              sql << dirId << ",?,?,?,'GIG',?," << statBuf.st_size << ",?,?,?,?,?)";              sql << dirId << ",?,?,?,'GIG',?," << f.GetSize() << ",?,?,?,?,?)";
1220    
1221              sqlite3_stmt* pStmt = NULL;              sqlite3_stmt* pStmt = NULL;
1222    
# Line 1182  namespace LinuxSampler { Line 1225  namespace LinuxSampler {
1225                  throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));                  throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1226              }              }
1227    
1228              String s = toEscapedFsPath(File);              String s = toEscapedFsPath(FilePath);
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 1196  namespace LinuxSampler { Line 1239  namespace LinuxSampler {
1239                      BindTextParam(pStmt, 7, gig->pInfo->Product);                      BindTextParam(pStmt, 7, gig->pInfo->Product);
1240                      BindTextParam(pStmt, 8, gig->pInfo->Artists);                      BindTextParam(pStmt, 8, gig->pInfo->Artists);
1241                      BindTextParam(pStmt, 9, gig->pInfo->Keywords);                      BindTextParam(pStmt, 9, gig->pInfo->Keywords);
1242                      AddGigInstrument(pStmt, DbDir, dirId, File, pInstrument, instrIndex);                      AddGigInstrument(pStmt, DbDir, dirId, FilePath, pInstrument, instrIndex);
1243    
1244                      instrIndex++;                      instrIndex++;
1245                      pInstrument = gig->GetNextInstrument();                      pInstrument = gig->GetNextInstrument();
# Line 1209  namespace LinuxSampler { Line 1252  namespace LinuxSampler {
1252                      BindTextParam(pStmt, 7, gig->pInfo->Product);                      BindTextParam(pStmt, 7, gig->pInfo->Product);
1253                      BindTextParam(pStmt, 8, gig->pInfo->Artists);                      BindTextParam(pStmt, 8, gig->pInfo->Artists);
1254                      BindTextParam(pStmt, 9, gig->pInfo->Keywords);                      BindTextParam(pStmt, 9, gig->pInfo->Keywords);
1255                      AddGigInstrument(pStmt, DbDir, dirId, File, pInstrument, Index);                      AddGigInstrument(pStmt, DbDir, dirId, FilePath, pInstrument, Index);
1256                  }                  }
1257              }              }
1258    
# Line 1220  namespace LinuxSampler { Line 1263  namespace LinuxSampler {
1263              if (gig != NULL) delete gig;              if (gig != NULL) delete gig;
1264              if (riff != NULL) delete riff;              if (riff != NULL) delete riff;
1265              std::stringstream ss;              std::stringstream ss;
1266              ss << "Failed to scan `" << File << "`: " << e.Message;              ss << "Failed to scan `" << FilePath << "`: " << e.Message;
1267                            
1268              throw Exception(ss.str());              throw Exception(ss.str());
1269          } catch (Exception e) {          } catch (Exception e) {
# Line 1230  namespace LinuxSampler { Line 1273  namespace LinuxSampler {
1273          } catch (...) {          } catch (...) {
1274              if (gig != NULL) delete gig;              if (gig != NULL) delete gig;
1275              if (riff != NULL) delete riff;              if (riff != NULL) delete riff;
1276              throw Exception("Failed to scan `" + File + "`");              throw Exception("Failed to scan `" + FilePath + "`");
1277          }          }
1278      }      }
1279    
1280      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) {
1281            dmsg(2,("InstrumentsDb: AddGigInstrument(DbDir=%s,DirId=%d,File=%s,Index=%d)\n", DbDir.c_str(), DirId, File.c_str(), Index));
1282          String name = pInstrument->pInfo->Name;          String name = pInstrument->pInfo->Name;
1283          if (name == "") return;          if (name == "") return;
1284          name = GetUniqueInstrumentName(DirId, name);          name = GetUniqueInstrumentName(DirId, name);
# Line 1333  namespace LinuxSampler { Line 1377  namespace LinuxSampler {
1377    
1378          return instrumentFinder.GetInstruments();          return instrumentFinder.GetInstruments();
1379      }      }
1380        
1381        StringListPtr InstrumentsDb::FindLostInstrumentFiles() {
1382            dmsg(2,("InstrumentsDb: FindLostInstrumentFiles()\n"));
1383    
1384            BeginTransaction();
1385            try {
1386                StringListPtr files = ExecSqlStringList("SELECT DISTINCT instr_file FROM instruments");
1387                StringListPtr result(new std::vector<String>);
1388                for (int i = 0; i < files->size(); i++) {
1389                    File f(toNonEscapedFsPath(files->at(i)));
1390                    if (!f.Exist()) result->push_back(files->at(i));
1391                }
1392                return result;
1393            } catch (Exception e) {
1394                EndTransaction();
1395                throw e;
1396            }
1397            EndTransaction();
1398        }
1399        
1400        void InstrumentsDb::SetInstrumentFilePath(String OldPath, String NewPath) {
1401            if (OldPath == NewPath) return;
1402            StringListPtr instrs;
1403            BeginTransaction();
1404            try {
1405                std::vector<String> params(2);
1406                params[0] = toEscapedFsPath(NewPath);
1407                params[1] = toEscapedFsPath(OldPath);
1408                instrs = GetInstrumentsByFile(OldPath);
1409                ExecSql("UPDATE instruments SET instr_file=? WHERE instr_file=?", params);
1410            } catch (Exception e) {
1411                EndTransaction();
1412                throw e;
1413            }
1414            EndTransaction();
1415            
1416            for (int i = 0; i < instrs->size(); i++) {
1417                FireInstrumentInfoChanged(instrs->at(i));
1418            }
1419        }
1420    
1421      void InstrumentsDb::BeginTransaction() {      void InstrumentsDb::BeginTransaction() {
1422          dmsg(2,("InstrumentsDb: BeginTransaction(InTransaction=%d)\n", InTransaction));          dmsg(2,("InstrumentsDb: BeginTransaction(InTransaction=%d)\n", InTransaction));
# Line 1394  namespace LinuxSampler { Line 1478  namespace LinuxSampler {
1478    
1479      void InstrumentsDb::ExecSql(String Sql) {      void InstrumentsDb::ExecSql(String Sql) {
1480          dmsg(2,("InstrumentsDb: ExecSql(Sql=%s)\n", Sql.c_str()));          dmsg(2,("InstrumentsDb: ExecSql(Sql=%s)\n", Sql.c_str()));
1481          sqlite3_stmt *pStmt = NULL;          std::vector<String> Params;
1482                    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);  
1483      }      }
1484    
1485      void InstrumentsDb::ExecSql(String Sql, String Param) {      void InstrumentsDb::ExecSql(String Sql, String Param) {
1486          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()));
1487            std::vector<String> Params;
1488            Params.push_back(Param);
1489            ExecSql(Sql, Params);
1490        }
1491    
1492        void InstrumentsDb::ExecSql(String Sql, std::vector<String>& Params) {
1493            dmsg(2,("InstrumentsDb: ExecSql(Sql=%s,Params)\n", Sql.c_str()));
1494          sqlite3_stmt *pStmt = NULL;          sqlite3_stmt *pStmt = NULL;
1495                    
1496          int res = sqlite3_prepare(GetDb(), Sql.c_str(), -1, &pStmt, NULL);          int res = sqlite3_prepare(GetDb(), Sql.c_str(), -1, &pStmt, NULL);
# Line 1420  namespace LinuxSampler { Line 1499  namespace LinuxSampler {
1499              throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));              throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1500          }          }
1501    
1502          BindTextParam(pStmt, 1, Param);          for(int i = 0; i < Params.size(); i++) {
1503                BindTextParam(pStmt, i + 1, Params[i]);
1504            }
1505    
1506          res = sqlite3_step(pStmt);          res = sqlite3_step(pStmt);
1507          if (res != SQLITE_DONE) {          if (res != SQLITE_DONE) {
# Line 1502  namespace LinuxSampler { Line 1583  namespace LinuxSampler {
1583      }      }
1584    
1585      IntListPtr InstrumentsDb::ExecSqlIntList(String Sql) {      IntListPtr InstrumentsDb::ExecSqlIntList(String Sql) {
1586            dmsg(2,("InstrumentsDb: ExecSqlIntList(Sql=%s)\n", Sql.c_str()));
1587            std::vector<String> Params;
1588            return ExecSqlIntList(Sql, Params);
1589        }
1590    
1591        IntListPtr InstrumentsDb::ExecSqlIntList(String Sql, String Param) {
1592            dmsg(2,("InstrumentsDb: ExecSqlIntList(Sql=%s,Param=%s)\n", Sql.c_str(), Param.c_str()));
1593            std::vector<String> Params;
1594            Params.push_back(Param);
1595            return ExecSqlIntList(Sql, Params);
1596        }
1597    
1598        IntListPtr InstrumentsDb::ExecSqlIntList(String Sql, std::vector<String>& Params) {
1599            dmsg(2,("InstrumentsDb: ExecSqlIntList(Sql=%s)\n", Sql.c_str()));
1600          IntListPtr intList(new std::vector<int>);          IntListPtr intList(new std::vector<int>);
1601                    
1602          sqlite3_stmt *pStmt = NULL;          sqlite3_stmt *pStmt = NULL;
# Line 1511  namespace LinuxSampler { Line 1606  namespace LinuxSampler {
1606              throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));              throw Exception("DB error: " + ToString(sqlite3_errmsg(db)));
1607          }          }
1608                    
1609            for(int i = 0; i < Params.size(); i++) {
1610                BindTextParam(pStmt, i + 1, Params[i]);
1611            }
1612            
1613          res = sqlite3_step(pStmt);          res = sqlite3_step(pStmt);
1614          while(res == SQLITE_ROW) {          while(res == SQLITE_ROW) {
1615              intList->push_back(sqlite3_column_int(pStmt, 0));              intList->push_back(sqlite3_column_int(pStmt, 0));
# Line 1528  namespace LinuxSampler { Line 1627  namespace LinuxSampler {
1627      }      }
1628            
1629      StringListPtr InstrumentsDb::ExecSqlStringList(String Sql) {      StringListPtr InstrumentsDb::ExecSqlStringList(String Sql) {
1630            dmsg(2,("InstrumentsDb: ExecSqlStringList(Sql=%s)\n", Sql.c_str()));
1631          StringListPtr stringList(new std::vector<String>);          StringListPtr stringList(new std::vector<String>);
1632                    
1633          sqlite3_stmt *pStmt = NULL;          sqlite3_stmt *pStmt = NULL;
# Line 1623  namespace LinuxSampler { Line 1723  namespace LinuxSampler {
1723          return Dir.substr(0, i);          return Dir.substr(0, i);
1724      }      }
1725    
1726        void InstrumentsDb::Format() {
1727            DbInstrumentsMutex.Lock();
1728            if (db != NULL) {
1729                sqlite3_close(db);
1730                db = NULL;
1731            }
1732    
1733            if (DbFile.empty()) DbFile = CONFIG_DEFAULT_INSTRUMENTS_DB_LOCATION;
1734            String bkp = DbFile + ".bkp";
1735            remove(bkp.c_str());
1736            if (rename(DbFile.c_str(), bkp.c_str()) && errno != ENOENT) {
1737                DbInstrumentsMutex.Unlock();
1738                throw Exception(String("Failed to backup database: ") + strerror(errno));
1739            }
1740            
1741            String f = DbFile;
1742            DbFile = "";
1743            try { CreateInstrumentsDb(f); }
1744            catch(Exception e) {
1745                DbInstrumentsMutex.Unlock();
1746                throw e;
1747            }
1748            DbInstrumentsMutex.Unlock();
1749            
1750            FireDirectoryCountChanged("/");
1751            FireInstrumentCountChanged("/");
1752        }
1753    
1754      void InstrumentsDb::CheckFileName(String File) {      void InstrumentsDb::CheckFileName(String File) {
1755          if (File.empty()) throw Exception("Invalid file name: " + File);          if (File.empty()) throw Exception("Invalid file name: " + File);
1756      }      }
# Line 1673  namespace LinuxSampler { Line 1801  namespace LinuxSampler {
1801          return text;          return text;
1802      }      }
1803            
1804        String InstrumentsDb::toNonEscapedText(String text) {
1805            String sb;
1806            for (int i = 0; i < text.length(); i++) {
1807                char c = text.at(i);
1808                            if(c == '\\') {
1809                                    if(i >= text.length()) {
1810                                            std::cerr << "Broken escape sequence!" << std::endl;
1811                                            break;
1812                                    }
1813                                    char c2 = text.at(++i);
1814                                    if(c2 == '\'')      sb.push_back('\'');
1815                                    else if(c2 == '"')  sb.push_back('"');
1816                                    else if(c2 == '\\') sb.push_back('\\');
1817                                    else if(c2 == 'r')  sb.push_back('\r');
1818                                    else if(c2 == 'n')  sb.push_back('\n');
1819                                    else std::cerr << "Unknown escape sequence \\" << c2 << std::endl;
1820                            } else {
1821                                    sb.push_back(c);
1822                            }
1823            }
1824            return sb;
1825        }
1826        
1827      String InstrumentsDb::toEscapedFsPath(String FsPath) {      String InstrumentsDb::toEscapedFsPath(String FsPath) {
1828          return toEscapedText(FsPath);          return toEscapedText(FsPath);
1829      }      }
1830            
1831        String InstrumentsDb::toNonEscapedFsPath(String FsPath) {
1832            return toNonEscapedText(FsPath);
1833        }
1834        
1835      String InstrumentsDb::toAbstractName(String DbName) {      String InstrumentsDb::toAbstractName(String DbName) {
1836          for (int i = 0; i < DbName.length(); i++) {          for (int i = 0; i < DbName.length(); i++) {
1837              if (DbName.at(i) == '/') DbName.at(i) = '\0';              if (DbName.at(i) == '/') DbName.at(i) = '\0';
# Line 1727  namespace LinuxSampler { Line 1882  namespace LinuxSampler {
1882      }      }
1883    
1884  } // namespace LinuxSampler  } // namespace LinuxSampler
   
 #endif // HAVE_SQLITE3  

Legend:
Removed from v.1350  
changed lines
  Added in v.1781

  ViewVC Help
Powered by ViewVC