文章目录

该类负责对plugins文件夹下的动态链接库进行组织,与其中函数的调用。定义于src/musikcore/plugin/PluginFactory.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
class PluginFactory {
public:
/* 单例懒汉模式 */
static PluginFactory& Instance();
/* 模板结构体,将运算符()重载为释放 */
template <typename T>
struct ReleaseDeleter {
void operator()(T* t) {
t->Release();
}
};

template <typename T>
struct NullDeleter {
void operator()(T* t) {
}
};
/* 调用functionName对应的函数,并将该函数的返回值作为参数传入handler */
template <class T, class D> void QueryInterface(
const std::string& functionName,
std::function<void(mymusic::core::sdk::IPlugin*, std::shared_ptr<T>, const std::string&)> handler)
{
std::unique_lock<std::mutex> lock(this->mutex);

typedef T * STDCALL(PluginInterfaceCall);

for (std::shared_ptr<Descriptor> descriptor : this->plugins) {
if (functionName == "GetPlugin" || prefs->GetBool(descriptor->key.c_str(), true)) { /* enabled */
PluginInterfaceCall funcPtr =
#ifdef WIN32
(PluginInterfaceCall) GetProcAddress((HMODULE)(descriptor->nativeHandle), functionName.c_str());
#else
(PluginInterfaceCall)dlsym(descriptor->nativeHandle, functionName.c_str());
#endif
if (funcPtr) {
T* result = funcPtr();

if (result) {
handler(descriptor->plugin, std::shared_ptr<T>(result, D()), descriptor->filename);
}
}
}
}
}
/* 获取动态链接库中所有有名为functionName的函数的plugin */
template <class T, class D> std::vector<std::shared_ptr<T> > QueryInterface(const std::string& functionName) {
std::vector<std::shared_ptr<T> > plugins;

QueryInterface<T, D>(
functionName,
[&plugins](
mymusic::core::sdk::IPlugin* unused,
std::shared_ptr<T> plugin,
const std::string& fn)
{
plugins.push_back(plugin);
});

return plugins;
}
/* 调用动态链接库中所有名为functionName的函数 */
template <class T> void QueryFunction(
const std::string& functionName,
std::function<void(mymusic::core::sdk::IPlugin*, T)> handler)
{
std::unique_lock<std::mutex> lock(this->mutex);

for (std::shared_ptr<Descriptor> descriptor : this->plugins) {
if (prefs->GetBool(descriptor->key.c_str(), true)) { /* if enabled by prefs */
T funcPtr =
#ifdef WIN32
(T) GetProcAddress((HMODULE)(descriptor->nativeHandle), functionName.c_str());
#else
(T)dlsym(descriptor->nativeHandle, functionName.c_str());
#endif
if (funcPtr) {
handler(descriptor->plugin, funcPtr);
}
}
}
}
/* 查询Guid为guid的plugin */
std::shared_ptr<mymusic::core::sdk::IPlugin> QueryGuid(const std::string& guid) {
using T = mymusic::core::sdk::IPlugin;
std::shared_ptr<T> result;
using Deleter = PluginFactory::ReleaseDeleter<T>;
Instance().QueryInterface<T, Deleter>(
"GetPlugin",
[&result, guid](T* unused, std::shared_ptr<T> plugin, const std::string& fn) {
if (std::string(plugin->Guid()) == guid) {
result = plugin;
}
});
return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    private:
/* plugin的描述符 */
struct Descriptor {
mymusic::core::sdk::IPlugin* plugin;
/* 对应的动态链接库文件描述符 */
void* nativeHandle;
/* 对应的动态链接库文件的绝对路径 */
std::string filename;
/* 对应的动态链接库文件名 */
std::string key;
};
/* 设置对象的属性于prefs,然后调用LoadPlugins */
PluginFactory();
/* 依次释放每个动态链接库对应的plugin,然后关闭对应的动态链接库;最后清除plugins向量 */
~PluginFactory();
/* 加载plugins目录下的所有动态链接库,调用其中的GetPlugin函数获取该动态链接库对应的plugin,并设置对应的Descriptor
* 所有的这些plugin存入plugins向量中*/
void LoadPlugins();
/* 存储所有的plugin */
std::vector<std::shared_ptr<Descriptor> > plugins;
/* 对象的互斥锁 */
std::mutex mutex;
/* 对象的属性 */
std::shared_ptr<mymusic::core::sdk::IPreferences> prefs;
};