1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995-2002 Spencer Kimball, Peter Mattis, and others
3 *
4 * gimppluginmanager.c
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include "config.h"
21
22 #include <string.h>
23
24 #include <gdk-pixbuf/gdk-pixbuf.h>
25 #include <gegl.h>
26
27 #include "libgimpbase/gimpbase.h"
28 #include "libgimpconfig/gimpconfig.h"
29
30 #include "plug-in-types.h"
31
32 #include "config/gimpcoreconfig.h"
33
34 #include "core/gimp.h"
35 #include "core/gimp-filter-history.h"
36 #include "core/gimp-memsize.h"
37 #include "core/gimpmarshal.h"
38
39 #include "pdb/gimppdb.h"
40
41 #include "gimpenvirontable.h"
42 #include "gimpinterpreterdb.h"
43 #include "gimpplugin.h"
44 #include "gimpplugindebug.h"
45 #include "gimpplugindef.h"
46 #include "gimppluginmanager.h"
47 #include "gimppluginmanager-data.h"
48 #include "gimppluginmanager-help-domain.h"
49 #include "gimppluginmanager-locale-domain.h"
50 #include "gimppluginmanager-menu-branch.h"
51 #include "gimppluginshm.h"
52 #include "gimptemporaryprocedure.h"
53
54 #include "gimp-intl.h"
55
56
57 enum
58 {
59 PLUG_IN_OPENED,
60 PLUG_IN_CLOSED,
61 MENU_BRANCH_ADDED,
62 LAST_SIGNAL
63 };
64
65
66 static void gimp_plug_in_manager_finalize (GObject *object);
67
68 static gint64 gimp_plug_in_manager_get_memsize (GimpObject *object,
69 gint64 *gui_size);
70
71
72 G_DEFINE_TYPE (GimpPlugInManager, gimp_plug_in_manager, GIMP_TYPE_OBJECT)
73
74 #define parent_class gimp_plug_in_manager_parent_class
75
76 static guint manager_signals[LAST_SIGNAL] = { 0, };
77
78
79 static void
gimp_plug_in_manager_class_init(GimpPlugInManagerClass * klass)80 gimp_plug_in_manager_class_init (GimpPlugInManagerClass *klass)
81 {
82 GObjectClass *object_class = G_OBJECT_CLASS (klass);
83 GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
84
85 manager_signals[PLUG_IN_OPENED] =
86 g_signal_new ("plug-in-opened",
87 G_TYPE_FROM_CLASS (klass),
88 G_SIGNAL_RUN_LAST,
89 G_STRUCT_OFFSET (GimpPlugInManagerClass,
90 plug_in_opened),
91 NULL, NULL,
92 gimp_marshal_VOID__OBJECT,
93 G_TYPE_NONE, 1,
94 GIMP_TYPE_PLUG_IN);
95
96 manager_signals[PLUG_IN_CLOSED] =
97 g_signal_new ("plug-in-closed",
98 G_TYPE_FROM_CLASS (klass),
99 G_SIGNAL_RUN_LAST,
100 G_STRUCT_OFFSET (GimpPlugInManagerClass,
101 plug_in_closed),
102 NULL, NULL,
103 gimp_marshal_VOID__OBJECT,
104 G_TYPE_NONE, 1,
105 GIMP_TYPE_PLUG_IN);
106
107 manager_signals[MENU_BRANCH_ADDED] =
108 g_signal_new ("menu-branch-added",
109 G_TYPE_FROM_CLASS (klass),
110 G_SIGNAL_RUN_LAST,
111 G_STRUCT_OFFSET (GimpPlugInManagerClass,
112 menu_branch_added),
113 NULL, NULL,
114 gimp_marshal_VOID__OBJECT_STRING_STRING,
115 G_TYPE_NONE, 3,
116 G_TYPE_FILE,
117 G_TYPE_STRING,
118 G_TYPE_STRING);
119
120 object_class->finalize = gimp_plug_in_manager_finalize;
121
122 gimp_object_class->get_memsize = gimp_plug_in_manager_get_memsize;
123 }
124
125 static void
gimp_plug_in_manager_init(GimpPlugInManager * manager)126 gimp_plug_in_manager_init (GimpPlugInManager *manager)
127 {
128 }
129
130 static void
gimp_plug_in_manager_finalize(GObject * object)131 gimp_plug_in_manager_finalize (GObject *object)
132 {
133 GimpPlugInManager *manager = GIMP_PLUG_IN_MANAGER (object);
134
135 g_clear_pointer (&manager->load_procs, g_slist_free);
136 g_clear_pointer (&manager->save_procs, g_slist_free);
137 g_clear_pointer (&manager->export_procs, g_slist_free);
138 g_clear_pointer (&manager->raw_load_procs, g_slist_free);
139
140 g_clear_pointer (&manager->display_load_procs, g_slist_free);
141 g_clear_pointer (&manager->display_save_procs, g_slist_free);
142 g_clear_pointer (&manager->display_export_procs, g_slist_free);
143 g_clear_pointer (&manager->display_raw_load_procs, g_slist_free);
144
145 if (manager->plug_in_procedures)
146 {
147 g_slist_free_full (manager->plug_in_procedures,
148 (GDestroyNotify) g_object_unref);
149 manager->plug_in_procedures = NULL;
150 }
151
152 if (manager->plug_in_defs)
153 {
154 g_slist_free_full (manager->plug_in_defs,
155 (GDestroyNotify) g_object_unref);
156 manager->plug_in_defs = NULL;
157 }
158
159 g_clear_object (&manager->environ_table);
160 g_clear_object (&manager->interpreter_db);
161
162 g_clear_pointer (&manager->debug, gimp_plug_in_debug_free);
163
164 gimp_plug_in_manager_menu_branch_exit (manager);
165 gimp_plug_in_manager_locale_domain_exit (manager);
166 gimp_plug_in_manager_help_domain_exit (manager);
167 gimp_plug_in_manager_data_free (manager);
168
169 G_OBJECT_CLASS (parent_class)->finalize (object);
170 }
171
172 static gint64
gimp_plug_in_manager_get_memsize(GimpObject * object,gint64 * gui_size)173 gimp_plug_in_manager_get_memsize (GimpObject *object,
174 gint64 *gui_size)
175 {
176 GimpPlugInManager *manager = GIMP_PLUG_IN_MANAGER (object);
177 gint64 memsize = 0;
178
179 memsize += gimp_g_slist_get_memsize_foreach (manager->plug_in_defs,
180 (GimpMemsizeFunc)
181 gimp_object_get_memsize,
182 gui_size);
183
184 memsize += gimp_g_slist_get_memsize (manager->plug_in_procedures, 0);
185 memsize += gimp_g_slist_get_memsize (manager->load_procs, 0);
186 memsize += gimp_g_slist_get_memsize (manager->save_procs, 0);
187 memsize += gimp_g_slist_get_memsize (manager->export_procs, 0);
188 memsize += gimp_g_slist_get_memsize (manager->raw_load_procs, 0);
189 memsize += gimp_g_slist_get_memsize (manager->display_load_procs, 0);
190 memsize += gimp_g_slist_get_memsize (manager->display_save_procs, 0);
191 memsize += gimp_g_slist_get_memsize (manager->display_export_procs, 0);
192 memsize += gimp_g_slist_get_memsize (manager->display_raw_load_procs, 0);
193
194 memsize += gimp_g_slist_get_memsize (manager->menu_branches, 0 /* FIXME */);
195 memsize += gimp_g_slist_get_memsize (manager->locale_domains, 0 /* FIXME */);
196 memsize += gimp_g_slist_get_memsize (manager->help_domains, 0 /* FIXME */);
197
198 memsize += gimp_g_slist_get_memsize_foreach (manager->open_plug_ins,
199 (GimpMemsizeFunc)
200 gimp_object_get_memsize,
201 gui_size);
202 memsize += gimp_g_slist_get_memsize (manager->plug_in_stack, 0);
203
204 memsize += 0; /* FIXME manager->shm */
205 memsize += /* FIXME */ gimp_g_object_get_memsize (G_OBJECT (manager->interpreter_db));
206 memsize += /* FIXME */ gimp_g_object_get_memsize (G_OBJECT (manager->environ_table));
207 memsize += 0; /* FIXME manager->plug_in_debug */
208 memsize += gimp_g_list_get_memsize (manager->data_list, 0 /* FIXME */);
209
210 return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
211 gui_size);
212 }
213
214 GimpPlugInManager *
gimp_plug_in_manager_new(Gimp * gimp)215 gimp_plug_in_manager_new (Gimp *gimp)
216 {
217 GimpPlugInManager *manager;
218
219 manager = g_object_new (GIMP_TYPE_PLUG_IN_MANAGER, NULL);
220
221 manager->gimp = gimp;
222 manager->interpreter_db = gimp_interpreter_db_new (gimp->be_verbose);
223 manager->environ_table = gimp_environ_table_new (gimp->be_verbose);
224
225 return manager;
226 }
227
228 void
gimp_plug_in_manager_initialize(GimpPlugInManager * manager,GimpInitStatusFunc status_callback)229 gimp_plug_in_manager_initialize (GimpPlugInManager *manager,
230 GimpInitStatusFunc status_callback)
231 {
232 GimpCoreConfig *config;
233 GList *path;
234
235 g_return_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager));
236 g_return_if_fail (status_callback != NULL);
237
238 config = manager->gimp->config;
239
240 status_callback (NULL, _("Plug-in Interpreters"), 0.8);
241
242 path = gimp_config_path_expand_to_files (config->interpreter_path, NULL);
243 gimp_interpreter_db_load (manager->interpreter_db, path);
244 g_list_free_full (path, (GDestroyNotify) g_object_unref);
245
246 status_callback (NULL, _("Plug-in Environment"), 0.9);
247
248 path = gimp_config_path_expand_to_files (config->environ_path, NULL);
249 gimp_environ_table_load (manager->environ_table, path);
250 g_list_free_full (path, (GDestroyNotify) g_object_unref);
251
252 /* allocate a piece of shared memory for use in transporting tiles
253 * to plug-ins. if we can't allocate a piece of shared memory then
254 * we'll fall back on sending the data over the pipe.
255 */
256 if (manager->gimp->use_shm)
257 manager->shm = gimp_plug_in_shm_new ();
258
259 manager->debug = gimp_plug_in_debug_new ();
260 }
261
262 void
gimp_plug_in_manager_exit(GimpPlugInManager * manager)263 gimp_plug_in_manager_exit (GimpPlugInManager *manager)
264 {
265 g_return_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager));
266
267 while (manager->open_plug_ins)
268 gimp_plug_in_close (manager->open_plug_ins->data, TRUE);
269
270 /* need to detach from shared memory, we can't rely on exit()
271 * cleaning up behind us (see bug #609026)
272 */
273 if (manager->shm)
274 {
275 gimp_plug_in_shm_free (manager->shm);
276 manager->shm = NULL;
277 }
278 }
279
280 void
gimp_plug_in_manager_add_procedure(GimpPlugInManager * manager,GimpPlugInProcedure * procedure)281 gimp_plug_in_manager_add_procedure (GimpPlugInManager *manager,
282 GimpPlugInProcedure *procedure)
283 {
284 GSList *list;
285
286 g_return_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager));
287 g_return_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (procedure));
288
289 for (list = manager->plug_in_procedures; list; list = list->next)
290 {
291 GimpPlugInProcedure *tmp_proc = list->data;
292
293 if (strcmp (gimp_object_get_name (procedure),
294 gimp_object_get_name (tmp_proc)) == 0)
295 {
296 GSList *list2;
297
298 list->data = g_object_ref (procedure);
299
300 g_printerr ("Removing duplicate PDB procedure '%s' "
301 "registered by '%s'\n",
302 gimp_object_get_name (tmp_proc),
303 gimp_file_get_utf8_name (tmp_proc->file));
304
305 /* search the plugin list to see if any plugins had references to
306 * the tmp_proc.
307 */
308 for (list2 = manager->plug_in_defs; list2; list2 = list2->next)
309 {
310 GimpPlugInDef *plug_in_def = list2->data;
311
312 if (g_slist_find (plug_in_def->procedures, tmp_proc))
313 gimp_plug_in_def_remove_procedure (plug_in_def, tmp_proc);
314 }
315
316 /* also remove it from the lists of load, save and export procs */
317 manager->load_procs = g_slist_remove (manager->load_procs, tmp_proc);
318 manager->save_procs = g_slist_remove (manager->save_procs, tmp_proc);
319 manager->export_procs = g_slist_remove (manager->export_procs, tmp_proc);
320 manager->raw_load_procs = g_slist_remove (manager->raw_load_procs, tmp_proc);
321 manager->display_load_procs = g_slist_remove (manager->display_load_procs, tmp_proc);
322 manager->display_save_procs = g_slist_remove (manager->display_save_procs, tmp_proc);
323 manager->display_export_procs = g_slist_remove (manager->display_export_procs, tmp_proc);
324 manager->display_raw_load_procs = g_slist_remove (manager->display_raw_load_procs, tmp_proc);
325
326 /* and from the history */
327 gimp_filter_history_remove (manager->gimp, GIMP_PROCEDURE (tmp_proc));
328
329 g_object_unref (tmp_proc);
330
331 return;
332 }
333 }
334
335 manager->plug_in_procedures = g_slist_prepend (manager->plug_in_procedures,
336 g_object_ref (procedure));
337 }
338
339 void
gimp_plug_in_manager_add_temp_proc(GimpPlugInManager * manager,GimpTemporaryProcedure * procedure)340 gimp_plug_in_manager_add_temp_proc (GimpPlugInManager *manager,
341 GimpTemporaryProcedure *procedure)
342 {
343 g_return_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager));
344 g_return_if_fail (GIMP_IS_TEMPORARY_PROCEDURE (procedure));
345
346 gimp_pdb_register_procedure (manager->gimp->pdb, GIMP_PROCEDURE (procedure));
347
348 manager->plug_in_procedures = g_slist_prepend (manager->plug_in_procedures,
349 g_object_ref (procedure));
350 }
351
352 void
gimp_plug_in_manager_remove_temp_proc(GimpPlugInManager * manager,GimpTemporaryProcedure * procedure)353 gimp_plug_in_manager_remove_temp_proc (GimpPlugInManager *manager,
354 GimpTemporaryProcedure *procedure)
355 {
356 g_return_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager));
357 g_return_if_fail (GIMP_IS_TEMPORARY_PROCEDURE (procedure));
358
359 manager->plug_in_procedures = g_slist_remove (manager->plug_in_procedures,
360 procedure);
361
362 gimp_filter_history_remove (manager->gimp,
363 GIMP_PROCEDURE (procedure));
364
365 gimp_pdb_unregister_procedure (manager->gimp->pdb,
366 GIMP_PROCEDURE (procedure));
367
368 g_object_unref (procedure);
369 }
370
371 void
gimp_plug_in_manager_add_open_plug_in(GimpPlugInManager * manager,GimpPlugIn * plug_in)372 gimp_plug_in_manager_add_open_plug_in (GimpPlugInManager *manager,
373 GimpPlugIn *plug_in)
374 {
375 g_return_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager));
376 g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
377
378 manager->open_plug_ins = g_slist_prepend (manager->open_plug_ins,
379 g_object_ref (plug_in));
380
381 g_signal_emit (manager, manager_signals[PLUG_IN_OPENED], 0,
382 plug_in);
383 }
384
385 void
gimp_plug_in_manager_remove_open_plug_in(GimpPlugInManager * manager,GimpPlugIn * plug_in)386 gimp_plug_in_manager_remove_open_plug_in (GimpPlugInManager *manager,
387 GimpPlugIn *plug_in)
388 {
389 g_return_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager));
390 g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
391
392 manager->open_plug_ins = g_slist_remove (manager->open_plug_ins, plug_in);
393
394 g_signal_emit (manager, manager_signals[PLUG_IN_CLOSED], 0,
395 plug_in);
396
397 g_object_unref (plug_in);
398 }
399
400 void
gimp_plug_in_manager_plug_in_push(GimpPlugInManager * manager,GimpPlugIn * plug_in)401 gimp_plug_in_manager_plug_in_push (GimpPlugInManager *manager,
402 GimpPlugIn *plug_in)
403 {
404 g_return_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager));
405 g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
406
407 manager->current_plug_in = plug_in;
408
409 manager->plug_in_stack = g_slist_prepend (manager->plug_in_stack,
410 manager->current_plug_in);
411 }
412
413 void
gimp_plug_in_manager_plug_in_pop(GimpPlugInManager * manager)414 gimp_plug_in_manager_plug_in_pop (GimpPlugInManager *manager)
415 {
416 g_return_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager));
417
418 if (manager->current_plug_in)
419 manager->plug_in_stack = g_slist_remove (manager->plug_in_stack,
420 manager->plug_in_stack->data);
421
422 if (manager->plug_in_stack)
423 manager->current_plug_in = manager->plug_in_stack->data;
424 else
425 manager->current_plug_in = NULL;
426 }
427