1 /*
2 * * Copyright (C) 2006-2011 Anders Brander <anders@brander.dk>,
3 * * Anders Kvist <akv@lnxbx.dk> and Klaus Post <klauspost@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20 #include <gmodule.h>
21 #include "rs-plugin.h"
22
23 struct _RSPlugin {
24 GTypeModule parent_instance;
25
26 gchar *filename;
27 GModule *library;
28
29 void (*load)(RSPlugin *plugin);
30 void (*unload)(RSPlugin *plugin);
31 };
32
33 struct _RSPluginClass {
34 GTypeModuleClass parent_class;
35 };
36
37 enum {
38 PROP_0,
39 PROP_FILENAME
40 };
41
42 static void rs_plugin_finalize (GObject *object);
43 static void rs_plugin_get_property (GObject *object, guint param_id, GValue *value, GParamSpec *pspec);
44 static void rs_plugin_set_property (GObject *object, guint param_id, const GValue *value, GParamSpec *pspec);
45 static gboolean rs_plugin_load_module (GTypeModule *gmodule);
46 static void rs_plugin_unload_module (GTypeModule *gmodule);
47
48 G_DEFINE_TYPE(RSPlugin, rs_plugin, G_TYPE_TYPE_MODULE);
49
50 static void
rs_plugin_class_init(RSPluginClass * klass)51 rs_plugin_class_init(RSPluginClass *klass)
52 {
53 GObjectClass *object_class = G_OBJECT_CLASS(klass);
54 GTypeModuleClass *type_module_class = G_TYPE_MODULE_CLASS(klass);
55
56 object_class->finalize = rs_plugin_finalize;
57 object_class->get_property = rs_plugin_get_property;
58 object_class->set_property = rs_plugin_set_property;
59
60 type_module_class->load = rs_plugin_load_module;
61 type_module_class->unload = rs_plugin_unload_module;
62
63 g_object_class_install_property(object_class,
64 PROP_FILENAME, g_param_spec_string (
65 "filename",
66 "Filename",
67 "The filaname of the plugin",
68 NULL,
69 G_PARAM_READWRITE |G_PARAM_CONSTRUCT_ONLY)
70 );
71 }
72
73 static void
rs_plugin_init(RSPlugin * plugin)74 rs_plugin_init(RSPlugin *plugin)
75 {
76 plugin->filename = NULL;
77 plugin->library = NULL;
78 plugin->load = NULL;
79 plugin->unload = NULL;
80 }
81
82 static void
rs_plugin_finalize(GObject * object)83 rs_plugin_finalize(GObject *object)
84 {
85 RSPlugin *plugin = RS_PLUGIN(object);
86
87 g_free(plugin->filename);
88
89 G_OBJECT_CLASS(rs_plugin_parent_class)->finalize(object);
90 }
91
92 static void
rs_plugin_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)93 rs_plugin_get_property(GObject *object, guint param_id, GValue *value, GParamSpec *pspec)
94 {
95 RSPlugin *plugin = RS_PLUGIN(object);
96
97 switch (param_id)
98 {
99 case PROP_FILENAME:
100 g_value_set_string(value, plugin->filename);
101 break;
102 default:
103 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
104 break;
105 }
106 }
107
108 static void
rs_plugin_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)109 rs_plugin_set_property (GObject *object, guint param_id, const GValue *value, GParamSpec *pspec)
110 {
111 RSPlugin *plugin = RS_PLUGIN(object);
112
113 switch (param_id)
114 {
115 case PROP_FILENAME:
116 g_free (plugin->filename);
117 plugin->filename = g_value_dup_string (value);
118 break;
119 default:
120 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
121 break;
122 }
123 }
124
125 static gboolean
rs_plugin_load_module(GTypeModule * gmodule)126 rs_plugin_load_module(GTypeModule *gmodule)
127 {
128 RSPlugin *plugin = RS_PLUGIN(gmodule);
129
130 g_assert(G_IS_TYPE_MODULE(gmodule));
131 g_assert(RS_IS_PLUGIN(plugin));
132
133 g_assert(plugin->filename != NULL);
134
135 plugin->library = g_module_open(plugin->filename, 0);
136
137 if (!plugin->library)
138 {
139 g_printerr ("%s\n", g_module_error ());
140 return FALSE;
141 }
142
143 if (!g_module_symbol(plugin->library, "rs_plugin_load", (gpointer *) &plugin->load))
144 {
145 g_printerr ("%s\n", g_module_error ());
146 g_module_close (plugin->library);
147 return FALSE;
148 }
149
150 /* This is not required from plugins - YET! */
151 if (!g_module_symbol(plugin->library, "rs_plugin_unload", (gpointer *) &plugin->unload))
152 plugin->unload = NULL;
153
154 /* Execute plugin load method */
155 plugin->load (plugin);
156
157 /* We don't support unloading of modules - FOR NOW - make sure it never happens */
158 g_module_make_resident(plugin->library);
159
160 return TRUE;
161 }
162
163 static void
rs_plugin_unload_module(GTypeModule * gmodule)164 rs_plugin_unload_module (GTypeModule *gmodule)
165 {
166 RSPlugin *plugin = RS_PLUGIN(gmodule);
167
168 g_assert(G_IS_TYPE_MODULE(gmodule));
169 g_assert(RS_IS_PLUGIN(plugin));
170
171 if (plugin->unload)
172 plugin->unload (plugin);
173
174 g_module_close (plugin->library);
175 plugin->library = NULL;
176
177 plugin->load = NULL;
178 plugin->unload = NULL;
179 }
180
181 RSPlugin *
rs_plugin_new(const gchar * filename)182 rs_plugin_new (const gchar *filename)
183 {
184 RSPlugin *plugin;
185
186 g_assert(filename != NULL);
187
188 plugin = g_object_new(RS_TYPE_PLUGIN, "filename", filename, NULL);
189
190 return plugin;
191 }
192