To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / src / vamp-hostsdk / Files.cpp @ 535:45b2bd15d8ae

History | View | Annotate | Download (11.5 KB)

1
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
2

    
3
/*
4
    Vamp
5

6
    An API for audio analysis and feature extraction plugins.
7

8
    Centre for Digital Music, Queen Mary, University of London.
9
    Copyright 2006-2015 Chris Cannam and QMUL.
10
  
11
    Permission is hereby granted, free of charge, to any person
12
    obtaining a copy of this software and associated documentation
13
    files (the "Software"), to deal in the Software without
14
    restriction, including without limitation the rights to use, copy,
15
    modify, merge, publish, distribute, sublicense, and/or sell copies
16
    of the Software, and to permit persons to whom the Software is
17
    furnished to do so, subject to the following conditions:
18

19
    The above copyright notice and this permission notice shall be
20
    included in all copies or substantial portions of the Software.
21

22
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
26
    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
27
    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28
    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29

30
    Except as contained in this notice, the names of the Centre for
31
    Digital Music; Queen Mary, University of London; and Chris Cannam
32
    shall not be used in advertising or otherwise to promote the sale,
33
    use or other dealings in this Software without prior written
34
    authorization.
35
*/
36

    
37
#include <vamp-hostsdk/PluginHostAdapter.h>
38

    
39
#include "Files.h"
40

    
41
#include <cctype> // tolower
42

    
43
#include <cstring>
44

    
45
#ifdef _WIN32
46

    
47
#include <windows.h>
48
#include <tchar.h>
49
#define PLUGIN_SUFFIX "dll"
50

    
51
#else /* ! _WIN32 */
52

    
53
#include <cstdlib>
54
#include <dirent.h>
55
#include <dlfcn.h>
56

    
57
#ifdef __APPLE__
58
#define PLUGIN_SUFFIX "dylib"
59
#else /* ! __APPLE__ */
60
#define PLUGIN_SUFFIX "so"
61
#endif /* ! __APPLE__ */
62

    
63
#endif /* ! _WIN32 */
64

    
65
using namespace std;
66

    
67
vector<string>
68
Files::listLibraryFiles()
69
{
70
    return listLibraryFilesMatching(Filter());
71
}
72

    
73
vector<string>
74
Files::listLibraryFilesMatching(Filter filter)
75
{
76
    vector<string> path = Vamp::PluginHostAdapter::getPluginPath();
77
    vector<string> libraryFiles;
78

    
79
    // we match case-insensitively, but only with ascii range
80
    // characters (input strings are expected to be utf-8)
81
    vector<string> libraryNames;
82
    for (int j = 0; j < int(filter.libraryNames.size()); ++j) {
83
        string n = filter.libraryNames[j];
84
        for (size_t i = 0; i < n.length(); ++i) {
85
            if (!(n[i] & 0x80)) {
86
                n[i] = char(tolower(n[i]));
87
            }
88
        }
89
        libraryNames.push_back(n);
90
    }
91

    
92
    for (size_t i = 0; i < path.size(); ++i) {
93
        
94
        vector<string> files = listFiles(path[i], PLUGIN_SUFFIX);
95

    
96
        for (vector<string>::iterator fi = files.begin();
97
             fi != files.end(); ++fi) {
98

    
99
            // we match case-insensitively, but only with ascii range
100
            // characters (this string is expected to be utf-8)
101
            string cleaned = *fi;
102
            for (size_t j = 0; j < cleaned.length(); ++j) {
103
                if (!(cleaned[j] & 0x80)) {
104
                    cleaned[j] = char(tolower(cleaned[j]));
105
                }
106
            }
107

    
108
            // libraryName should be lacking an extension, as it is
109
            // supposed to have come from the plugin key
110
            string::size_type pi = cleaned.find('.');
111
            if (pi != string::npos) {
112
                cleaned = cleaned.substr(0, pi);
113
            }
114
            
115
            bool matched = false;
116

    
117
            switch (filter.type) {
118

    
119
            case Filter::All:
120
                matched = true;
121
                break;
122

    
123
            case Filter::Matching:
124
                for (int j = 0; j < int(libraryNames.size()); ++j) {
125
                    if (cleaned == libraryNames[j]) {
126
                        matched = true;
127
                        break;
128
                    }
129
                }
130
                break;
131

    
132
            case Filter::NotMatching:
133
                matched = true;
134
                for (int j = 0; j < int(libraryNames.size()); ++j) {
135
                    if (cleaned == libraryNames[j]) {
136
                        matched = false;
137
                        break;
138
                    }
139
                }
140
                break;
141
            }
142

    
143
            if (!matched) continue;
144
            
145
            string fullPath = path[i];
146
            fullPath = splicePath(fullPath, *fi);
147
            libraryFiles.push_back(fullPath);
148
        }
149
    }
150

    
151
    return libraryFiles;
152
}
153

    
154
void *
155
Files::loadLibrary(string path)
156
{
157
    void *handle = 0;
158
#ifdef _WIN32
159
#ifdef UNICODE
160
    int wlen = MultiByteToWideChar(CP_UTF8, 0, path.c_str(), path.length(), 0, 0);
161
    if (wlen < 0) {
162
        cerr << "Vamp::HostExt: Unable to convert library path \""
163
             << path << "\" to wide characters " << endl;
164
        return handle;
165
    }
166
    wchar_t *buffer = new wchar_t[wlen+1];
167
    (void)MultiByteToWideChar(CP_UTF8, 0, path.c_str(), path.length(), buffer, wlen);
168
    buffer[wlen] = L'\0';
169
    handle = LoadLibrary(buffer);
170
    delete[] buffer;
171
#else
172
    handle = LoadLibrary(path.c_str());
173
#endif
174
    if (!handle) {
175
        cerr << "Vamp::HostExt: Unable to load library \""
176
             << path << "\": error code " << GetLastError() << endl;
177
    }
178
#else
179
    handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL);
180
    if (!handle) {
181
        cerr << "Vamp::HostExt: Unable to load library \""
182
             << path << "\": " << dlerror() << endl;
183
    }
184
#endif
185
    return handle;
186
}
187

    
188
void
189
Files::unloadLibrary(void *handle)
190
{
191
#ifdef _WIN32
192
    FreeLibrary((HINSTANCE)handle);
193
#else
194
    dlclose(handle);
195
#endif
196
}
197

    
198
void *
199
Files::lookupInLibrary(void *handle, const char *symbol)
200
{
201
#ifdef _WIN32
202
    return (void *)GetProcAddress((HINSTANCE)handle, symbol);
203
#else
204
    return (void *)dlsym(handle, symbol);
205
#endif
206
}
207

    
208
string
209
Files::lcBasename(string path)
210
{
211
    string basename(path);
212
        
213
    string::size_type li = basename.rfind('/');
214
    if (li != string::npos) basename = basename.substr(li + 1);
215

    
216
#ifdef _WIN32
217
    li = basename.rfind('\\');
218
    if (li != string::npos) basename = basename.substr(li + 1);
219
#endif
220

    
221
    li = basename.find('.');
222
    if (li != string::npos) basename = basename.substr(0, li);
223

    
224
    // case-insensitive, but only with ascii range characters (this
225
    // string is expected to be utf-8)
226
    for (size_t i = 0; i < basename.length(); ++i) {
227
        if (!(basename[i] & 0x80)) {
228
            basename[i] = char(tolower(basename[i]));
229
        }
230
    }
231

    
232
    return basename;
233
}
234

    
235
string
236
Files::splicePath(string a, string b)
237
{
238
#ifdef _WIN32
239
    return a + "\\" + b;
240
#else
241
    return a + "/" + b;
242
#endif
243
}
244

    
245
vector<string>
246
Files::listFiles(string dir, string extension)
247
{
248
    vector<string> files;
249

    
250
#ifdef _WIN32
251
    string expression = dir + "\\*." + extension;
252
#ifdef UNICODE
253
    int wlen = MultiByteToWideChar(CP_UTF8, 0, expression.c_str(), expression.length(), 0, 0);
254
    if (wlen < 0) {
255
        cerr << "Vamp::HostExt: Unable to convert wildcard path \""
256
             << expression << "\" to wide characters" << endl;
257
        return files;
258
    }
259
    wchar_t *buffer = new wchar_t[wlen+1];
260
    (void)MultiByteToWideChar(CP_UTF8, 0, expression.c_str(), expression.length(), buffer, wlen);
261
    buffer[wlen] = L'\0';
262
    WIN32_FIND_DATA data;
263
    HANDLE fh = FindFirstFile(buffer, &data);
264
    if (fh == INVALID_HANDLE_VALUE) {
265
        delete[] buffer;
266
        return files;
267
    }
268

    
269
    bool ok = true;
270
    while (ok) {
271
        wchar_t *fn = data.cFileName;
272
        int wlen = wcslen(fn);
273
        int len = WideCharToMultiByte(CP_UTF8, 0, fn, wlen, 0, 0, 0, 0);
274
        if (len < 0) {
275
            cerr << "Vamp::HostExt: Unable to convert wide char filename to utf-8" << endl;
276
            break;
277
        }
278
        char *conv = new char[len+1];
279
        (void)WideCharToMultiByte(CP_UTF8, 0, fn, wlen, conv, len, 0, 0);
280
        conv[len] = '\0';
281
        if (len > 0) {
282
            files.push_back(conv);
283
        }
284
        delete[] conv;
285
        ok = FindNextFile(fh, &data);
286
    }
287

    
288
    FindClose(fh);
289
    delete[] buffer;
290
#else
291
    WIN32_FIND_DATA data;
292
    HANDLE fh = FindFirstFile(expression.c_str(), &data);
293
    if (fh == INVALID_HANDLE_VALUE) return files;
294

    
295
    bool ok = true;
296
    while (ok) {
297
        files.push_back(data.cFileName);
298
        ok = FindNextFile(fh, &data);
299
    }
300

    
301
    FindClose(fh);
302
#endif
303
#else
304

    
305
    size_t extlen = extension.length();
306
    DIR *d = opendir(dir.c_str());
307
    if (!d) return files;
308
            
309
    struct dirent *e = 0;
310
    while ((e = readdir(d))) {
311
 
312
        size_t len = strlen(e->d_name);
313
        if (len < extlen + 2 ||
314
            e->d_name + len - extlen - 1 != "." + extension) {
315
            continue;
316
        }
317

    
318
        files.push_back(e->d_name);
319
    }
320

    
321
    closedir(d);
322
#endif
323

    
324
    return files;
325
}
326

    
327
bool
328
Files::isNonNative32Bit()
329
{
330
    // Return true if we are running on a system for which we should
331
    // use the VAMP_PATH_32 variable instead of VAMP_PATH. This will
332
    // be the case if we are a 32-bit executable but the OS is
333
    // natively 64-bit.
334
    //
335
    // This currently works only on Windows; other operating systems
336
    // will use VAMP_PATH always.
337
    
338
    if (sizeof(void *) == 8) {
339
        return false;
340
    }
341

    
342
#ifdef _WIN32
343
    BOOL wow64 = FALSE;
344
    BOOL (WINAPI *fnIsWow64Process)(HANDLE, PBOOL) =
345
        (BOOL (WINAPI *)(HANDLE, PBOOL)) GetProcAddress
346
        (GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
347
    if (fnIsWow64Process) {
348
        if (fnIsWow64Process(GetCurrentProcess(), &wow64)) {
349
            if (wow64) {
350
                return true;
351
            } else {
352
                return false;
353
            }
354
        } else {
355
            cerr << "Vamp::HostExt: Unable to query process architecture"
356
                 << endl;
357
            return false;
358
        }
359
    } else {
360
        cerr << "Vamp::HostExt: Unable to query process architecture: "
361
             << "Function not available" << endl;
362
        return false;
363
    }
364
#endif
365

    
366
    return false;
367
}
368

    
369
bool
370
Files::getEnvUtf8(std::string variable, std::string &value)
371
{
372
    value = "";
373
    
374
#ifdef _WIN32
375
    int wvarlen = MultiByteToWideChar(CP_UTF8, 0,
376
                                      variable.c_str(), int(variable.length()),
377
                                      0, 0);
378
    if (wvarlen < 0) {
379
        cerr << "Vamp::HostExt: Unable to convert environment variable name "
380
             << variable << " to wide characters" << endl;
381
        return false;
382
    }
383
    
384
    wchar_t *wvarbuf = new wchar_t[wvarlen + 1];
385
    (void)MultiByteToWideChar(CP_UTF8, 0,
386
                              variable.c_str(), int(variable.length()),
387
                              wvarbuf, wvarlen);
388
    wvarbuf[wvarlen] = L'\0';
389
    
390
    wchar_t *wvalue = _wgetenv(wvarbuf);
391

    
392
    delete[] wvarbuf;
393

    
394
    if (!wvalue) {
395
        return false;
396
    }
397

    
398
    int wvallen = int(wcslen(wvalue));
399
    int vallen = WideCharToMultiByte(CP_UTF8, 0,
400
                                     wvalue, wvallen,
401
                                     0, 0, 0, 0);
402
    if (vallen < 0) {
403
        cerr << "Vamp::HostExt: Unable to convert environment value to UTF-8"
404
             << endl;
405
        return false;
406
    }
407

    
408
    char *val = new char[vallen + 1];
409
    (void)WideCharToMultiByte(CP_UTF8, 0,
410
                              wvalue, wvallen,
411
                              val, vallen, 0, 0);
412
    val[vallen] = '\0';
413

    
414
    value = val;
415

    
416
    delete[] val;
417
    return true;
418

    
419
#else
420

    
421
    char *val = getenv(variable.c_str());
422
    if (!val) {
423
        return false;
424
    }
425

    
426
    value = val;
427
    return true;
428
    
429
#endif
430
}