Update changelog and bump version to 0.0.17-2.
[tweakr] / tweakr-module-manager.c
1 /*
2  * vim:ts=4:sw=4:et:cindent:cino=(0
3  */ 
4
5 #include <config.h>
6
7 #include <string.h>
8 #include <unistd.h>
9
10 #include <gmodule.h>
11
12 #include "tweakr-types.h"
13 #include "libtweakr-section/tweakr-module.h"
14 #include "tweakr-module-manager.h"
15
16
17 enum
18 {
19     PROP_0,
20     PROP_MODULE_PATH
21 };
22
23
24 static GObject *
25 tweakr_module_manager_constructor (GType type,
26                                          guint n_params,
27                                          GObjectConstructParam *params);
28 static void
29 tweakr_module_manager_finalize (GObject *object);
30
31 static void
32 tweakr_module_manager_get_property (GObject *object,
33                                           guint param_id,
34                                           GValue *value,
35                                           GParamSpec *pspec);
36
37 static void
38 tweakr_module_manager_set_property (GObject *object,
39                                           guint param_id,
40                                           const GValue *value,
41                                           GParamSpec *pspec);
42
43 static gboolean
44 tweakr_module_manager_query_modules
45     (TweakrModuleManager *manager);
46
47
48 G_DEFINE_TYPE (TweakrModuleManager, tweakr_module_manager,
49                G_TYPE_OBJECT);
50
51
52 static void
53 tweakr_module_manager_class_init (TweakrModuleManagerClass *klass)
54 {
55     GObjectClass *object_class = G_OBJECT_CLASS (klass);
56
57     object_class->constructor  = tweakr_module_manager_constructor;
58     object_class->finalize     = tweakr_module_manager_finalize;
59     object_class->get_property = tweakr_module_manager_get_property;
60     object_class->set_property = tweakr_module_manager_set_property;
61
62     g_object_class_install_property
63         (object_class, PROP_MODULE_PATH,
64          g_param_spec_string ("module-path",
65                               "Module Path",
66                               "The path where to look for modules",
67                               NULL,
68                               G_PARAM_READWRITE |
69                               G_PARAM_CONSTRUCT_ONLY));
70 }
71
72 static void
73 tweakr_module_manager_init (TweakrModuleManager *manager)
74 {
75     manager->module_path = NULL;
76     manager->modules     = NULL;
77 }
78
79 static GObject *
80 tweakr_module_manager_constructor (GType type,
81                                          guint n_params,
82                                          GObjectConstructParam *params)
83 {
84     GObject *object;
85     TweakrModuleManager *manager;
86
87     object = G_OBJECT_CLASS
88         (tweakr_module_manager_parent_class)->constructor (type,
89                                                                  n_params,
90                                                                  params);
91
92     manager = TWEAKR_MODULE_MANAGER (object);
93
94     if (manager->module_path)
95         tweakr_module_manager_query_modules (manager);
96
97     return object;
98 }
99
100 static void
101 tweakr_module_manager_finalize (GObject *object)
102 {
103     TweakrModuleManager *manager = TWEAKR_MODULE_MANAGER (object);
104
105     g_free (manager->module_path);
106
107     /* GTypeModules most not be finalized, don't unref them */
108     g_list_free (manager->modules);
109
110     G_OBJECT_CLASS (tweakr_module_manager_parent_class)->
111         finalize (object);
112 }
113
114 static void
115 tweakr_module_manager_get_property (GObject *object,
116                                           guint param_id,
117                                           GValue *value,
118                                           GParamSpec *pspec)
119 {
120     TweakrModuleManager *manager = TWEAKR_MODULE_MANAGER (object);
121
122     switch (param_id)
123     {
124         case PROP_MODULE_PATH:
125             g_value_set_string (value, manager->module_path);
126             break;
127         default:
128             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
129             break;
130     }
131 }
132
133 static void
134 tweakr_module_manager_set_property (GObject *object,
135                                           guint param_id,
136                                           const GValue *value,
137                                           GParamSpec *pspec)
138 {
139     TweakrModuleManager *manager = TWEAKR_MODULE_MANAGER (object);
140
141     switch (param_id)
142     {
143         case PROP_MODULE_PATH:
144             manager->module_path = g_value_dup_string (value);
145             break;
146         default:
147             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
148             break;
149     }
150 }
151
152 static gboolean
153 tweakr_module_manager_is_valid_module_name (const gchar *name)
154 {
155     return g_str_has_suffix (name, ".so");
156 }
157
158 static gboolean
159 tweakr_module_manager_query_modules (TweakrModuleManager *manager)
160 {
161     const gchar *name;
162     GDir        *dir;
163     GError      *error = NULL;
164
165     dir = g_dir_open (manager->module_path, 0, &error);
166
167     if (!dir)
168     {
169         g_printerr ("Error while opening module dir: %s\n", error->message);
170         g_clear_error (&error);
171         return FALSE;
172     }
173
174     while ((name = g_dir_read_name (dir)))
175     {
176         if (tweakr_module_manager_is_valid_module_name (name))
177         {
178             TweakrModule *module;
179             gchar     *path;
180
181             path = g_build_filename (manager->module_path, name, NULL);
182             module = tweakr_module_new (path);
183
184             if (! g_type_module_use (G_TYPE_MODULE (module)))
185             {
186                 g_printerr ("Failed to load module: %s\n", path);
187                 g_object_unref (module);
188                 g_free (path);
189                 continue;
190             }
191
192             g_free (path);
193
194             g_type_module_unuse (G_TYPE_MODULE (module));
195
196             manager->modules = g_list_prepend (manager->modules, module);
197         }
198     }
199
200     g_dir_close (dir);
201
202     return TRUE;
203 }
204