aboutsummaryrefslogtreecommitdiffstats
path: root/Alc
diff options
context:
space:
mode:
Diffstat (limited to 'Alc')
-rw-r--r--Alc/helpers.c547
-rw-r--r--Alc/hrtf.c49
2 files changed, 115 insertions, 481 deletions
diff --git a/Alc/helpers.c b/Alc/helpers.c
index c98f121f..20cd8900 100644
--- a/Alc/helpers.c
+++ b/Alc/helpers.c
@@ -476,301 +476,69 @@ void al_print(const char *type, const char *func, const char *fmt, ...)
static inline int is_slash(int c)
{ return (c == '\\' || c == '/'); }
-static size_t strlenW(const WCHAR *str)
-{
- const WCHAR *end = str;
- while(*end) ++end;
- return end-str;
-}
-
-static const WCHAR *strchrW(const WCHAR *str, WCHAR ch)
-{
- for(;*str != 0;++str)
- {
- if(*str == ch)
- return str;
- }
- return NULL;
-}
-
-static const WCHAR *strrchrW(const WCHAR *str, WCHAR ch)
-{
- const WCHAR *ret = NULL;
- for(;*str != 0;++str)
- {
- if(*str == ch)
- ret = str;
- }
- return ret;
-}
-
-static const WCHAR *strstrW(const WCHAR *haystack, const WCHAR *needle)
-{
- size_t len = strlenW(needle);
- while(*haystack != 0)
- {
- if(CompareStringW(GetThreadLocale(), NORM_IGNORECASE,
- haystack, len, needle, len) == CSTR_EQUAL)
- return haystack;
-
- do {
- ++haystack;
- } while(((*haystack)&0xC000) == 0x8000);
- }
- return NULL;
-}
-
-
-/* Compares the filename in the find data with the match string. The match
- * string may contain the "%r" marker to signifiy a sample rate (really any
- * positive integer), "%%" to signify a single '%', or "%s" for a (non-greedy)
- * string.
- */
-static int MatchFilter(const WCHAR *match, const WIN32_FIND_DATAW *fdata)
-{
- const WCHAR *name = fdata->cFileName;
- int ret = 1;
-
- do {
- const WCHAR *p = strchrW(match, '%');
- if(!p)
- ret = CompareStringW(GetThreadLocale(), NORM_IGNORECASE,
- match, -1, name, -1) == CSTR_EQUAL;
- else
- {
- int len = p-match;
- ret = lstrlenW(name) >= len;
- if(ret)
- ret = CompareStringW(GetThreadLocale(), NORM_IGNORECASE,
- match, len, name, len) == CSTR_EQUAL;
- if(ret)
- {
- match += len;
- name += len;
-
- ++p;
- if(*p == 'r')
- {
- unsigned long l = 0;
- while(*name >= '0' && *name <= '9')
- {
- l = l*10 + (*name-'0');
- ++name;
- }
- ret = l > 0;
- ++p;
- }
- else if(*p == 's')
- {
- const WCHAR *next = p+1;
- if(*next != '\0' && *next != '%')
- {
- const WCHAR *next_p = strchrW(next, '%');
- const WCHAR *m;
-
- if(!next_p)
- m = strstrW(name, next);
- else
- {
- WCHAR *tmp = malloc((next_p - next + 1) * 2);
- memcpy(tmp, next, (next_p - next) * 2);
- tmp[next_p - next] = 0;
-
- m = strstrW(name, tmp);
-
- free(tmp);
- }
-
- ret = !!m;
- if(ret)
- {
- size_t l;
- if(next_p) l = next_p - next;
- else l = strlenW(next);
-
- name = m + l;
- next += l;
- }
- }
- p = next;
- }
- }
- }
-
- match = p;
- } while(ret && match && *match);
-
- return ret;
-}
-
-static void RecurseDirectorySearch(const char *path, const WCHAR *match, vector_al_string *results)
+static void DirectorySearch(const char *path, const char *ext, vector_al_string *results)
{
+ al_string pathstr = AL_STRING_INIT_STATIC();
WIN32_FIND_DATAW fdata;
- const WCHAR *sep, *p;
+ WCHAR *wpath;
HANDLE hdl;
- if(!match[0])
- return;
-
- /* Find the last directory separator and the next '%' marker in the match
- * string. */
- sep = strrchrW(match, '\\');
- p = strchrW(match, '%');
-
- /* If there's no separator, test the files in the specified path against
- * the match string, and add the results. */
- if(!sep)
- {
- al_string pathstr = AL_STRING_INIT_STATIC();
- WCHAR *wpath;
-
- TRACE("Searching %s for %ls\n", path, match);
-
- al_string_append_cstr(&pathstr, path);
- al_string_append_cstr(&pathstr, "\\*.*");
- wpath = FromUTF8(al_string_get_cstr(pathstr));
-
- hdl = FindFirstFileW(wpath, &fdata);
- if(hdl != INVALID_HANDLE_VALUE)
- {
- size_t base = VECTOR_SIZE(*results);
- do {
- if(MatchFilter(match, &fdata))
- {
- al_string str = AL_STRING_INIT_STATIC();
- al_string_copy_cstr(&str, path);
- al_string_append_char(&str, '\\');
- al_string_append_wcstr(&str, fdata.cFileName);
- TRACE("Got result %s\n", al_string_get_cstr(str));
- VECTOR_PUSH_BACK(*results, str);
- }
- } while(FindNextFileW(hdl, &fdata));
- FindClose(hdl);
-
- if(VECTOR_SIZE(*results) > base)
- qsort(VECTOR_ITER_BEGIN(*results)+base, VECTOR_SIZE(*results)-base,
- sizeof(VECTOR_FRONT(*results)), StringSortCompare);
- }
+ al_string_copy_cstr(&pathstr, path);
+ al_string_append_cstr(&pathstr, "\\*");
+ al_string_append_cstr(&pathstr, ext);
- free(wpath);
- al_string_deinit(&pathstr);
+ TRACE("Searching %s\n", al_string_get_cstr(pathstr));
- return;
- }
+ wpath = FromUTF8(al_string_get_cstr(pathstr));
- /* If there's no '%' marker, or it's after the final separator, append the
- * remaining directories to the path and recurse into it with the remaining
- * filename portion. */
- if(!p || p-sep >= 0)
+ hdl = FindFirstFileW(wpath, &fdata);
+ if(hdl != INVALID_HANDLE_VALUE)
{
- al_string npath = AL_STRING_INIT_STATIC();
- al_string_append_cstr(&npath, path);
- al_string_append_char(&npath, '\\');
- al_string_append_wrange(&npath, match, sep);
-
- TRACE("Recursing into %s with %ls\n", al_string_get_cstr(npath), sep+1);
- RecurseDirectorySearch(al_string_get_cstr(npath), sep+1, results);
+ size_t base = VECTOR_SIZE(*results);
+ do {
+ al_string str = AL_STRING_INIT_STATIC();
+ al_string_copy_cstr(&str, path);
+ al_string_append_char(&str, '\\');
+ al_string_append_wcstr(&str, fdata.cFileName);
+ TRACE("Got result %s\n", al_string_get_cstr(str));
+ VECTOR_PUSH_BACK(*results, str);
+ } while(FindNextFileW(hdl, &fdata));
+ FindClose(hdl);
- al_string_deinit(&npath);
- return;
+ if(VECTOR_SIZE(*results) > base)
+ qsort(VECTOR_ITER_BEGIN(*results)+base, VECTOR_SIZE(*results)-base,
+ sizeof(VECTOR_FRONT(*results)), StringSortCompare);
}
- /* Look for the last separator before the '%' marker, and the first
- * separator after it. */
- sep = strchrW(match, '\\');
- if(sep-p >= 0) sep = NULL;
- for(;;)
- {
- const WCHAR *next = strchrW(sep?sep+1:match, '\\');
- if(next-p < 0)
- {
- al_string npath = AL_STRING_INIT_STATIC();
- WCHAR *nwpath, *nwmatch;
-
- /* Append up to the last directory before the one with a '%'. */
- al_string_copy_cstr(&npath, path);
- if(sep)
- {
- al_string_append_char(&npath, '\\');
- al_string_append_wrange(&npath, match, sep);
- }
- al_string_append_cstr(&npath, "\\*.*");
- nwpath = FromUTF8(al_string_get_cstr(npath));
-
- /* Take the directory name containing a '%' as a new string to
- * match against. */
- if(!sep)
- {
- nwmatch = calloc(2, next-match+1);
- memcpy(nwmatch, match, (next-match)*2);
- }
- else
- {
- nwmatch = calloc(2, next-(sep+1)+1);
- memcpy(nwmatch, sep+1, (next-(sep+1))*2);
- }
-
- /* For each matching directory name, recurse into it with the
- * remaining string. */
- TRACE("Searching %s for %ls\n", al_string_get_cstr(npath), nwmatch);
- hdl = FindFirstFileW(nwpath, &fdata);
- if(hdl != INVALID_HANDLE_VALUE)
- {
- do {
- if(MatchFilter(nwmatch, &fdata))
- {
- al_string ndir = AL_STRING_INIT_STATIC();
- al_string_copy(&ndir, npath);
- al_string_append_char(&ndir, '\\');
- al_string_append_wcstr(&ndir, fdata.cFileName);
- TRACE("Recursing %s with %ls\n", al_string_get_cstr(ndir), next+1);
- RecurseDirectorySearch(al_string_get_cstr(ndir), next+1, results);
- al_string_deinit(&ndir);
- }
- } while(FindNextFileW(hdl, &fdata));
- FindClose(hdl);
- }
-
- free(nwmatch);
- free(nwpath);
- al_string_deinit(&npath);
- break;
- }
- sep = next;
- }
+ free(wpath);
+ al_string_deinit(&pathstr);
}
-vector_al_string SearchDataFiles(const char *match, const char *subdir)
+vector_al_string SearchDataFiles(const char *ext, const char *subdir)
{
static const int ids[2] = { CSIDL_APPDATA, CSIDL_COMMON_APPDATA };
static RefCount search_lock;
vector_al_string results = VECTOR_INIT_STATIC();
- WCHAR *wmatch;
size_t i;
while(ATOMIC_EXCHANGE(uint, &search_lock, 1) == 1)
althrd_yield();
- wmatch = FromUTF8(match);
- if(!wmatch)
- {
- ERR("Failed to convert UTF-8 filename: \"%s\"\n", match);
- return results;
- }
- for(i = 0;wmatch[i];++i)
- {
- if(wmatch[i] == '/')
- wmatch[i] = '\\';
- }
-
/* If the path is absolute, use it directly. */
- if(isalpha(wmatch[0]) && wmatch[1] == ':' && is_slash(wmatch[2]))
+ if(isalpha(subdir[0]) && subdir[1] == ':' && is_slash(subdir[2]))
{
- char drv[3] = { (char)wmatch[0], ':', 0 };
- RecurseDirectorySearch(drv, wmatch+3, &results);
+ al_string path = AL_STRING_INIT_STATIC();
+ al_string_copy_cstr(&path, subdir);
+#define FIX_SLASH(i) do { if(*(i) == '/') *(i) = '\\'; } while(0)
+ VECTOR_FOR_EACH(char, path, FIX_SLASH);
+#undef FIX_SLASH
+
+ DirectorySearch(al_string_get_cstr(path), ext, &results);
+
+ al_string_deinit(&path);
}
- else if(wmatch[0] == '\\' && wmatch[1] == '\\' && wmatch[2] == '?' && wmatch[3] == '\\')
- RecurseDirectorySearch("\\\\?", wmatch+4, &results);
+ else if(subdir[0] == '\\' && subdir[1] == '\\' && subdir[2] == '?' && subdir[3] == '\\')
+ DirectorySearch(subdir, ext, &results);
else
{
al_string path = AL_STRING_INIT_STATIC();
@@ -801,7 +569,7 @@ vector_al_string SearchDataFiles(const char *match, const char *subdir)
#define FIX_SLASH(i) do { if(*(i) == '/') *(i) = '\\'; } while(0)
VECTOR_FOR_EACH(char, path, FIX_SLASH);
#undef FIX_SLASH
- RecurseDirectorySearch(al_string_get_cstr(path), wmatch, &results);
+ DirectorySearch(al_string_get_cstr(path), ext, &results);
/* Search the local and global data dirs. */
for(i = 0;i < COUNTOF(ids);i++)
@@ -817,14 +585,13 @@ vector_al_string SearchDataFiles(const char *match, const char *subdir)
VECTOR_FOR_EACH(char, path, FIX_SLASH);
#undef FIX_SLASH
- RecurseDirectorySearch(al_string_get_cstr(path), wmatch, &results);
+ DirectorySearch(al_string_get_cstr(path), ext, &results);
}
}
al_string_deinit(&path);
}
- free(wmatch);
ATOMIC_STORE(&search_lock, 0);
return results;
@@ -877,192 +644,46 @@ void al_print(const char *type, const char *func, const char *fmt, ...)
}
-static int MatchFilter(const char *name, const char *match)
-{
- int ret = 1;
-
- do {
- const char *p = strchr(match, '%');
- if(!p)
- ret = strcmp(match, name) == 0;
- else
- {
- size_t len = p-match;
- ret = strncmp(match, name, len) == 0;
- if(ret)
- {
- match += len;
- name += len;
-
- ++p;
- if(*p == 'r')
- {
- char *end;
- ret = strtoul(name, &end, 10) > 0;
- if(ret) name = end;
- ++p;
- }
- else if(*p == 's')
- {
- const char *next = p+1;
- if(*next != '\0' && *next != '%')
- {
- const char *next_p = strchr(next, '%');
- const char *m;
-
- if(!next_p)
- m = strstr(name, next);
- else
- {
- char *tmp = malloc(next_p - next + 1);
- memcpy(tmp, next, next_p - next);
- tmp[next_p - next] = 0;
-
- m = strstr(name, tmp);
-
- free(tmp);
- }
-
- ret = !!m;
- if(ret)
- {
- size_t l;
- if(next_p) l = next_p - next;
- else l = strlen(next);
-
- name = m + l;
- next += l;
- }
- }
- p = next;
- }
- }
- }
-
- match = p;
- } while(ret && match && *match);
-
- return ret;
-}
-
-static void RecurseDirectorySearch(const char *path, const char *match, vector_al_string *results)
+static void DirectorySearch(const char *path, const char *ext, vector_al_string *results)
{
- char *sep, *p;
-
- if(!match[0])
- return;
-
- sep = strrchr(match, '/');
- p = strchr(match, '%');
-
- if(!sep)
- {
- DIR *dir;
-
- TRACE("Searching %s for %s\n", path?path:"/", match);
- dir = opendir(path?path:"/");
- if(dir != NULL)
- {
- size_t base = VECTOR_SIZE(*results);
- struct dirent *dirent;
- while((dirent=readdir(dir)) != NULL)
- {
- al_string str;
- if(strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0 ||
- !MatchFilter(dirent->d_name, match))
- continue;
-
- AL_STRING_INIT(str);
- if(path) al_string_copy_cstr(&str, path);
- al_string_append_char(&str, '/');
- al_string_append_cstr(&str, dirent->d_name);
- TRACE("Got result %s\n", al_string_get_cstr(str));
- VECTOR_PUSH_BACK(*results, str);
- }
- closedir(dir);
-
- if(VECTOR_SIZE(*results) > base)
- qsort(VECTOR_ITER_BEGIN(*results)+base, VECTOR_SIZE(*results)-base,
- sizeof(VECTOR_FRONT(*results)), StringSortCompare);
- }
-
- return;
- }
-
- if(!p || p-sep >= 0)
- {
- al_string npath = AL_STRING_INIT_STATIC();
- if(path) al_string_append_cstr(&npath, path);
- al_string_append_char(&npath, '/');
- al_string_append_range(&npath, match, sep);
-
- TRACE("Recursing into %s with %s\n", al_string_get_cstr(npath), sep+1);
- RecurseDirectorySearch(al_string_get_cstr(npath), sep+1, results);
-
- al_string_deinit(&npath);
- return;
- }
+ size_t extlen = strlen(ext);
+ DIR *dir;
- sep = strchr(match, '/');
- if(sep-p >= 0) sep = NULL;
- for(;;)
+ TRACE("Searching %s for *%s\n", path, ext);
+ dir = opendir(path);
+ if(dir != NULL)
{
- char *next = strchr(sep?sep+1:match, '/');
- if(next-p < 0)
+ size_t base = VECTOR_SIZE(*results);
+ struct dirent *dirent;
+ while((dirent=readdir(dir)) != NULL)
{
- al_string npath = AL_STRING_INIT_STATIC();
- al_string nmatch = AL_STRING_INIT_STATIC();
- const char *tomatch;
- DIR *dir;
-
- if(!sep)
- {
- al_string_append_cstr(&npath, path?path:"/.");
- tomatch = match;
- }
- else
- {
- if(path) al_string_append_cstr(&npath, path);
- al_string_append_char(&npath, '/');
- al_string_append_range(&npath, match, sep);
-
- al_string_append_range(&nmatch, sep+1, next);
- tomatch = al_string_get_cstr(nmatch);
- }
-
- TRACE("Searching %s for %s\n", al_string_get_cstr(npath), tomatch);
- dir = opendir(path?path:"/");
- if(dir != NULL)
- {
- al_string ndir = AL_STRING_INIT_STATIC();
- struct dirent *dirent;
-
- while((dirent=readdir(dir)) != NULL)
- {
- if(strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0 ||
- !MatchFilter(dirent->d_name, tomatch))
- continue;
- al_string_copy(&ndir, npath);
- al_string_append_char(&ndir, '/');
- al_string_append_cstr(&ndir, dirent->d_name);
- TRACE("Recursing %s with %s\n", al_string_get_cstr(ndir), next+1);
- RecurseDirectorySearch(al_string_get_cstr(ndir), next+1, results);
- }
- closedir(dir);
-
- al_string_deinit(&ndir);
- }
-
- al_string_deinit(&nmatch);
- al_string_deinit(&npath);
- break;
+ al_string str;
+ size_t len;
+ if(strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0)
+ continue;
+
+ len = strlen(dirent->d_name);
+ if(!(len > extlen))
+ continue;
+ if(strcasecmp(dirent->d_name+len-extlen, ext) != 0)
+ continue;
+
+ AL_STRING_INIT(str);
+ al_string_copy_cstr(&str, path);
+ al_string_append_char(&str, '/');
+ al_string_append_cstr(&str, dirent->d_name);
+ TRACE("Got result %s\n", al_string_get_cstr(str));
+ VECTOR_PUSH_BACK(*results, str);
}
+ closedir(dir);
- sep = next;
+ if(VECTOR_SIZE(*results) > base)
+ qsort(VECTOR_ITER_BEGIN(*results)+base, VECTOR_SIZE(*results)-base,
+ sizeof(VECTOR_FRONT(*results)), StringSortCompare);
}
}
-vector_al_string SearchDataFiles(const char *match, const char *subdir)
+vector_al_string SearchDataFiles(const char *ext, const char *subdir)
{
static RefCount search_lock;
vector_al_string results = VECTOR_INIT_STATIC();
@@ -1070,8 +691,8 @@ vector_al_string SearchDataFiles(const char *match, const char *subdir)
while(ATOMIC_EXCHANGE(uint, &search_lock, 1) == 1)
althrd_yield();
- if(match[0] == '/')
- RecurseDirectorySearch(NULL, match+1, &results);
+ if(subdir[0] == '/')
+ DirectorySearch(subdir, ext, &results);
else
{
al_string path = AL_STRING_INIT_STATIC();
@@ -1080,29 +701,27 @@ vector_al_string SearchDataFiles(const char *match, const char *subdir)
/* Search the app-local directory. */
if((str=getenv("ALSOFT_LOCAL_PATH")) && *str != '\0')
- {
- strncpy(cwdbuf, str, sizeof(cwdbuf)-1);
- cwdbuf[sizeof(cwdbuf)-1] = '\0';
- }
- else if(!getcwd(cwdbuf, sizeof(cwdbuf)))
- strcpy(cwdbuf, ".");
- RecurseDirectorySearch(cwdbuf, match, &results);
+ DirectorySearch(str, ext, &results);
+ else if(getcwd(cwdbuf, sizeof(cwdbuf)))
+ DirectorySearch(cwdbuf, ext, &results);
+ else
+ DirectorySearch(".", ext, &results);
// Search local data dir
if((str=getenv("XDG_DATA_HOME")) != NULL && str[0] != '\0')
{
- al_string_append_cstr(&path, str);
+ al_string_copy_cstr(&path, str);
al_string_append_char(&path, '/');
al_string_append_cstr(&path, subdir);
+ DirectorySearch(al_string_get_cstr(path), ext, &results);
}
else if((str=getenv("HOME")) != NULL && str[0] != '\0')
{
- al_string_append_cstr(&path, str);
+ al_string_copy_cstr(&path, str);
al_string_append_cstr(&path, "/.local/share/");
al_string_append_cstr(&path, subdir);
+ DirectorySearch(al_string_get_cstr(path), ext, &results);
}
- if(!al_string_empty(path))
- RecurseDirectorySearch(al_string_get_cstr(path), match, &results);
// Search global data dirs
if((str=getenv("XDG_DATA_DIRS")) == NULL || str[0] == '\0')
@@ -1125,7 +744,7 @@ vector_al_string SearchDataFiles(const char *match, const char *subdir)
al_string_append_char(&path, '/');
al_string_append_cstr(&path, subdir);
- RecurseDirectorySearch(al_string_get_cstr(path), match, &results);
+ DirectorySearch(al_string_get_cstr(path), ext, &results);
}
}
diff --git a/Alc/hrtf.c b/Alc/hrtf.c
index beb67e76..eeb4be41 100644
--- a/Alc/hrtf.c
+++ b/Alc/hrtf.c
@@ -603,43 +603,58 @@ done:
vector_HrtfEntry EnumerateHrtf(const_al_string devname)
{
vector_HrtfEntry list = VECTOR_INIT_STATIC();
- const char *fnamelist = "%s.mhr";
const char *defaulthrtf = "";
+ const char *pathlist = "";
+ bool usedefaults = true;
- ConfigValueStr(al_string_get_cstr(devname), NULL, "hrtf_tables", &fnamelist);
- while(fnamelist && *fnamelist)
+ if(ConfigValueStr(al_string_get_cstr(devname), NULL, "hrtf-paths", &pathlist))
{
- while(isspace(*fnamelist) || *fnamelist == ',')
- fnamelist++;
- if(*fnamelist != '\0')
+ while(pathlist && *pathlist)
{
const char *next, *end;
- next = strchr(fnamelist, ',');
- if(!next)
- end = fnamelist + strlen(fnamelist);
- else
+ while(isspace(*pathlist) || *pathlist == ',')
+ pathlist++;
+ if(*pathlist == '\0')
+ continue;
+
+ next = strchr(pathlist, ',');
+ if(next)
end = next++;
+ else
+ {
+ end = pathlist + strlen(pathlist);
+ usedefaults = false;
+ }
- while(end != fnamelist && isspace(*(end-1)))
+ while(end != pathlist && isspace(*(end-1)))
--end;
- if(end != fnamelist)
+ if(end != pathlist)
{
- al_string fname = AL_STRING_INIT_STATIC();
+ al_string pname = AL_STRING_INIT_STATIC();
vector_al_string flist;
- al_string_append_range(&fname, fnamelist, end);
+ al_string_append_range(&pname, pathlist, end);
- flist = SearchDataFiles(al_string_get_cstr(fname), "openal/hrtf");
+ flist = SearchDataFiles(".mhr", al_string_get_cstr(pname));
VECTOR_FOR_EACH_PARAMS(al_string, flist, AddFileEntry, &list);
VECTOR_DEINIT(flist);
- al_string_deinit(&fname);
+ al_string_deinit(&pname);
}
- fnamelist = next;
+ pathlist = next;
}
}
+ else if(ConfigValueExists(al_string_get_cstr(devname), NULL, "hrtf_tables"))
+ ERR("The hrtf_tables option is deprecated, please use hrtf-paths instead.\n");
+
+ if(usedefaults)
+ {
+ vector_al_string flist = SearchDataFiles(".mhr", "openal/hrtf");
+ VECTOR_FOR_EACH_PARAMS(al_string, flist, AddFileEntry, &list);
+ VECTOR_DEINIT(flist);
+ }
if(VECTOR_SIZE(list) > 1 && ConfigValueStr(al_string_get_cstr(devname), NULL, "default-hrtf", &defaulthrtf))
{