]> www.fi.muni.cz Git - evince.git/blob - libdocument/ev-backends-manager.c
Allow making backend modules resident. This is needed only for some
[evince.git] / libdocument / ev-backends-manager.c
1 /* this file is part of evince, a gnome document viewer
2  *
3  *  Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
4  *
5  * Evince is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * Evince is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 #include <config.h>
21
22 #include <glib/gstdio.h>
23
24 #include "ev-module.h"
25 #include "ev-backends-manager.h"
26
27 static GList *ev_backends_list = NULL;
28
29 typedef struct _EvBackendInfo EvBackendInfo;
30 struct _EvBackendInfo {
31         gchar       *module_name;
32         GTypeModule *module;
33         gboolean     resident;
34
35         GType        type_id;
36
37         gchar       *type_desc;
38         gchar      **mime_types;
39 };
40
41 #define EV_BACKENDS_GROUP     "Evince Backend"
42 #define EV_BACKENDS_EXTENSION ".evince-backend"
43
44 static void
45 ev_backend_info_free (EvBackendInfo *info)
46 {
47         g_free (info->module_name);
48         g_free (info->type_desc);
49         g_strfreev (info->mime_types);
50         g_free (info);
51 }
52
53 static EvBackendInfo *
54 ev_backends_manager_load_backend (const gchar *file)
55 {
56         EvBackendInfo *info;
57         GKeyFile      *backend_file = NULL;
58         GError        *error = NULL;
59
60         backend_file = g_key_file_new ();
61         if (!g_key_file_load_from_file (backend_file, file, G_KEY_FILE_NONE, &error)) {
62                 g_warning ("Error opening backend file %s: %s",
63                            file, error->message);
64                 g_error_free (error);
65                 g_key_file_free (backend_file);
66
67                 return NULL;
68         }
69
70         info = g_new0 (EvBackendInfo, 1);
71         info->module_name = g_key_file_get_string (backend_file, EV_BACKENDS_GROUP,
72                                                    "Module", NULL);
73         if (!info->module_name) {
74                 g_warning ("Bad evince backend file %s: Could not find 'Module'",
75                            file);
76                 ev_backend_info_free (info);
77                 g_key_file_free (backend_file);
78
79                 return NULL;
80         }
81
82         info->resident = g_key_file_get_boolean (backend_file, EV_BACKENDS_GROUP,
83                                                  "Resident", NULL);
84         
85         info->type_desc = g_key_file_get_locale_string (backend_file, EV_BACKENDS_GROUP,
86                                                         "TypeDescription", NULL, NULL);
87         if (!info->type_desc) {
88                 g_warning ("Bad evince backend file %s: Could not find 'TypeDescription'",
89                            file);
90                 ev_backend_info_free (info);
91                 g_key_file_free (backend_file);
92
93                 return NULL;
94         }
95
96         info->mime_types = g_key_file_get_string_list (backend_file, EV_BACKENDS_GROUP,
97                                                        "MimeType", NULL, NULL);
98         if (!info->mime_types) {
99                 g_warning ("Bad evince backend file %s: Could not find 'MimeType'",
100                            file);
101                 ev_backend_info_free (info);
102                 g_key_file_free (backend_file);
103
104                 return NULL;
105         }
106
107         g_key_file_free (backend_file);
108
109         return info;
110 }
111
112 static gboolean
113 ev_backends_manager_load (void)
114 {
115         GDir        *dir;
116         const gchar *dirent;
117         GError      *error = NULL;
118
119         dir = g_dir_open (EV_BACKENDSDIR, 0, &error);
120         if (!dir) {
121                 g_warning (error->message);
122                 g_error_free (error);
123
124                 return FALSE;
125         }
126
127         while ((dirent = g_dir_read_name (dir))) {
128                 EvBackendInfo *info;
129                 gchar         *file;
130                 
131                 if (!g_str_has_suffix (dirent, EV_BACKENDS_EXTENSION))
132                         continue;
133
134                 file = g_build_filename (EV_BACKENDSDIR, dirent, NULL);
135                 info = ev_backends_manager_load_backend (file);
136                 g_free (file);
137
138                 if (!info)
139                         continue;
140                 
141                 ev_backends_list = g_list_prepend (ev_backends_list, info);
142         }
143
144         g_dir_close (dir);
145
146         return TRUE;
147 }
148
149 gboolean
150 ev_backends_manager_init (void)
151 {
152         if (ev_backends_list)
153                 return FALSE;
154
155         return ev_backends_manager_load ();
156 }
157
158 void
159 ev_backends_manager_shutdown (void)
160 {
161         g_list_foreach (ev_backends_list, (GFunc)ev_backend_info_free, NULL);
162         g_list_free (ev_backends_list);
163         ev_backends_list = NULL;
164 }
165
166 static EvBackendInfo *
167 ev_backends_manager_get_backend_info (const gchar *mime_type)
168 {
169         GList *l;
170
171         for (l = ev_backends_list; l; l = g_list_next (l)) {
172                 EvBackendInfo *info;
173                 gint           i = 0;
174                 const char    *mime;
175                 
176                 info = (EvBackendInfo *)l->data;
177                 
178                 while ((mime = info->mime_types[i++])) {
179                         if (g_ascii_strcasecmp (mime, mime_type) == 0)
180                                 return info;
181                 }
182         }
183
184         return NULL;
185 }
186
187 EvDocument *
188 ev_backends_manager_get_document (const gchar *mime_type)
189 {
190         EvDocument    *document;
191         EvBackendInfo *info;
192
193         info = ev_backends_manager_get_backend_info (mime_type);
194         if (!info)
195                 return NULL;
196
197         if (!info->module) {
198                 gchar *path;
199                 
200                 path = g_module_build_path (EV_BACKENDSDIR, info->module_name);
201                 info->module = G_TYPE_MODULE (ev_module_new (path, info->resident));
202                 g_free (path);
203         }
204         
205         if (!g_type_module_use (info->module)) {
206                 g_warning ("Cannot load backend '%s' since file '%s' cannot be read.",
207                            info->module_name,
208                            ev_module_get_path (EV_MODULE (info->module)));
209                 g_object_unref (G_OBJECT (info->module));
210                 info->module = NULL;
211
212                 return NULL;
213         }
214
215         document = EV_DOCUMENT (ev_module_new_object (EV_MODULE (info->module)));
216         g_type_module_unuse (info->module);
217
218         return document;
219 }
220
221 static EvBackendInfo *
222 get_document_backend_info (EvDocument *document)
223 {
224         GList *l;
225
226         for (l = ev_backends_list; l; l = g_list_next (l)) {
227                 EvBackendInfo *info;
228                 GType          type_id;
229
230                 info = (EvBackendInfo *)l->data;
231
232                 if (!info->module)
233                         continue;
234
235                 type_id = ev_module_get_object_type (EV_MODULE (info->module));
236
237                 if (G_TYPE_CHECK_INSTANCE_TYPE (document, type_id)) {
238                         return info;
239                 }
240         }
241
242         return NULL;
243 }
244
245 const gchar *
246 ev_backends_manager_get_document_module_name (EvDocument *document)
247 {
248         EvBackendInfo *info;
249
250         info = get_document_backend_info (document);
251         return info ? info->module_name : NULL;
252 }
253
254 static EvTypeInfo *
255 ev_type_info_new (const gchar *desc, const gchar **mime_types)
256 {
257         EvTypeInfo *info;
258
259         info = g_new (EvTypeInfo, 1);
260
261         info->desc = desc;
262         info->mime_types = mime_types;
263
264         return info;
265 }
266
267 EvTypeInfo *
268 ev_backends_manager_get_document_type_info (EvDocument *document)
269 {
270         EvBackendInfo *info;
271
272         info = get_document_backend_info (document);
273         return info ?
274                 ev_type_info_new (info->type_desc,
275                                   (const gchar **)info->mime_types)
276                 : NULL;
277 }
278
279 GList *
280 ev_backends_manager_get_all_types_info (void)
281 {
282         GList *l;
283         GList *retval = NULL;
284
285         for (l = ev_backends_list; l; l = g_list_next (l)) {
286                 EvBackendInfo *info;
287                 EvTypeInfo    *type_info;
288
289                 info = (EvBackendInfo *)l->data;
290
291                 type_info = ev_type_info_new (info->type_desc,
292                                               (const gchar **)info->mime_types);
293                 retval = g_list_prepend (retval, type_info);
294         }
295
296         return retval;
297 }