Hi,
I've been working with the InstrumentsDb code in LS, to make it actually
work in Windows. I think I've succeeded with this, see the attached
patch. It turned out that the win32 code that Benno copied from
somewhere and put in File.cpp was very buggy. I replaced it with MinGW
dirent.h calls plus an own implementation of WalkDirectory. In
InstrumentDb I had to do some small changes to convert from \ to / at
the right places.
However, when I tested this I run into different problems which I don't
think are because of my patch. I'm not sure, but I think that some of
them may be bugs in Fantasia rather than in LS.
My test case is that I choose "Add Instruments/From Directory..." in the
Instrument Database window, and there choose a directory with a lot of
files, deep structure, but only one single gig file.
Problems:
1) The "Scanning..." dialog seems to disappear too early. The scanning
thread first counts all gig files, and then traverses all files again to
actually scan the gig files. After it has scanned my single gig file I
guess Fantasia closes the dialog as all gig files are done. But the
traversing of the file system continues by the background thread. If I
then do some operation in Fantasia, like "Format database" for example,
I can get into trouble as the background thread is still doing it's
thing. This is the least important problem I guess.
2) Rather often the "Scanning..." dialog doesn't disappear, instead an
"Updating the database instruments" dialog appears and never goes away.
I have debugged lscp on LS side, and it looks like it does what it
should - it sends the notifications and it answers all lscp requests. My
theory is that there are some problems with notification handling in
Fantasia here. This happens often, but not every time.
3) One single time the "Scanning..." dialog didn't disappear. I think
one thread in LS were stuck waiting for a mutex. This was before I added
all debugging printouts so I don't know which mutex it was. I haven't
been able to reproduce this. A theory is that I because of 1) started a
scanning before the previous one was finished.
4) A "Retrieving status" dialog appears and never goes away. This is
similar to 2). I see in the debug printouts that LS has answered all
lscp requests.
I did most of the testing on windows, just a little on Linux. I know
4) happens on Linux, don't know about the others.
So, do you have any ideas? Do you think there could be a problem in how
Fantasia handles the lscp responses and notifications during a
instrumentdb directory import?
/Andreas
Index: linuxsampler/src/common/File.cpp
===================================================================
RCS file: /var/cvs/linuxsampler/linuxsampler/src/common/File.cpp,v
retrieving revision 1.6
diff -u -2 -r1.6 File.cpp
--- linuxsampler/src/common/File.cpp 6 Jun 2009 13:50:36 -0000 1.6
+++ linuxsampler/src/common/File.cpp 12 Jul 2009 04:48:16 -0000
@@ -1,5 +1,5 @@
/***************************************************************************
* *
- * Copyright (C) 2008 Grigor Iliev, Benno Senoner *
+ * Copyright (C) 2008 - 2009 Grigor Iliev, Benno Senoner *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -25,4 +25,5 @@
#include <sstream>
#include <sys/stat.h>
+#include <dirent.h>
#include "Exception.h"
@@ -30,425 +31,15 @@
#if WIN32
-
-/*
-dirent.c
-POSIX WIN32 Directory Browsing parts
-Copyright (C) 2005 OpenAsthra
-blogs.openasthra AT gmail.com
-modifications copyright 2009 by Benno Senoner
-Licence: LGPL
-*/
-
-#include "dirent.h"
-#include <errno.h>
-#include <io.h>
-#include <stdlib.h>
-#include <string.h>
-
-struct DIR
-{
- long handle;
- long int pos;
- struct _finddata_t info;
- struct dirent d_ent;
-};
-
-//aux functions
-static int StripRegEx(char *name);
-static int PreOrderTraversal(DIR *dirp, int (*fn) (const char *fpath, const
struct stat *sb, int typeflag));
-static int CallFn(int (*fn) (const char *fpath, const struct stat *sb, int
typeflag), char *dirpath, DIR *dirp);
-
-
-//posix directory browsing API implementation
-
-DIR *opendir(const char *name)
-{
- DIR *dir = NULL;
- const char *all;
- long len;
-
- if((NULL == name) || ('\0' == *name))
- {
- errno = EINVAL;
- return dir;
- }
-
- len = strlen(name);
- all = strchr("/\\", name[len - 1]) ? "*" : "/*";
-
- len += strlen(all) + 1;
-
- dir = (DIR *) malloc((len*sizeof(char)) + sizeof(*dir));
- if(NULL == dir)
- {
- errno = ENOMEM;
- return NULL;
- }
-
- dir->d_ent.d_namlen = len;
- dir->pos = 0;
- strcpy(dir->d_ent.d_name, name);
- strcat(dir->d_ent.d_name, all);
- dir->handle = (long) _findfirst(dir->d_ent.d_name, &dir->info);
- if(dir->handle == -1)
- {
- free(dir);
- dir = NULL;
- }
-
- return dir;
-}
-
-int closedir(DIR *dir)
-{
- int result = -1;
-
- if(dir)
- {
- if(dir->handle != -1)
- {
- result = _findclose(dir->handle);
- }
- free(dir);
- }
-
- if(result == -1)
- {
- errno = EBADF;
- }
-
- return result;
-}
-
-struct dirent *readdir(DIR *dir)
-{
- struct dirent *result = 0;
-
- if(dir && dir->handle != -1)
- {
- if(_findnext(dir->handle, &dir->info) != -1)
- {
- result = &dir->d_ent;
- strcpy(result->d_name, dir->info.name);
- result->d_type = DT_REG;
- if(dir->info.attrib & _A_SUBDIR) result->d_type = DT_DIR;
- dir->pos ++;
- }
- }
- else
- {
- errno = EBADF;
- }
-
- return result;
-}
-
-void rewinddir(DIR *dir)
-{
- if(dir && dir->handle != -1)
- {
- _findclose(dir->handle);
- dir->handle = (long) _findfirst(dir->d_ent.d_name, &dir->info);
- dir->pos = 0;
- }
- else
- {
- errno = EBADF;
- }
-}
-
-int dirfd(DIR *dirp)
-{
- if (NULL == dirp)
- {
- return -1;
- }
-
- return dirp->handle;
-}
-
-void seekdir (DIR *dirp, long int pos)
-{
- long int i;
-
- if (NULL == dirp)
- {
- return;
- }
-
- if (pos < 0)
- {
- pos = dirp->pos + pos;
- _findclose(dirp->handle);
- dirp->handle = (long) _findfirst(dirp->d_ent.d_name, &dirp->info);
- }
-
- for (i=0; i<pos; i++)
- {
- if(_findnext(dirp->handle, &dirp->info) != -1)
- {
- dirp->pos ++;
- }
- else
- {
- break;
- }
- }
-
-}
-
-
-long int telldir (DIR *dirp)
-{
- if (NULL == dirp)
- {
- return -1;
- }
-
- return dirp->pos;
-
-}
-
-
-int scandir(const char *dir, struct dirent ***namelist,
- int (*filter)(const struct dirent *),
- int (*compar)(const struct dirent **, const struct dirent **))
-{
- struct dirent *result = 0;
- struct dirent **namlist;
- int namelistlen = 0;
- int num_enrties= 0;
-
- DIR *dirp = opendir(dir);
-
- if (NULL == dirp)
- {
- return -1;
- }
-
- if(dirp && dirp->handle != -1)
- {
- while(_findnext(dirp->handle, &dirp->info) != -1)
- {
- num_enrties++;
- }
- }
-
- rewinddir(dirp);
-
- namlist = (struct dirent **) malloc(num_enrties * sizeof(struct dirent *));
-
- if (NULL == namlist)
- {
- closedir(dirp);
- return namelistlen;
- }
-
- if(dirp && dirp->handle != -1)
- {
- while(_findnext(dirp->handle, &dirp->info) != -1)
- {
- result = (struct dirent *) malloc(sizeof(struct dirent) +
strlen(dirp->info.name) + 1);
- strcpy(result->d_name, dirp->info.name);
- result->d_type = DT_REG;
- if(dirp->info.attrib & _A_SUBDIR) result->d_type = DT_DIR;
- if (filter)
- {
- if (filter(result))
- {
- namlist[namelistlen] = result;
- namelistlen++;
- }
- }
- else
- {
- namlist[namelistlen] = result;
- namelistlen++;
- }
- }
- }
-
- //qdirsort(namlist, namelistlen, compar); //todo
-
- *namelist = namlist;
-
- closedir(dirp);
-
- return namelistlen;
-}
-
-int ftw(const char *dirpath,
- int (*fn) (const char *fpath, const struct stat *sb,
- int typeflag),
- int nopenfd)
-{
- struct dirent *result = 0;
- struct dirent **namlist;
- int namelistlen = 0;
- int num_enrties= 0;
- struct stat sb;
- int typeflag = 0;
-
- DIR *dirp = opendir(dirpath);
-
- if (NULL == dirp)
- {
- return -1;
- }
-
-
- if (CallFn(fn, (char *)dirpath, dirp))
- {
- closedir(dirp);
- return 0;
- }
-
- if(dirp && (dirp->handle != -1))
- {
- while(_findnext(dirp->handle, &dirp->info) != -1)
- {
- if ((dirp->info.attrib & _A_SUBDIR) &&
- (strcmp(dirp->info.name, ".")) && (strcmp(dirp->info.name, "..")))
- {
- if (PreOrderTraversal(dirp, fn)>0)
- {
- break;
- }
- }
- else
- {
- if (CallFn(fn, dirp->info.name, dirp))
- {
- break;
- }
- }
- }
- }
-
- closedir(dirp);
- return 0;
-
-}
-
-//aux functions
-int StripRegEx(char *name)
-{
- char *t = strstr(name, "/*");
- if (t)
- {
- *t='\0';
- }
- else
- {
- t = strstr(name, "\\*");
- if (t)
- {
- *t='\0';
- }
- }
-
- return 0;
-}
-
-int CallFn(int (*fn) (const char *fpath, const struct stat *sb,
- int typeflag), char *dirpath, DIR *dirp)
-{
- struct stat sb;
- int typeflag = 0;
-
- if (fn)
- {
- stat(dirpath, &sb);
- if (dirp->info.attrib & _A_SUBDIR)
- {
- typeflag = FTW_D;
- }
- else
- {
- typeflag = FTW_F;
- }
- return fn(dirpath, &sb, typeflag);
- }
- return 0;
-}
-
-
-int PreOrderTraversal(DIR *dirp, int (*fn) (const char *fpath, const struct
stat *sb, int typeflag))
-{
- DIR *dirp2;
- struct stat sb;
- int typeflag = 0;
- char *tmpdirnam;
-
- StripRegEx(dirp->d_ent.d_name);
-
- tmpdirnam = (char
*)malloc(strlen(dirp->d_ent.d_name)+strlen(dirp->info.name)+2);
- if (!tmpdirnam)
- {
- return -1;
- }
-
- strcpy(tmpdirnam, dirp->d_ent.d_name);
- strcat(tmpdirnam, "/");
- strcat(tmpdirnam, dirp->info.name);
-
- dirp2 = opendir(tmpdirnam);
-
- if (NULL == dirp2)
- {
- free(tmpdirnam);
- return -1;
- }
-
- if (CallFn(fn, tmpdirnam, dirp2))
- {
- free(tmpdirnam);
- closedir(dirp2);
- return 1;
- }
-
- while(_findnext(dirp2->handle, &dirp2->info) != -1)
- {
- if (strcmp(dirp2->info.name, ".."))
- {
- if ((dirp2->info.attrib & _A_SUBDIR) && strcmp(dirp2->info.name, ".")
&& strcmp(dirp2->info.name, ".."))
- {
- if (PreOrderTraversal(dirp2, fn))
- {
- free(tmpdirnam);
- closedir(dirp2);
- return 1;
- }
- }
- else
- {
- if (CallFn(fn, dirp2->info.name, dirp2))
- {
- free(tmpdirnam);
- closedir(dirp2);
- return 1;
- }
- }
- } /*if (strcmp(dirp2->info.name, ".."))*/
- }
-
- free(tmpdirnam);
- closedir(dirp2);
- return 0;
-
-}
-
-/* end of POSIX WIN32 Directory Browsing dirent.c implementation */
-
-
+#include <windows.h>
#else
-#include <dirent.h>
#include <ftw.h>
#endif
namespace LinuxSampler {
-
+#ifdef WIN32
+ char File::DirSeparator = '\\';
+#else
char File::DirSeparator = '/';
-
+#endif
Mutex File::DirectoryWalkerMutex;
std::vector<File::DirectoryWalker*> File::DirectoryWalkers;
@@ -499,10 +90,14 @@
struct dirent* pEnt = readdir(pDir);
while (pEnt != NULL) {
- if (pEnt->d_type != DT_REG) {
- pEnt = readdir(pDir);
- continue;
- }
-
+#ifdef _DIRENT_HAVE_D_TYPE
+ if (pEnt->d_type == DT_REG) {
fileList->push_back(std::string(pEnt->d_name));
+ }
+#else
+ struct stat s;
+ if (stat((Dir + DirSeparator + pEnt->d_name).c_str(), &s) == 0 &&
S_ISREG(s.st_mode)) {
+ fileList->push_back(std::string(pEnt->d_name));
+ }
+#endif
pEnt = readdir(pDir);
}
@@ -523,5 +118,7 @@
if(!f.Exist()) throw Exception("Fail to stat `" + Dir + "`: " +
f.GetErrorMsg());
if(!f.IsDirectory()) throw Exception("The specified path is not a
directory: " + Dir);
-
+#ifdef WIN32
+ WalkDirectoryTreeSub(Dir, pWalker);
+#else
DirectoryWalkerMutex.Lock();
DirectoryWalkers.push_back(pWalker);
@@ -535,7 +132,35 @@
DirectoryWalkers.pop_back();
if (DirectoryWalkers.size() == 0) DirectoryWalkerMutex.Unlock();
+#endif
}
-
+#ifdef WIN32
+ void File::WalkDirectoryTreeSub(String Dir, DirectoryWalker* pWalker) {
+ dmsg(2,("File: WalkDirectoryTreeSub(Dir=%s)\n", Dir.c_str()));
+ DWORD attrs = GetFileAttributes(Dir.c_str());
+ if (attrs == INVALID_FILE_ATTRIBUTES) return;
+
+ if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
+ pWalker->DirectoryEntry(Dir);
+
+ std::string::size_type l = Dir.length() - 1;
+ if (Dir[l] == '/') Dir[l] = '\\';
+ else if (Dir[l] != '\\') Dir += '\\';
+
+ WIN32_FIND_DATA fd;
+ HANDLE h = FindFirstFile((Dir + "*").c_str(), &fd);
+ if (h == INVALID_HANDLE_VALUE) return;
+ do {
+ if (strcmp(fd.cFileName, ".") != 0 &&
+ strcmp(fd.cFileName, "..") != 0) {
+ WalkDirectoryTreeSub(Dir + fd.cFileName, pWalker);
+ }
+ } while (FindNextFile(h, &fd));
+ FindClose(h);
+ } else {
+ pWalker->FileEntry(Dir);
+ }
+ }
+#else
int File::FtwCallback(const char* fpath, const struct stat* sb, int
typeflag) {
dmsg(2,("File: FtwCallback(fpath=%s)\n", fpath));
@@ -550,4 +175,5 @@
return 0;
- };
+ }
+#endif
}
Index: linuxsampler/src/common/File.h
===================================================================
RCS file: /var/cvs/linuxsampler/linuxsampler/src/common/File.h,v
retrieving revision 1.6
diff -u -2 -r1.6 File.h
--- linuxsampler/src/common/File.h 6 Jun 2009 13:50:36 -0000 1.6
+++ linuxsampler/src/common/File.h 12 Jul 2009 04:48:16 -0000
@@ -1,5 +1,5 @@
/***************************************************************************
* *
- * Copyright (C) 2008 Grigor Iliev, Benno Senoner *
+ * Copyright (C) 2008 - 2009 Grigor Iliev, Benno Senoner *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -27,72 +27,5 @@
#include "Mutex.h"
-
-#if WIN32
-
-/*
-dirent.h
-POSIX WIN32 Directory Browsing parts
-Copyright (C) 2005 OpenAsthra
-blogs.openasthra AT gmail.com
-modifications copyright 2009 by Benno Senoner
-Licence: LGPL
-*/
-
-#ifndef _DIRENT_H_
-#define _DIRENT_H_
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-typedef struct DIR DIR;
-
-struct dirent{
- long d_ino;
- long d_off;
- unsigned short d_reclen;
- unsigned char d_type;
- unsigned short d_namlen;
- char d_name[1];
-};
-
-DIR *opendir(const char *);
-int closedir(DIR *);
-struct dirent *readdir(DIR *);
-void rewinddir(DIR *);
-
-void seekdir (DIR *dirp, long int pos);
-long int telldir (DIR *dirp);
-
-int scandir(const char *dir, struct dirent ***namelist,
- int (*filter)(const struct dirent *),
- int (*compar)(const struct dirent **, const struct dirent **));
-
-int ftw(const char *dirpath,
- int (*fn) (const char *fpath, const struct stat *sb,
- int typeflag),
- int nopenfd);
-
-
-int dirfd(DIR *dirp);
-
-#define DT_DIR 4
-#define DT_REG 8
-
-#define FTW_F 0x01
-#define FTW_D 0x02
-#define FTW_DNR 0x03
-#define FTW_NS 0x04
-#define FTW_SL 0x05
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-/* end of POSIX WIN32 Directory Browsing implementation */
-
-#else
+#ifndef WIN32
#include <sys/stat.h>
#endif
@@ -168,5 +101,9 @@
struct stat Status;
+#ifdef WIN32
+ static void WalkDirectoryTreeSub(std::string Dir, DirectoryWalker*
pWalker);
+#else
static int FtwCallback(const char* fpath, const struct stat* sb,
int typeflag);
+#endif
};
}
Index: linuxsampler/src/common/Path.cpp
===================================================================
RCS file: /var/cvs/linuxsampler/linuxsampler/src/common/Path.cpp,v
retrieving revision 1.10
diff -u -2 -r1.10 Path.cpp
--- linuxsampler/src/common/Path.cpp 30 Sep 2008 02:16:41 -0000 1.10
+++ linuxsampler/src/common/Path.cpp 12 Jul 2009 04:48:16 -0000
@@ -131,4 +131,5 @@
result << "\\" << elements[iElement];
}
+ if (elements.empty()) result << '\\';
return result.str();
}
Index: linuxsampler/src/db/InstrumentsDb.cpp
===================================================================
RCS file: /var/cvs/linuxsampler/linuxsampler/src/db/InstrumentsDb.cpp,v
retrieving revision 1.21
diff -u -2 -r1.21 InstrumentsDb.cpp
--- linuxsampler/src/db/InstrumentsDb.cpp 6 Jun 2009 16:48:00 -0000
1.21
+++ linuxsampler/src/db/InstrumentsDb.cpp 12 Jul 2009 04:48:16 -0000
@@ -1226,11 +1226,4 @@
String s = FilePath;
-
- #if WIN32
- for (int i = 0; i < s.length(); i++) {
- if (s[i] == '\\') s[i] = '/';
- }
- #endif
-
s = toEscapedFsPath(s);
BindTextParam(pStmt, 2, s);
@@ -1865,9 +1858,16 @@
String InstrumentsDb::toEscapedFsPath(String FsPath) {
+#ifdef WIN32
+ replace(FsPath.begin(), FsPath.end(), '\\', '/');
+#endif
return toEscapedText(FsPath);
}
String InstrumentsDb::toNonEscapedFsPath(String FsPath) {
- return toNonEscapedText(FsPath);
+ FsPath = toNonEscapedText(FsPath);
+#ifdef WIN32
+ replace(FsPath.begin(), FsPath.end(), '/', '\\');
+#endif
+ return FsPath;
}
Index: linuxsampler/src/db/InstrumentsDbUtilities.cpp
===================================================================
RCS file: /var/cvs/linuxsampler/linuxsampler/src/db/InstrumentsDbUtilities.cpp,v
retrieving revision 1.7
diff -u -2 -r1.7 InstrumentsDbUtilities.cpp
--- linuxsampler/src/db/InstrumentsDbUtilities.cpp 1 Jun 2009 18:50:06
-0000 1.7
+++ linuxsampler/src/db/InstrumentsDbUtilities.cpp 12 Jul 2009 04:48:16
-0000
@@ -24,4 +24,5 @@
#include "../common/global_private.h"
+#include <algorithm>
#include <errno.h>
@@ -584,4 +585,7 @@
if(subdir.length() > FsDir.length()) {
subdir = subdir.substr(FsDir.length());
+#ifdef WIN32
+ replace(subdir.begin(), subdir.end(), '\\', '/');
+#endif
dir += subdir;
}
Index: linuxsampler/src/db/InstrumentsDbUtilities.h
===================================================================
RCS file: /var/cvs/linuxsampler/linuxsampler/src/db/InstrumentsDbUtilities.h,v
retrieving revision 1.6
diff -u -2 -r1.6 InstrumentsDbUtilities.h
--- linuxsampler/src/db/InstrumentsDbUtilities.h 29 Sep 2008 18:18:02
-0000 1.6
+++ linuxsampler/src/db/InstrumentsDbUtilities.h 12 Jul 2009 04:48:16
-0000
@@ -1,5 +1,5 @@
/***************************************************************************
* *
- * Copyright (C) 2007, 2008 Grigor Iliev *
+ * Copyright (C) 2007 - 2009 Grigor Iliev *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -116,5 +116,5 @@
int Status;
- ScanJob() { }
+ ScanJob() : FilesTotal(0), FilesScanned(0), Status(0) { }
ScanJob(const ScanJob& Job) { Copy(Job); }
void operator=(const ScanJob& Job) { Copy(Job); }
------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge
This is your chance to win up to $100,000 in prizes! For a limited time,
vendors submitting new applications to BlackBerry App World(TM) will have
the opportunity to enter the BlackBerry Developer Challenge. See full prize
details at: http://p.sf.net/sfu/Challenge
_______________________________________________
Linuxsampler-devel mailing list
Linuxsampler-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxsampler-devel