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
96
97
98
|
using Gee;
namespace Dino.Plugins {
private class Info : Object {
public Module module;
public Type gtype;
public Info(Type type, owned Module module) {
this.module = (owned) module;
this.gtype = type;
}
}
public class Loader : Object {
[CCode (has_target = false)]
private delegate Type RegisterPluginFunction(Module module);
private Application app;
private string[] search_paths;
private RootInterface[] plugins = new RootInterface[0];
private Info[] infos = new Info[0];
public Loader(Application app) {
this.app = app;
this.search_paths = app.search_path_generator.get_plugin_paths();
}
public void load_all() throws Error {
if (Module.supported() == false) {
throw new Error(-1, 0, "Plugins are not supported");
}
HashSet<string> plugin_names = new HashSet<string>();
foreach (string path in search_paths) {
try {
Dir dir = Dir.open(path, 0);
string? file = null;
while ((file = dir.read_name()) != null) {
if (file.has_suffix(Module.SUFFIX)) plugin_names.add(file);
}
} catch (Error e) {
// Ignore this folder
}
}
foreach (string plugin in plugin_names) {
load(plugin);
}
}
public RootInterface load(string name) throws Error {
if (Module.supported() == false) {
throw new Error(-1, 0, "Plugins are not supported");
}
Module module = null;
string path = "";
foreach (string prefix in search_paths) {
path = Path.build_filename(prefix, name);
module = Module.open(path, ModuleFlags.BIND_LAZY);
if (module != null) break;
}
if (module == null) {
throw new Error(-1, 1, "%s", Module.error().replace(path, name));
}
void* function;
module.symbol("register_plugin", out function);
if (function == null) {
throw new Error(-1, 2, "register_plugin () not found");
}
RegisterPluginFunction register_plugin = (RegisterPluginFunction) function;
Type type = register_plugin(module);
if (type.is_a(typeof(RootInterface)) == false) {
throw new Error(-1, 3, "Unexpected type");
}
Info info = new Plugins.Info(type, (owned) module);
infos += info;
RootInterface plugin = (RootInterface) Object.new (type);
plugins += plugin;
plugin.registered(app);
return plugin;
}
public void shutdown() {
foreach (RootInterface p in plugins) {
p.shutdown();
}
}
}
}
|