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

Legend:
Removed from v.1353  
changed lines
  Added in v.1944

  ViewVC Help
Powered by ViewVC