annotate src/vamp-hostsdk/Files.cpp @ 415:1522e2f6d700

Fix handling of output sample rate in buffering adapter in case where SampleType is Fixed but no sample rate provided (which is invalid behaviour from the plugin, but we might as well do the right thing with it)
author Chris Cannam
date Fri, 04 Sep 2015 13:48:28 +0100
parents b7268e8bd292
children 35fa4733bc5d
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@390 69 return listLibraryFilesMatching("");
Chris@390 70 }
Chris@390 71
Chris@390 72 vector<string>
Chris@390 73 Files::listLibraryFilesMatching(string libraryName)
Chris@390 74 {
Chris@390 75 vector<string> path = Vamp::PluginHostAdapter::getPluginPath();
Chris@390 76 vector<string> libraryFiles;
Chris@390 77
Chris@390 78 // we match case-insensitively
Chris@390 79 for (size_t i = 0; i < libraryName.length(); ++i) {
Chris@390 80 libraryName[i] = tolower(libraryName[i]);
Chris@390 81 }
Chris@390 82
Chris@390 83 for (size_t i = 0; i < path.size(); ++i) {
Chris@390 84
Chris@390 85 vector<string> files = listFiles(path[i], PLUGIN_SUFFIX);
Chris@390 86
Chris@390 87 for (vector<string>::iterator fi = files.begin();
Chris@390 88 fi != files.end(); ++fi) {
Chris@390 89
Chris@390 90 if (libraryName != "") {
Chris@390 91 // we match case-insensitively
Chris@390 92 string temp = *fi;
Chris@390 93 for (size_t i = 0; i < temp.length(); ++i) {
Chris@390 94 temp[i] = tolower(temp[i]);
Chris@390 95 }
Chris@390 96 // libraryName should be lacking an extension, as it
Chris@390 97 // is supposed to have come from the plugin key
Chris@390 98 string::size_type pi = temp.find('.');
Chris@390 99 if (pi == string::npos) {
Chris@390 100 if (libraryName != temp) continue;
Chris@390 101 } else {
Chris@390 102 if (libraryName != temp.substr(0, pi)) continue;
Chris@390 103 }
Chris@390 104 }
Chris@390 105
Chris@390 106 string fullPath = path[i];
Chris@390 107 fullPath = splicePath(fullPath, *fi);
Chris@390 108 libraryFiles.push_back(fullPath);
Chris@390 109 }
Chris@390 110 }
Chris@390 111
Chris@390 112 return libraryFiles;
Chris@390 113 }
Chris@390 114
Chris@390 115 void *
Chris@390 116 Files::loadLibrary(string path)
Chris@390 117 {
Chris@390 118 void *handle = 0;
Chris@390 119 #ifdef _WIN32
Chris@390 120 #ifdef UNICODE
Chris@390 121 int len = path.length() + 1; // cannot be more wchars than length in bytes of utf8 string
Chris@390 122 wchar_t *buffer = new wchar_t[len];
Chris@390 123 int rv = MultiByteToWideChar(CP_UTF8, 0, path.c_str(), len, buffer, len);
Chris@390 124 if (rv <= 0) {
Chris@390 125 cerr << "Vamp::HostExt: Unable to convert library path \""
Chris@390 126 << path << "\" to wide characters " << endl;
Chris@390 127 delete[] buffer;
Chris@390 128 return handle;
Chris@390 129 }
Chris@390 130 handle = LoadLibrary(buffer);
Chris@390 131 delete[] buffer;
Chris@390 132 #else
Chris@390 133 handle = LoadLibrary(path.c_str());
Chris@390 134 #endif
Chris@390 135 if (!handle) {
Chris@390 136 cerr << "Vamp::HostExt: Unable to load library \""
Chris@390 137 << path << "\"" << endl;
Chris@390 138 }
Chris@390 139 #else
Chris@390 140 handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL);
Chris@390 141 if (!handle) {
Chris@390 142 cerr << "Vamp::HostExt: Unable to load library \""
Chris@390 143 << path << "\": " << dlerror() << endl;
Chris@390 144 }
Chris@390 145 #endif
Chris@390 146 return handle;
Chris@390 147 }
Chris@390 148
Chris@390 149 void
Chris@390 150 Files::unloadLibrary(void *handle)
Chris@390 151 {
Chris@390 152 #ifdef _WIN32
Chris@390 153 FreeLibrary((HINSTANCE)handle);
Chris@390 154 #else
Chris@390 155 dlclose(handle);
Chris@390 156 #endif
Chris@390 157 }
Chris@390 158
Chris@390 159 void *
Chris@390 160 Files::lookupInLibrary(void *handle, const char *symbol)
Chris@390 161 {
Chris@390 162 #ifdef _WIN32
Chris@390 163 return (void *)GetProcAddress((HINSTANCE)handle, symbol);
Chris@390 164 #else
Chris@390 165 return (void *)dlsym(handle, symbol);
Chris@390 166 #endif
Chris@390 167 }
Chris@390 168
Chris@390 169 string
Chris@390 170 Files::lcBasename(string path)
Chris@390 171 {
Chris@390 172 string basename(path);
Chris@390 173
Chris@390 174 string::size_type li = basename.rfind('/');
Chris@390 175 if (li != string::npos) basename = basename.substr(li + 1);
Chris@390 176
Chris@403 177 #ifdef _WIN32
Chris@405 178 li = basename.rfind('\\');
Chris@403 179 if (li != string::npos) basename = basename.substr(li + 1);
Chris@403 180 #endif
Chris@403 181
Chris@390 182 li = basename.find('.');
Chris@390 183 if (li != string::npos) basename = basename.substr(0, li);
Chris@390 184
Chris@390 185 for (size_t i = 0; i < basename.length(); ++i) {
Chris@390 186 basename[i] = tolower(basename[i]);
Chris@390 187 }
Chris@390 188
Chris@390 189 return basename;
Chris@390 190 }
Chris@390 191
Chris@390 192 string
Chris@390 193 Files::splicePath(string a, string b)
Chris@390 194 {
Chris@390 195 #ifdef _WIN32
Chris@390 196 return a + "\\" + b;
Chris@390 197 #else
Chris@390 198 return a + "/" + b;
Chris@390 199 #endif
Chris@390 200 }
Chris@390 201
Chris@390 202 vector<string>
Chris@390 203 Files::listFiles(string dir, string extension)
Chris@390 204 {
Chris@390 205 vector<string> files;
Chris@390 206
Chris@390 207 #ifdef _WIN32
Chris@390 208 string expression = dir + "\\*." + extension;
Chris@390 209 #ifdef UNICODE
Chris@390 210 int len = expression.length() + 1; // cannot be more wchars than length in bytes of utf8 string
Chris@390 211 wchar_t *buffer = new wchar_t[len];
Chris@390 212 int rv = MultiByteToWideChar(CP_UTF8, 0, expression.c_str(), len, buffer, len);
Chris@390 213 if (rv <= 0) {
Chris@390 214 cerr << "Vamp::HostExt: Unable to convert wildcard path \""
Chris@390 215 << expression << "\" to wide characters" << endl;
Chris@390 216 delete[] buffer;
Chris@390 217 return files;
Chris@390 218 }
Chris@390 219 WIN32_FIND_DATA data;
Chris@390 220 HANDLE fh = FindFirstFile(buffer, &data);
Chris@390 221 if (fh == INVALID_HANDLE_VALUE) {
Chris@390 222 delete[] buffer;
Chris@390 223 return files;
Chris@390 224 }
Chris@390 225
Chris@390 226 bool ok = true;
Chris@390 227 while (ok) {
Chris@390 228 wchar_t *fn = data.cFileName;
Chris@390 229 int wlen = wcslen(fn) + 1;
Chris@390 230 int maxlen = wlen * 6;
Chris@390 231 char *conv = new char[maxlen];
Chris@390 232 int rv = WideCharToMultiByte(CP_UTF8, 0, fn, wlen, conv, maxlen, 0, 0);
Chris@390 233 if (rv > 0) {
Chris@390 234 files.push_back(conv);
Chris@390 235 }
Chris@390 236 delete[] conv;
Chris@390 237 ok = FindNextFile(fh, &data);
Chris@390 238 }
Chris@390 239
Chris@390 240 FindClose(fh);
Chris@390 241 delete[] buffer;
Chris@390 242 #else
Chris@390 243 WIN32_FIND_DATA data;
Chris@390 244 HANDLE fh = FindFirstFile(expression.c_str(), &data);
Chris@390 245 if (fh == INVALID_HANDLE_VALUE) return files;
Chris@390 246
Chris@390 247 bool ok = true;
Chris@390 248 while (ok) {
Chris@390 249 files.push_back(data.cFileName);
Chris@390 250 ok = FindNextFile(fh, &data);
Chris@390 251 }
Chris@390 252
Chris@390 253 FindClose(fh);
Chris@390 254 #endif
Chris@390 255 #else
Chris@390 256
Chris@390 257 size_t extlen = extension.length();
Chris@390 258 DIR *d = opendir(dir.c_str());
Chris@390 259 if (!d) return files;
Chris@390 260
Chris@390 261 struct dirent *e = 0;
Chris@390 262 while ((e = readdir(d))) {
Chris@390 263
Chris@390 264 size_t len = strlen(e->d_name);
Chris@390 265 if (len < extlen + 2 ||
Chris@390 266 e->d_name + len - extlen - 1 != "." + extension) {
Chris@390 267 continue;
Chris@390 268 }
Chris@390 269
Chris@390 270 files.push_back(e->d_name);
Chris@390 271 }
Chris@390 272
Chris@390 273 closedir(d);
Chris@390 274 #endif
Chris@390 275
Chris@390 276 return files;
Chris@390 277 }