annotate src/vamp-hostsdk/Files.cpp @ 501:90571dcc371a vamp-kiss-naming

Extensively rename things in the KissFFT headers to use a Vamp prefix. The motivation is not to change anything about the Vamp SDK library builds, but to avoid confusion in case any other code (for example that pulls in the Vamp SDK as part of a wider project definition) accidentally includes these headers instead of, or as well as, some other copy of KissFFT.
author Chris Cannam
date Tue, 30 Jan 2018 09:56:46 +0000
parents 628a5b8ff634
children 54277cb679ff
rev   line source
Chris@390 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@390 2
Chris@390 3 /*
Chris@390 4 Vamp
Chris@390 5
Chris@390 6 An API for audio analysis and feature extraction plugins.
Chris@390 7
Chris@390 8 Centre for Digital Music, Queen Mary, University of London.
Chris@390 9 Copyright 2006-2015 Chris Cannam and QMUL.
Chris@390 10
Chris@390 11 Permission is hereby granted, free of charge, to any person
Chris@390 12 obtaining a copy of this software and associated documentation
Chris@390 13 files (the "Software"), to deal in the Software without
Chris@390 14 restriction, including without limitation the rights to use, copy,
Chris@390 15 modify, merge, publish, distribute, sublicense, and/or sell copies
Chris@390 16 of the Software, and to permit persons to whom the Software is
Chris@390 17 furnished to do so, subject to the following conditions:
Chris@390 18
Chris@390 19 The above copyright notice and this permission notice shall be
Chris@390 20 included in all copies or substantial portions of the Software.
Chris@390 21
Chris@390 22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Chris@390 23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Chris@390 24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Chris@390 25 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
Chris@390 26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
Chris@390 27 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
Chris@390 28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Chris@390 29
Chris@390 30 Except as contained in this notice, the names of the Centre for
Chris@390 31 Digital Music; Queen Mary, University of London; and Chris Cannam
Chris@390 32 shall not be used in advertising or otherwise to promote the sale,
Chris@390 33 use or other dealings in this Software without prior written
Chris@390 34 authorization.
Chris@390 35 */
Chris@390 36
Chris@390 37 #include <vamp-hostsdk/PluginHostAdapter.h>
Chris@390 38
Chris@390 39 #include "Files.h"
Chris@390 40
Chris@390 41 #include <cctype> // tolower
Chris@390 42
Chris@390 43 #include <cstring>
Chris@390 44
Chris@390 45 #ifdef _WIN32
Chris@390 46
Chris@390 47 #include <windows.h>
Chris@390 48 #include <tchar.h>
Chris@390 49 #define PLUGIN_SUFFIX "dll"
Chris@390 50
Chris@390 51 #else /* ! _WIN32 */
Chris@390 52
Chris@390 53 #include <dirent.h>
Chris@390 54 #include <dlfcn.h>
Chris@390 55
Chris@390 56 #ifdef __APPLE__
Chris@390 57 #define PLUGIN_SUFFIX "dylib"
Chris@390 58 #else /* ! __APPLE__ */
Chris@390 59 #define PLUGIN_SUFFIX "so"
Chris@390 60 #endif /* ! __APPLE__ */
Chris@390 61
Chris@390 62 #endif /* ! _WIN32 */
Chris@390 63
Chris@390 64 using namespace std;
Chris@390 65
Chris@390 66 vector<string>
Chris@390 67 Files::listLibraryFiles()
Chris@390 68 {
Chris@477 69 return listLibraryFilesMatching(Filter());
Chris@390 70 }
Chris@390 71
Chris@390 72 vector<string>
Chris@473 73 Files::listLibraryFilesMatching(Filter filter)
Chris@390 74 {
Chris@390 75 vector<string> path = Vamp::PluginHostAdapter::getPluginPath();
Chris@390 76 vector<string> libraryFiles;
Chris@390 77
Chris@421 78 // we match case-insensitively, but only with ascii range
Chris@473 79 // characters (input strings are expected to be utf-8)
Chris@473 80 vector<string> libraryNames;
Chris@477 81 for (int j = 0; j < int(filter.libraryNames.size()); ++j) {
Chris@477 82 string n = filter.libraryNames[j];
Chris@473 83 for (size_t i = 0; i < n.length(); ++i) {
Chris@473 84 if (!(n[i] & 0x80)) {
Chris@473 85 n[i] = char(tolower(n[i]));
Chris@473 86 }
Chris@421 87 }
Chris@473 88 libraryNames.push_back(n);
Chris@390 89 }
Chris@390 90
Chris@390 91 for (size_t i = 0; i < path.size(); ++i) {
Chris@390 92
Chris@390 93 vector<string> files = listFiles(path[i], PLUGIN_SUFFIX);
Chris@390 94
Chris@390 95 for (vector<string>::iterator fi = files.begin();
Chris@390 96 fi != files.end(); ++fi) {
Chris@473 97
Chris@473 98 // we match case-insensitively, but only with ascii range
Chris@473 99 // characters (this string is expected to be utf-8)
Chris@473 100 string cleaned = *fi;
Chris@477 101 for (size_t j = 0; j < cleaned.length(); ++j) {
Chris@477 102 if (!(cleaned[j] & 0x80)) {
Chris@477 103 cleaned[j] = char(tolower(cleaned[j]));
Chris@390 104 }
Chris@390 105 }
Chris@390 106
Chris@473 107 // libraryName should be lacking an extension, as it is
Chris@473 108 // supposed to have come from the plugin key
Chris@473 109 string::size_type pi = cleaned.find('.');
Chris@473 110 if (pi != string::npos) {
Chris@473 111 cleaned = cleaned.substr(0, pi);
Chris@473 112 }
Chris@473 113
Chris@473 114 bool matched = false;
Chris@473 115
Chris@473 116 switch (filter.type) {
Chris@473 117
Chris@473 118 case Filter::All:
Chris@473 119 matched = true;
Chris@473 120 break;
Chris@473 121
Chris@473 122 case Filter::Matching:
Chris@477 123 for (int j = 0; j < int(libraryNames.size()); ++j) {
Chris@477 124 if (cleaned == libraryNames[j]) {
Chris@473 125 matched = true;
Chris@473 126 break;
Chris@473 127 }
Chris@473 128 }
Chris@473 129 break;
Chris@473 130
Chris@473 131 case Filter::NotMatching:
Chris@473 132 matched = true;
Chris@477 133 for (int j = 0; j < int(libraryNames.size()); ++j) {
Chris@477 134 if (cleaned == libraryNames[j]) {
Chris@473 135 matched = false;
Chris@473 136 break;
Chris@473 137 }
Chris@473 138 }
Chris@473 139 break;
Chris@473 140 }
Chris@473 141
Chris@473 142 if (!matched) continue;
Chris@473 143
Chris@390 144 string fullPath = path[i];
Chris@390 145 fullPath = splicePath(fullPath, *fi);
Chris@390 146 libraryFiles.push_back(fullPath);
Chris@390 147 }
Chris@390 148 }
Chris@390 149
Chris@390 150 return libraryFiles;
Chris@390 151 }
Chris@390 152
Chris@390 153 void *
Chris@390 154 Files::loadLibrary(string path)
Chris@390 155 {
Chris@390 156 void *handle = 0;
Chris@390 157 #ifdef _WIN32
Chris@390 158 #ifdef UNICODE
Chris@472 159 int wlen = MultiByteToWideChar(CP_UTF8, 0, path.c_str(), path.length(), 0, 0);
Chris@472 160 if (wlen < 0) {
Chris@390 161 cerr << "Vamp::HostExt: Unable to convert library path \""
Chris@390 162 << path << "\" to wide characters " << endl;
Chris@390 163 return handle;
Chris@390 164 }
Chris@472 165 wchar_t *buffer = new wchar_t[wlen+1];
Chris@472 166 (void)MultiByteToWideChar(CP_UTF8, 0, path.c_str(), path.length(), buffer, wlen);
Chris@472 167 buffer[wlen] = L'\0';
Chris@390 168 handle = LoadLibrary(buffer);
Chris@390 169 delete[] buffer;
Chris@390 170 #else
Chris@390 171 handle = LoadLibrary(path.c_str());
Chris@390 172 #endif
Chris@390 173 if (!handle) {
Chris@390 174 cerr << "Vamp::HostExt: Unable to load library \""
Chris@390 175 << path << "\"" << endl;
Chris@390 176 }
Chris@390 177 #else
Chris@390 178 handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL);
Chris@390 179 if (!handle) {
Chris@390 180 cerr << "Vamp::HostExt: Unable to load library \""
Chris@390 181 << path << "\": " << dlerror() << endl;
Chris@390 182 }
Chris@390 183 #endif
Chris@390 184 return handle;
Chris@390 185 }
Chris@390 186
Chris@390 187 void
Chris@390 188 Files::unloadLibrary(void *handle)
Chris@390 189 {
Chris@390 190 #ifdef _WIN32
Chris@390 191 FreeLibrary((HINSTANCE)handle);
Chris@390 192 #else
Chris@390 193 dlclose(handle);
Chris@390 194 #endif
Chris@390 195 }
Chris@390 196
Chris@390 197 void *
Chris@390 198 Files::lookupInLibrary(void *handle, const char *symbol)
Chris@390 199 {
Chris@390 200 #ifdef _WIN32
Chris@390 201 return (void *)GetProcAddress((HINSTANCE)handle, symbol);
Chris@390 202 #else
Chris@390 203 return (void *)dlsym(handle, symbol);
Chris@390 204 #endif
Chris@390 205 }
Chris@390 206
Chris@390 207 string
Chris@390 208 Files::lcBasename(string path)
Chris@390 209 {
Chris@390 210 string basename(path);
Chris@390 211
Chris@390 212 string::size_type li = basename.rfind('/');
Chris@390 213 if (li != string::npos) basename = basename.substr(li + 1);
Chris@390 214
Chris@403 215 #ifdef _WIN32
Chris@405 216 li = basename.rfind('\\');
Chris@403 217 if (li != string::npos) basename = basename.substr(li + 1);
Chris@403 218 #endif
Chris@403 219
Chris@390 220 li = basename.find('.');
Chris@390 221 if (li != string::npos) basename = basename.substr(0, li);
Chris@390 222
Chris@421 223 // case-insensitive, but only with ascii range characters (this
Chris@421 224 // string is expected to be utf-8)
Chris@390 225 for (size_t i = 0; i < basename.length(); ++i) {
Chris@421 226 if (!(basename[i] & 0x80)) {
Chris@421 227 basename[i] = char(tolower(basename[i]));
Chris@421 228 }
Chris@390 229 }
Chris@390 230
Chris@390 231 return basename;
Chris@390 232 }
Chris@390 233
Chris@390 234 string
Chris@390 235 Files::splicePath(string a, string b)
Chris@390 236 {
Chris@390 237 #ifdef _WIN32
Chris@390 238 return a + "\\" + b;
Chris@390 239 #else
Chris@390 240 return a + "/" + b;
Chris@390 241 #endif
Chris@390 242 }
Chris@390 243
Chris@390 244 vector<string>
Chris@390 245 Files::listFiles(string dir, string extension)
Chris@390 246 {
Chris@390 247 vector<string> files;
Chris@390 248
Chris@390 249 #ifdef _WIN32
Chris@390 250 string expression = dir + "\\*." + extension;
Chris@390 251 #ifdef UNICODE
Chris@472 252 int wlen = MultiByteToWideChar(CP_UTF8, 0, expression.c_str(), expression.length(), 0, 0);
Chris@472 253 if (wlen < 0) {
Chris@390 254 cerr << "Vamp::HostExt: Unable to convert wildcard path \""
Chris@390 255 << expression << "\" to wide characters" << endl;
Chris@390 256 return files;
Chris@390 257 }
Chris@472 258 wchar_t *buffer = new wchar_t[wlen+1];
Chris@472 259 (void)MultiByteToWideChar(CP_UTF8, 0, expression.c_str(), expression.length(), buffer, wlen);
Chris@472 260 buffer[wlen] = L'\0';
Chris@390 261 WIN32_FIND_DATA data;
Chris@390 262 HANDLE fh = FindFirstFile(buffer, &data);
Chris@390 263 if (fh == INVALID_HANDLE_VALUE) {
Chris@390 264 delete[] buffer;
Chris@390 265 return files;
Chris@390 266 }
Chris@390 267
Chris@390 268 bool ok = true;
Chris@390 269 while (ok) {
Chris@390 270 wchar_t *fn = data.cFileName;
Chris@472 271 int wlen = wcslen(fn);
Chris@472 272 int len = WideCharToMultiByte(CP_UTF8, 0, fn, wlen, 0, 0, 0, 0);
Chris@472 273 if (len < 0) {
Chris@472 274 cerr << "Vamp::HostExt: Unable to convert wide char filename to utf-8" << endl;
Chris@472 275 break;
Chris@472 276 }
Chris@472 277 char *conv = new char[len+1];
Chris@472 278 (void)WideCharToMultiByte(CP_UTF8, 0, fn, wlen, conv, len, 0, 0);
Chris@472 279 conv[len] = '\0';
Chris@472 280 if (len > 0) {
Chris@390 281 files.push_back(conv);
Chris@390 282 }
Chris@390 283 delete[] conv;
Chris@390 284 ok = FindNextFile(fh, &data);
Chris@390 285 }
Chris@390 286
Chris@390 287 FindClose(fh);
Chris@390 288 delete[] buffer;
Chris@390 289 #else
Chris@390 290 WIN32_FIND_DATA data;
Chris@390 291 HANDLE fh = FindFirstFile(expression.c_str(), &data);
Chris@390 292 if (fh == INVALID_HANDLE_VALUE) return files;
Chris@390 293
Chris@390 294 bool ok = true;
Chris@390 295 while (ok) {
Chris@390 296 files.push_back(data.cFileName);
Chris@390 297 ok = FindNextFile(fh, &data);
Chris@390 298 }
Chris@390 299
Chris@390 300 FindClose(fh);
Chris@390 301 #endif
Chris@390 302 #else
Chris@390 303
Chris@390 304 size_t extlen = extension.length();
Chris@390 305 DIR *d = opendir(dir.c_str());
Chris@390 306 if (!d) return files;
Chris@390 307
Chris@390 308 struct dirent *e = 0;
Chris@390 309 while ((e = readdir(d))) {
Chris@390 310
Chris@390 311 size_t len = strlen(e->d_name);
Chris@390 312 if (len < extlen + 2 ||
Chris@390 313 e->d_name + len - extlen - 1 != "." + extension) {
Chris@390 314 continue;
Chris@390 315 }
Chris@390 316
Chris@390 317 files.push_back(e->d_name);
Chris@390 318 }
Chris@390 319
Chris@390 320 closedir(d);
Chris@390 321 #endif
Chris@390 322
Chris@390 323 return files;
Chris@390 324 }