]> www.fi.muni.cz Git - evince.git/blob - libdocument/ev-backends-manager.c
de8be24cbf96c6ef5f3fa04c3b70ffe30b077aa7
[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 ("%s", 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 ev_backends_list != NULL;
147 }
148
149 /*
150  * _ev_backends_manager_init:
151  *
152  * Initializes the evince backends manager.
153  *
154  * Returns: %TRUE if there were any backends found; %FALSE otherwise
155  */
156 gboolean
157 _ev_backends_manager_init (void)
158 {
159         if (ev_backends_list)
160                 return TRUE;
161
162         return ev_backends_manager_load ();
163 }
164
165 /*
166  * _ev_backends_manager_shutdown:
167  *
168  * Shuts the evince backends manager down.
169  */
170 void
171 _ev_backends_manager_shutdown (void)
172 {
173         g_list_foreach (ev_backends_list, (GFunc)ev_backend_info_free, NULL);
174         g_list_free (ev_backends_list);
175         ev_backends_list = NULL;
176 }
177
178 static EvBackendInfo *
179 ev_backends_manager_get_backend_info (const gchar *mime_type)
180 {
181         GList *l;
182
183         for (l = ev_backends_list; l; l = g_list_next (l)) {
184                 EvBackendInfo *info;
185                 gint           i = 0;
186                 const char    *mime;
187                 
188                 info = (EvBackendInfo *)l->data;
189                 
190                 while ((mime = info->mime_types[i++])) {
191                         if (g_ascii_strcasecmp (mime, mime_type) == 0)
192                                 return info;
193                 }
194         }
195
196         return NULL;
197 }
198
199 EvDocument *
200 ev_backends_manager_get_document (const gchar *mime_type)
201 {
202         EvDocument    *document;
203         EvBackendInfo *info;
204
205         info = ev_backends_manager_get_backend_info (mime_type);
206         if (!info)
207                 return NULL;
208
209         if (!info->module) {
210                 gchar *path;
211                 
212                 path = g_module_build_path (EV_BACKENDSDIR, info->module_name);
213                 info->module = G_TYPE_MODULE (ev_module_new (path, info->resident));
214                 g_free (path);
215         }
216         
217         if (!g_type_module_use (info->module)) {
218                 g_warning ("Cannot load backend '%s' since file '%s' cannot be read.",
219                            info->module_name,
220                            ev_module_get_path (EV_MODULE (info->module)));
221                 g_object_unref (G_OBJECT (info->module));
222                 info->module = NULL;
223
224                 return NULL;
225         }
226
227         document = EV_DOCUMENT (ev_module_new_object (EV_MODULE (info->module)));
228         g_type_module_unuse (info->module);
229
230         return document;
231 }
232
233 static EvBackendInfo *
234 get_document_backend_info (EvDocument *document)
235 {
236         GList *l;
237
238         for (l = ev_backends_list; l; l = g_list_next (l)) {
239                 EvBackendInfo *info;
240                 GType          type_id;
241
242                 info = (EvBackendInfo *)l->data;
243
244                 if (!info->module)
245                         continue;
246
247                 type_id = ev_module_get_object_type (EV_MODULE (info->module));
248
249                 if (G_TYPE_CHECK_INSTANCE_TYPE (document, type_id)) {
250                         return info;
251                 }
252         }
253
254         return NULL;
255 }
256
257 const gchar *
258 ev_backends_manager_get_document_module_name (EvDocument *document)
259 {
260         EvBackendInfo *info;
261
262         info = get_document_backend_info (document);
263         return info ? info->module_name : NULL;
264 }
265
266 static EvTypeInfo *
267 ev_type_info_new (const gchar *desc, const gchar **mime_types)
268 {
269         EvTypeInfo *info;
270
271         info = g_new (EvTypeInfo, 1);
272
273         info->desc = desc;
274         info->mime_types = mime_types;
275
276         return info;
277 }
278
279 EvTypeInfo *
280 ev_backends_manager_get_document_type_info (EvDocument *document)
281 {
282         EvBackendInfo *info;
283
284         info = get_document_backend_info (document);
285         return info ?
286                 ev_type_info_new (info->type_desc,
287                                   (const gchar **)info->mime_types)
288                 : NULL;
289 }
290
291 GList *
292 ev_backends_manager_get_all_types_info (void)
293 {
294         GList *l;
295         GList *retval = NULL;
296
297         for (l = ev_backends_list; l; l = g_list_next (l)) {
298                 EvBackendInfo *info;
299                 EvTypeInfo    *type_info;
300
301                 info = (EvBackendInfo *)l->data;
302
303                 type_info = ev_type_info_new (info->type_desc,
304                                               (const gchar **)info->mime_types);
305                 retval = g_list_prepend (retval, type_info);
306         }
307
308         return retval;
309 }