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

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

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

revision 1345 by iliev, Thu Sep 13 21:46:25 2007 UTC revision 3092 by schoenebeck, Mon Jan 16 22:02:36 2017 UTC
# Line 1  Line 1 
1  /***************************************************************************  /***************************************************************************
2   *                                                                         *   *                                                                         *
3   *   Copyright (C) 2007 Grigor Iliev                                       *   *   Copyright (C) 2007 - 2009 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 "InstrumentsDbUtilities.h"  #include "InstrumentsDbUtilities.h"
22    
23  #if HAVE_SQLITE3  #include "../common/File.h"
24    #include "../common/global_private.h"
25    
26  #include <dirent.h>  #include <algorithm>
27  #include <errno.h>  #include <errno.h>
 #include <ftw.h>  
28    
29  #include "../common/Exception.h"  #include "../common/Exception.h"
30  #include "InstrumentsDb.h"  #include "InstrumentsDb.h"
31    #include "../engines/sfz/sfz.h"
32    #if HAVE_SF2
33    # if AC_APPLE_UNIVERSAL_BUILD
34    #  include <libgig/SF.h>
35    # else
36    #  include <SF.h>
37    # endif
38    #endif // HAVE_SF2
39    
40  namespace LinuxSampler {  namespace LinuxSampler {
41    
42        class GigFileInfo : public InstrumentFileInfo {
43        public:
44            GigFileInfo(String fileName) : InstrumentFileInfo(fileName) {
45                m_gig  = NULL;
46                m_riff = NULL;
47                try {
48                    m_riff = new RIFF::File(fileName);
49                    m_gig  = new gig::File(m_riff);
50                    m_gig->SetAutoLoad(false); // avoid time consuming samples scanning
51                } catch (RIFF::Exception e) {
52                    throw Exception(e.Message);
53                } catch (...) {
54                    throw Exception("Unknown exception while accessing gig file");
55                }
56            }
57    
58            virtual ~GigFileInfo() {
59                if (m_gig)  delete m_gig;
60                if (m_riff) delete m_riff;
61            }
62    
63            String formatName() OVERRIDE {
64                return "GIG";
65            }
66    
67            String formatVersion() OVERRIDE {
68                return (m_gig->pVersion) ? ToString(m_gig->pVersion->major) : "";
69            }
70    
71            optional<InstrumentInfo> getInstrumentInfo(int index, ScanProgress* pProgress) OVERRIDE {
72                InstrumentInfo info;
73                try {
74                    ::gig::progress_t* progress = (pProgress) ? &pProgress->GigFileProgress : NULL;
75                    ::gig::Instrument* pInstrument = m_gig->GetInstrument(index, progress);
76                    if (!pInstrument)
77                        return optional<InstrumentInfo>::nothing;
78    
79                    info.instrumentName = pInstrument->pInfo->Name;
80                    info.product = (!pInstrument->pInfo->Product.empty()) ? pInstrument->pInfo->Product : m_gig->pInfo->Product;
81                    info.artists = (!pInstrument->pInfo->Artists.empty()) ? pInstrument->pInfo->Artists : m_gig->pInfo->Artists;
82                    info.keywords = (!pInstrument->pInfo->Keywords.empty()) ? pInstrument->pInfo->Keywords : m_gig->pInfo->Keywords;
83                    info.comments = (!pInstrument->pInfo->Comments.empty()) ? pInstrument->pInfo->Comments : m_gig->pInfo->Comments;
84                    info.isDrum = pInstrument->IsDrum;
85                } catch (RIFF::Exception e) {
86                    throw Exception(e.Message);
87                } catch (...) {
88                    throw Exception("Unknown exception while accessing gig file");
89                }
90                return info;
91            }
92        private:
93            ::RIFF::File* m_riff;
94            ::gig::File*  m_gig;
95        };
96    
97        class SFZFileInfo : public InstrumentFileInfo {
98        public:
99            SFZFileInfo(String fileName) : InstrumentFileInfo(fileName) {
100                m_sfz = NULL;
101                try {
102                    m_sfz = new ::sfz::File(fileName);
103                } catch (sfz::Exception e) {
104                    throw Exception(e.Message());
105                } catch (...) {
106                    throw Exception("Unknown exception while accessing sfz file");
107                }
108            }
109    
110            virtual ~SFZFileInfo() {
111                if (m_sfz) delete m_sfz;
112            }
113    
114            String formatName() OVERRIDE {
115                return "SFZ";
116            }
117    
118            String formatVersion() OVERRIDE {
119                return "";
120            }
121    
122            optional<InstrumentInfo> getInstrumentInfo(int index, ScanProgress* pProgress) OVERRIDE {
123                if (index != 0)
124                    return optional<InstrumentInfo>::nothing;
125    
126                InstrumentInfo info;
127                // yeah, lousy info, but SFZ does not provide any meta info unfortunately yet
128                return info;
129            }
130        private:
131            ::sfz::File* m_sfz;
132        };
133    
134    #if HAVE_SF2
135    
136        class Sf2FileInfo : public InstrumentFileInfo {
137        public:
138            Sf2FileInfo(String fileName) : InstrumentFileInfo(fileName) {
139                m_sf2  = NULL;
140                m_riff = NULL;
141                try {
142                    m_riff = new RIFF::File(fileName);
143                    m_sf2  = new sf2::File(m_riff);
144                } catch (RIFF::Exception e) {
145                    throw Exception(e.Message);
146                } catch (...) {
147                    throw Exception("Unknown exception while accessing sf2 file");
148                }
149            }
150    
151            virtual ~Sf2FileInfo() {
152                if (m_sf2)  delete m_sf2;
153                if (m_riff) delete m_riff;
154            }
155    
156            String formatName() OVERRIDE {
157                return "SF2";
158            }
159    
160            String formatVersion() OVERRIDE {
161                if (!m_sf2->pInfo || !m_sf2->pInfo->pVer) return "";
162                String major = ToString(m_sf2->pInfo->pVer->Major);
163                //String minor = ToString(m_sf2->pInfo->pVer->Minor);
164                //return major + "." + minor;
165                return major;
166            }
167    
168            optional<InstrumentInfo> getInstrumentInfo(int index, ScanProgress* pProgress) OVERRIDE {
169                if (index >= m_sf2->GetPresetCount())
170                    return optional<InstrumentInfo>::nothing;
171    
172                InstrumentInfo info;
173                try {
174                    ::sf2::Preset* preset = m_sf2->GetPreset(index);
175                    if (!preset)
176                        return optional<InstrumentInfo>::nothing;
177    
178                    info.instrumentName = preset->Name;
179                    if (m_sf2->pInfo) {
180                        info.product = m_sf2->pInfo->Product;
181                        info.comments = m_sf2->pInfo->Comments;
182                        info.artists = m_sf2->pInfo->Engineers;
183                    }
184                } catch (RIFF::Exception e) {
185                    throw Exception(e.Message);
186                } catch (...) {
187                    throw Exception("Unknown exception while accessing gig file");
188                }
189                return info;
190            }
191        private:
192            ::RIFF::File* m_riff;
193            ::sf2::File*  m_sf2;
194        };
195    
196    #endif // #if HAVE_SF2
197    
198      void DbInstrument::Copy(const DbInstrument& Instr) {      void DbInstrument::Copy(const DbInstrument& Instr) {
199          if (this == &Instr) return;          if (this == &Instr) return;
200    
# Line 153  namespace LinuxSampler { Line 317  namespace LinuxSampler {
317          if (Pattern.length() == 0) return;          if (Pattern.length() == 0) return;
318    
319          if (IsRegex(Pattern)) {          if (IsRegex(Pattern)) {
320    #ifndef WIN32
321              Sql << " AND " << Col << " regexp ?";              Sql << " AND " << Col << " regexp ?";
322    #else
323                for (int i = 0; i < Pattern.length(); i++) {
324                    if (Pattern.at(i) == '?') Pattern.at(i) = '_';
325                    else if (Pattern.at(i) == '*') Pattern.at(i) = '%';
326                }
327                Sql << " AND " << Col << " LIKE ?";
328    #endif
329              Params.push_back(Pattern);              Params.push_back(Pattern);
330              return;              return;
331          }          }
# Line 243  namespace LinuxSampler { Line 415  namespace LinuxSampler {
415      }      }
416    
417      StringListPtr DirectoryFinder::GetDirectories() {      StringListPtr DirectoryFinder::GetDirectories() {
418    #if __cplusplus >= 201103L && !CONFIG_NO_CPP11STL
419            return std::move(pDirectories);
420    #else
421          return pDirectories;          return pDirectories;
422    #endif
423      }      }
424            
425      void DirectoryFinder::ProcessDirectory(String Path, int DirId) {      void DirectoryFinder::ProcessDirectory(String Path, int DirId) {
# Line 356  namespace LinuxSampler { Line 532  namespace LinuxSampler {
532      }      }
533    
534      StringListPtr InstrumentFinder::GetInstruments() {      StringListPtr InstrumentFinder::GetInstruments() {
535    #if __cplusplus >= 201103L && !CONFIG_NO_CPP11STL
536            return std::move(pInstruments);
537    #else
538          return pInstruments;          return pInstruments;
539    #endif
540      }      }
541    
542      void DirectoryCounter::ProcessDirectory(String Path, int DirId) {      void DirectoryCounter::ProcessDirectory(String Path, int DirId) {
# Line 464  namespace LinuxSampler { Line 644  namespace LinuxSampler {
644          sp->SetStatus((int)(pProgress->factor * 100));          sp->SetStatus((int)(pProgress->factor * 100));
645      }      }
646    
647      AddInstrumentsJob::AddInstrumentsJob(int JobId, ScanMode Mode, String DbDir, String FsDir) {      AddInstrumentsJob::AddInstrumentsJob(int JobId, ScanMode Mode, String DbDir, String FsDir, bool insDir) {
648          this->JobId = JobId;          this->JobId = JobId;
649          Progress.JobId = JobId;          Progress.JobId = JobId;
650          this->Mode = Mode;          this->Mode = Mode;
651          this->DbDir = DbDir;          this->DbDir = DbDir;
652          this->FsDir = FsDir;          this->FsDir = FsDir;
653                    this->insDir = insDir;
654      }      }
655    
656      void AddInstrumentsJob::Run() {      void AddInstrumentsJob::Run() {
# Line 479  namespace LinuxSampler { Line 660  namespace LinuxSampler {
660              switch (Mode) {              switch (Mode) {
661                  case NON_RECURSIVE:                  case NON_RECURSIVE:
662                      Progress.SetTotalFileCount(GetFileCount());                      Progress.SetTotalFileCount(GetFileCount());
663                      db->AddInstrumentsNonrecursive(DbDir, FsDir, &Progress);                      db->AddInstrumentsNonrecursive(DbDir, FsDir, insDir, &Progress);
664                      break;                      break;
665                  case RECURSIVE:                  case RECURSIVE:
666                      db->AddInstrumentsRecursive(DbDir, FsDir, false, &Progress);                      db->AddInstrumentsRecursive(DbDir, FsDir, false, insDir, &Progress);
667                      break;                      break;
668                  case FLAT:                  case FLAT:
669                      db->AddInstrumentsRecursive(DbDir, FsDir, true, &Progress);                      db->AddInstrumentsRecursive(DbDir, FsDir, true, insDir, &Progress);
670                      break;                      break;
671                  default:                  default:
672                      throw Exception("Unknown scan mode");                      throw Exception("Unknown scan mode");
# Line 505  namespace LinuxSampler { Line 686  namespace LinuxSampler {
686      int AddInstrumentsJob::GetFileCount() {      int AddInstrumentsJob::GetFileCount() {
687          int count = 0;          int count = 0;
688    
689          DIR* pDir = opendir(FsDir.c_str());          try {
690          if (pDir == NULL) {              FileListPtr fileList = File::GetFiles(FsDir);
             std::stringstream ss;  
             ss << "The scanning of directory `" << FsDir << "` failed: ";  
             ss << strerror(errno);  
             std::cerr << ss.str();  
             return 0;  
         }  
   
         struct dirent* pEnt = readdir(pDir);  
         while (pEnt != NULL) {  
             if (pEnt->d_type != DT_REG) {  
                 pEnt = readdir(pDir);  
                 continue;  
             }  
691    
692              String s(pEnt->d_name);              for (int i = 0; i < fileList->size(); i++) {
693              if(s.length() < 4) {                  String s = fileList->at(i);
694                  pEnt = readdir(pDir);                  if (InstrumentFileInfo::isSupportedFile(s)) count++;
                 continue;  
695              }              }
696              if(!strcasecmp(".gig", s.substr(s.length() - 4).c_str())) count++;          } catch(Exception e) {
697                e.PrintMessage();
698              pEnt = readdir(pDir);              return 0;
         }  
           
         if (closedir(pDir)) {  
             std::stringstream ss;  
             ss << "Failed to close directory `" << FsDir << "`: ";  
             ss << strerror(errno);  
             std::cerr << ss.str();  
699          }          }
700                    
701          return count;          return count;
702      }      }
703    
704      AddInstrumentsFromFileJob::AddInstrumentsFromFileJob(int JobId, String DbDir, String FilePath, int Index) {      AddInstrumentsFromFileJob::AddInstrumentsFromFileJob(int JobId, String DbDir, String FilePath, int Index, bool insDir) {
705          this->JobId = JobId;          this->JobId = JobId;
706          Progress.JobId = JobId;          Progress.JobId = JobId;
707          Progress.SetTotalFileCount(1);          Progress.SetTotalFileCount(1);
# Line 549  namespace LinuxSampler { Line 709  namespace LinuxSampler {
709          this->DbDir = DbDir;          this->DbDir = DbDir;
710          this->FilePath = FilePath;          this->FilePath = FilePath;
711          this->Index = Index;          this->Index = Index;
712                    this->insDir = insDir;
713      }      }
714    
715      void AddInstrumentsFromFileJob::Run() {      void AddInstrumentsFromFileJob::Run() {
716          try {          try {
717              InstrumentsDb::GetInstrumentsDb()->AddInstruments(DbDir, FilePath, Index, &Progress);              InstrumentsDb::GetInstrumentsDb()->AddInstruments(DbDir, insDir, FilePath, Index, &Progress);
718    
719              // Just to be sure that the frontends will be notified about the job completion              // Just to be sure that the frontends will be notified about the job completion
720              if (Progress.GetTotalFileCount() != Progress.GetScannedFileCount()) {              if (Progress.GetTotalFileCount() != Progress.GetScannedFileCount()) {
# Line 567  namespace LinuxSampler { Line 728  namespace LinuxSampler {
728      }      }
729    
730    
731      String DirectoryScanner::DbDir;      void DirectoryScanner::Scan(String DbDir, String FsDir, bool Flat, bool insDir, ScanProgress* pProgress) {
732      String DirectoryScanner::FsDir;          dmsg(2,("DirectoryScanner: Scan(DbDir=%s,FsDir=%s,Flat=%d,insDir=%d)\n", DbDir.c_str(), FsDir.c_str(), Flat, insDir));
     bool DirectoryScanner::Flat;  
     ScanProgress* DirectoryScanner::pProgress;  
   
     void DirectoryScanner::Scan(String DbDir, String FsDir, bool Flat, ScanProgress* pProgress) {  
         dmsg(2,("DirectoryScanner: Scan(DbDir=%s,FsDir=%s,Flat=%d)\n", DbDir.c_str(), FsDir.c_str(), Flat));  
733          if (DbDir.empty() || FsDir.empty()) throw Exception("Directory expected");          if (DbDir.empty() || FsDir.empty()) throw Exception("Directory expected");
734                    
735          struct stat statBuf;          this->DbDir = DbDir;
736          int res = stat(FsDir.c_str(), &statBuf);          this->FsDir = FsDir;
737          if (res) {          this->insDir = insDir;
             std::stringstream ss;  
             ss << "Fail to stat `" << FsDir << "`: " << strerror(errno);  
             throw Exception(ss.str());  
         }  
   
         if (!S_ISDIR(statBuf.st_mode)) {  
             throw Exception("Directory expected");  
         }  
           
         DirectoryScanner::DbDir = DbDir;  
         DirectoryScanner::FsDir = FsDir;  
738          if (DbDir.at(DbDir.length() - 1) != '/') {          if (DbDir.at(DbDir.length() - 1) != '/') {
739              DirectoryScanner::DbDir.append("/");              this->DbDir.append("/");
740          }          }
741          if (FsDir.at(FsDir.length() - 1) != '/') {          if (FsDir.at(FsDir.length() - 1) != File::DirSeparator) {
742              DirectoryScanner::FsDir.append("/");              this->FsDir.push_back(File::DirSeparator);
743          }          }
744          DirectoryScanner::Flat = Flat;          this->Flat = Flat;
745          DirectoryScanner::pProgress = pProgress;          this->pProgress = pProgress;
746                    
747          ftw(FsDir.c_str(), FtwCallback, 10);          File::WalkDirectoryTree(FsDir, this);
748      }      }
749    
750      int DirectoryScanner::FtwCallback(const char* fpath, const struct stat* sb, int typeflag) {      void DirectoryScanner::DirectoryEntry(std::string Path) {
751          dmsg(2,("DirectoryScanner: FtwCallback(fpath=%s)\n", fpath));          dmsg(2,("DirectoryScanner: DirectoryEntry(Path=%s)\n", Path.c_str()));
         if (typeflag != FTW_D) return 0;  
752    
753          String dir = DbDir;          String dir = DbDir;
754          if (!Flat) {          if (!Flat) {
755              String subdir = fpath;              String subdir = Path;
756              if(subdir.length() > FsDir.length()) {              if(subdir.length() > FsDir.length()) {
757                  subdir = subdir.substr(FsDir.length());                  subdir = subdir.substr(FsDir.length());
758    #ifdef WIN32
759                    replace(subdir.begin(), subdir.end(), '\\', '/');
760    #endif
761                  dir += subdir;                  dir += subdir;
762              }              }
763          }          }
764                    
765          InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();          InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
766    
767          if (HasInstrumentFiles(String(fpath))) {          if (HasInstrumentFiles(Path)) {
768              if (!db->DirectoryExist(dir)) db->AddDirectory(dir);              if (!db->DirectoryExist(dir)) db->AddDirectory(dir);
769              db->AddInstrumentsNonrecursive(dir, String(fpath), pProgress);              db->AddInstrumentsNonrecursive(dir, Path, insDir, pProgress);
770          }          }
   
         return 0;  
771      };      };
772    
773      bool DirectoryScanner::HasInstrumentFiles(String Dir) {      bool DirectoryScanner::HasInstrumentFiles(String Dir) {
774          return InstrumentFileCounter::Count(Dir) > 0;          InstrumentFileCounter c;
775            return c.Count(Dir) > 0;
776      }      }
777    
     int InstrumentFileCounter::FileCount;  
   
778      int InstrumentFileCounter::Count(String FsDir) {      int InstrumentFileCounter::Count(String FsDir) {
779          dmsg(2,("InstrumentFileCounter: Count(FsDir=%s)\n", FsDir.c_str()));          dmsg(2,("InstrumentFileCounter: Count(FsDir=%s)\n", FsDir.c_str()));
780          if (FsDir.empty()) throw Exception("Directory expected");          if (FsDir.empty()) throw Exception("Directory expected");
781          FileCount = 0;          FileCount = 0;
782    
783          struct stat statBuf;          File::WalkDirectoryTree(FsDir, this);
         int res = stat(FsDir.c_str(), &statBuf);  
         if (res) {  
             std::stringstream ss;  
             ss << "Fail to stat `" << FsDir << "`: " << strerror(errno);  
             throw Exception(ss.str());  
         }  
   
         if (!S_ISDIR(statBuf.st_mode)) {  
             throw Exception("Directory expected");  
         }  
           
         ftw(FsDir.c_str(), FtwCallback, 10);  
784          return FileCount;          return FileCount;
785      }      }
786    
787      int InstrumentFileCounter::FtwCallback(const char* fpath, const struct stat* sb, int typeflag) {      void InstrumentFileCounter::FileEntry(std::string Path) {
788          if (typeflag != FTW_F) return 0;          dmsg(2,("InstrumentFileCounter: FileEntry(Path=%s)\n", Path.c_str()));
789          String s = fpath;          if (InstrumentFileInfo::isSupportedFile(Path)) FileCount++;
         if(s.length() < 4) return 0;  
         if(!strcasecmp(".gig", s.substr(s.length() - 4).c_str())) FileCount++;  
   
         return 0;  
790      };      };
791    
 } // namespace LinuxSampler  
792    
793  #endif // HAVE_SQLITE3      InstrumentFileInfo* InstrumentFileInfo::getFileInfoFor(String filename) {
794            if (filename.length() < 4) return NULL;
795            String fileExtension = filename.substr(filename.length() - 4);
796            if (!strcasecmp(".gig", fileExtension.c_str()))
797                return new GigFileInfo(filename);
798            if (!strcasecmp(".sfz", fileExtension.c_str()))
799                return new SFZFileInfo(filename);
800            #if HAVE_SF2
801            if (!strcasecmp(".sf2", fileExtension.c_str()))
802                return new Sf2FileInfo(filename);
803            #endif
804            return NULL;
805        }
806    
807        bool InstrumentFileInfo::isSupportedFile(String filename) {
808            if (filename.length() < 4) return false;
809            String fileExtension = filename.substr(filename.length() - 4);
810            if (!strcasecmp(".gig", fileExtension.c_str())) return true;
811            if (!strcasecmp(".sfz", fileExtension.c_str())) return true;
812            #if HAVE_SF2
813            if (!strcasecmp(".sf2", fileExtension.c_str())) return true;
814            #endif
815            return false;
816        }
817    
818    } // namespace LinuxSampler

Legend:
Removed from v.1345  
changed lines
  Added in v.3092

  ViewVC Help
Powered by ViewVC