1 |
/*************************************************************************** |
/*************************************************************************** |
2 |
* * |
* * |
3 |
* Copyright (C) 2007 Christian Schoenebeck * |
* Copyright (C) 2007 - 2009 Christian Schoenebeck * |
4 |
* * |
* * |
5 |
* This program is free software; you can redistribute it and/or modify * |
* This program is free software; you can redistribute it and/or modify * |
6 |
* it under the terms of the GNU General Public License as published by * |
* it under the terms of the GNU General Public License as published by * |
21 |
#include "InstrumentEditorFactory.h" |
#include "InstrumentEditorFactory.h" |
22 |
|
|
23 |
#include "../common/global_private.h" |
#include "../common/global_private.h" |
24 |
|
#include "../Sampler.h" |
25 |
|
|
26 |
#if defined(WIN32) |
#if defined(WIN32) |
27 |
#include <windows.h> |
#include <windows.h> |
29 |
#include <dlfcn.h> |
#include <dlfcn.h> |
30 |
#include <errno.h> |
#include <errno.h> |
31 |
#include <dirent.h> |
#include <dirent.h> |
32 |
|
#include <sys/types.h> |
33 |
|
#include <sys/stat.h> |
34 |
|
#include <unistd.h> |
35 |
#endif |
#endif |
36 |
#include <string.h> |
#include <string.h> |
37 |
|
|
102 |
if (!bPluginsLoaded) { |
if (!bPluginsLoaded) { |
103 |
dmsg(1,("Loading instrument editor plugins...")); |
dmsg(1,("Loading instrument editor plugins...")); |
104 |
#if defined(WIN32) |
#if defined(WIN32) |
105 |
bool firstFileFound = true; |
String dir = Sampler::GetInstallDir(); |
106 |
WIN32_FIND_DATA win32FindData; |
if (dir.empty() || !LoadPlugins(dir + "\\plugins")) { |
107 |
String plugindir = (String)CONFIG_PLUGIN_DIR + (String)("\\*.DLL"); |
if (!LoadPlugins(CONFIG_PLUGIN_DIR)) { |
108 |
HANDLE hDir = FindFirstFile(plugindir.c_str(), &win32FindData); |
std::cerr << "Could not open instrument editor plugins " |
109 |
if (hDir == INVALID_HANDLE_VALUE) { |
<< "directory (" << dir << "\\plugins or " |
110 |
if(GetLastError() != ERROR_FILE_NOT_FOUND) { |
<< CONFIG_PLUGIN_DIR << "), Error: " |
|
std::cerr << "Could not open instrument editor plugins directory " |
|
|
<< "(" << CONFIG_PLUGIN_DIR << "): Error " |
|
|
<< GetLastError() << std::endl; |
|
|
return; |
|
|
} |
|
|
else { |
|
|
firstFileFound = false; |
|
|
} |
|
|
} |
|
|
|
|
|
while(GetLastError() != ERROR_NO_MORE_FILES && firstFileFound) { |
|
|
if(!(win32FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { |
|
|
String sPath = (String)CONFIG_PLUGIN_DIR + ((String)"\\" + (String)win32FindData.cFileName); |
|
|
// load the DLL (the plugins should register themselfes automatically) |
|
|
void* pDLL = myhinstance = LoadLibrary( sPath.c_str() ); |
|
|
if (pDLL) LoadedDLLs.push_back(pDLL); |
|
|
else { |
|
|
std::cerr << "Failed to load instrument editor plugin: " |
|
|
<< sPath << std::endl; |
|
|
} |
|
|
} |
|
|
int res = FindNextFile(hDir, &win32FindData); |
|
|
if(res == 0 && GetLastError() != ERROR_NO_MORE_FILES) { |
|
|
std::cerr << "Error while reading plugins directory FindNextFile Error " |
|
111 |
<< GetLastError() << std::endl; |
<< GetLastError() << std::endl; |
112 |
return; |
return; |
113 |
} |
} |
114 |
} |
} |
115 |
FindClose(hDir); |
#else |
116 |
#else // POSIX |
if (!LoadPlugins(CONFIG_PLUGIN_DIR)) { |
117 |
DIR* hDir = opendir(CONFIG_PLUGIN_DIR); |
std::cerr << "Could not open instrument editor plugins " |
118 |
if (!hDir) { |
<< "directory (" << CONFIG_PLUGIN_DIR << "): " |
|
std::cerr << "Could not open instrument editor plugins directory " |
|
|
<< "(" << CONFIG_PLUGIN_DIR << "): " |
|
119 |
<< strerror(errno) << std::endl; |
<< strerror(errno) << std::endl; |
120 |
return; |
return; |
121 |
} |
} |
|
for (dirent* pEntry = readdir(hDir); pEntry; pEntry = readdir(hDir)) { |
|
|
// skip entries that are not regular files |
|
|
if (pEntry->d_type != DT_REG) continue; |
|
|
String sPath = pEntry->d_name; |
|
|
// skip files that are not .so files |
|
|
if ( |
|
|
sPath.substr(sPath.length() - 3) != ".so" && |
|
|
sPath.find(".so.") == String::npos |
|
|
) continue; |
|
|
// make it a full qualified path |
|
|
sPath = CONFIG_PLUGIN_DIR + ("/" + sPath); |
|
|
// load the DLL (the plugins should register themselfes automatically) |
|
|
void* pDLL = dlopen(sPath.c_str(), RTLD_NOW); |
|
|
if (pDLL) LoadedDLLs.push_back(pDLL); |
|
|
else { |
|
|
std::cerr << "Failed to load instrument editor plugin: " |
|
|
<< sPath << std::endl; |
|
|
} |
|
|
} |
|
|
closedir(hDir); |
|
122 |
#endif |
#endif |
123 |
bPluginsLoaded = true; |
bPluginsLoaded = true; |
124 |
dmsg(1,("OK\n")); |
dmsg(1,("OK\n")); |
125 |
} |
} |
126 |
} |
} |
127 |
|
|
128 |
|
bool InstrumentEditorFactory::LoadPlugins(String plugindir) { |
129 |
|
#if defined(WIN32) |
130 |
|
WIN32_FIND_DATA win32FindData; |
131 |
|
const String pluginpattern = plugindir + "\\*.dll"; |
132 |
|
HANDLE hDir = FindFirstFile(pluginpattern.c_str(), &win32FindData); |
133 |
|
if (hDir == INVALID_HANDLE_VALUE) { |
134 |
|
if (GetLastError() != ERROR_FILE_NOT_FOUND) { |
135 |
|
return false; |
136 |
|
} else { |
137 |
|
dmsg(1,("None")); |
138 |
|
return true; |
139 |
|
} |
140 |
|
} |
141 |
|
|
142 |
|
do { |
143 |
|
// skip directory entries |
144 |
|
if (win32FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) |
145 |
|
continue; |
146 |
|
// dir entry name as full qualified path |
147 |
|
const String sPath = plugindir + "\\" + win32FindData.cFileName; |
148 |
|
// load the DLL |
149 |
|
HINSTANCE hinstLib; |
150 |
|
void* pDLL = hinstLib = LoadLibrary(sPath.c_str()); |
151 |
|
if (!pDLL) { |
152 |
|
std::cerr << "Failed to load instrument editor plugin: " |
153 |
|
<< sPath << std::endl; |
154 |
|
continue; |
155 |
|
} |
156 |
|
|
157 |
|
InnerFactory* (*fn)() = (InnerFactory* (*)()) |
158 |
|
GetProcAddress(hinstLib, "createInstrumentEditorInnerFactory"); |
159 |
|
if (fn == NULL) { |
160 |
|
std::cerr << "ERROR: unable to find " |
161 |
|
"createInstrumentEditorInnerFactory() " |
162 |
|
"in DLL\n" << std::flush; |
163 |
|
FreeLibrary(hinstLib); |
164 |
|
continue; |
165 |
|
} |
166 |
|
|
167 |
|
// get the plugin instance and register it to the factory |
168 |
|
|
169 |
|
InnerFactory* pInnerFactory = fn(); |
170 |
|
if (!pInnerFactory) { |
171 |
|
std::cerr << "ERROR: !pInnerFactory\n" << std::flush; |
172 |
|
FreeLibrary(hinstLib); |
173 |
|
continue; |
174 |
|
} |
175 |
|
InstrumentEditor* pEditor = pInnerFactory->Create(); |
176 |
|
if (InnerFactories.count(pEditor->Name())) { |
177 |
|
std::cerr << "ERROR: a plugin with name '" |
178 |
|
<< pEditor->Name() |
179 |
|
<< "' already loaded (skipping)\n" |
180 |
|
<< std::flush; |
181 |
|
pInnerFactory->Destroy(pEditor); |
182 |
|
FreeLibrary(hinstLib); |
183 |
|
continue; |
184 |
|
} |
185 |
|
InnerFactories[pEditor->Name()] = pInnerFactory; |
186 |
|
pInnerFactory->Destroy(pEditor); |
187 |
|
|
188 |
|
LoadedDLLs.push_back(pDLL); |
189 |
|
} while (FindNextFile(hDir, &win32FindData)); |
190 |
|
|
191 |
|
if (hDir != INVALID_HANDLE_VALUE) FindClose(hDir); |
192 |
|
|
193 |
|
#else // POSIX |
194 |
|
|
195 |
|
#if defined(__APPLE__) /* 20071224 Toshi Nagata */ |
196 |
|
if (plugindir.find("~") == 0) |
197 |
|
plugindir.replace(0, 1, getenv("HOME")); |
198 |
|
#endif |
199 |
|
DIR* hDir = opendir(plugindir.c_str()); |
200 |
|
if (!hDir) { |
201 |
|
return false; |
202 |
|
} |
203 |
|
for (dirent* pEntry = readdir(hDir); pEntry; pEntry = readdir(hDir)) { |
204 |
|
// dir entry name as full qualified path |
205 |
|
const String sPath = plugindir + "/" + pEntry->d_name; |
206 |
|
// skip entries that are not regular files |
207 |
|
struct stat entry_stat; |
208 |
|
if (lstat(sPath.c_str(), &entry_stat) != 0 || |
209 |
|
(entry_stat.st_mode & S_IFMT) != S_IFREG) |
210 |
|
continue; |
211 |
|
// skip files that are not .so files |
212 |
|
if (sPath.length() < 3 || |
213 |
|
sPath.substr(sPath.length() - 3) != ".so" && |
214 |
|
sPath.find(".so.") == String::npos) |
215 |
|
continue; |
216 |
|
// load the DLL (the plugins should register themselfes automatically) |
217 |
|
void* pDLL = dlopen(sPath.c_str(), RTLD_NOW); |
218 |
|
if (pDLL) LoadedDLLs.push_back(pDLL); |
219 |
|
else { |
220 |
|
std::cerr << "Failed to load instrument editor plugin: '" |
221 |
|
<< sPath << "', cause: " << dlerror() << std::endl; |
222 |
|
} |
223 |
|
} |
224 |
|
closedir(hDir); |
225 |
|
#endif |
226 |
|
return true; |
227 |
|
} |
228 |
|
|
229 |
void InstrumentEditorFactory::ClosePlugins() { |
void InstrumentEditorFactory::ClosePlugins() { |
230 |
if (LoadedDLLs.size()) { |
if (LoadedDLLs.size()) { |
231 |
dmsg(1,("Unloading instrument editor plugins...")); |
dmsg(1,("Unloading instrument editor plugins...")); |