1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3  * Libbrasero-burn
4  * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app@wanadoo.fr>
5  *
6  * Libbrasero-burn 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 2 of the License, or
9  * (at your option) any later version.
10  *
11  * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
12  * GStreamer plugins to be used and distributed together with GStreamer
13  * and Libbrasero-burn. This permission is above and beyond the permissions granted
14  * by the GPL license by which Libbrasero-burn is covered. If you modify this code
15  * you may extend this exception to your version of the code, but you are not
16  * obligated to do so. If you do not wish to do so, delete this exception
17  * statement from your version.
18  *
19  * Libbrasero-burn is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to:
26  * 	The Free Software Foundation, Inc.,
27  * 	51 Franklin Street, Fifth Floor
28  * 	Boston, MA  02110-1301, USA.
29  */
30 
31 #ifdef HAVE_CONFIG_H
32 #  include <config.h>
33 #endif
34 
35 #include <string.h>
36 
37 #include <glib.h>
38 #include <glib-object.h>
39 #include <gmodule.h>
40 #include <glib/gi18n-lib.h>
41 
42 #include <gst/gst.h>
43 
44 #include <stdio.h>
45 
46 #include "brasero-media-private.h"
47 
48 #include "brasero-media.h"
49 
50 #include "burn-basics.h"
51 #include "burn-debug.h"
52 #include "brasero-plugin.h"
53 #include "brasero-plugin-private.h"
54 #include "brasero-plugin-information.h"
55 #include "brasero-plugin-registration.h"
56 #include "burn-caps.h"
57 
58 #define BRASERO_SCHEMA_PLUGINS				"org.gnome.brasero.plugins"
59 #define BRASERO_PROPS_PRIORITY_KEY			"priority"
60 
61 typedef struct _BraseroPluginFlagPair BraseroPluginFlagPair;
62 
63 struct _BraseroPluginFlagPair {
64 	BraseroPluginFlagPair *next;
65 	BraseroBurnFlag supported;
66 	BraseroBurnFlag compulsory;
67 };
68 
69 struct _BraseroPluginFlags {
70 	BraseroMedia media;
71 	BraseroPluginFlagPair *pairs;
72 };
73 typedef struct _BraseroPluginFlags BraseroPluginFlags;
74 
75 struct _BraseroPluginConfOption {
76 	gchar *key;
77 	gchar *description;
78 	BraseroPluginConfOptionType type;
79 
80 	union {
81 		struct {
82 			guint max;
83 			guint min;
84 		} range;
85 
86 		GSList *suboptions;
87 
88 		GSList *choices;
89 	} specifics;
90 };
91 
92 typedef struct _BraseroPluginPrivate BraseroPluginPrivate;
93 struct _BraseroPluginPrivate
94 {
95 	GSettings *settings;
96 
97 	gboolean active;
98 	guint group;
99 
100 	GSList *options;
101 
102 	GSList *errors;
103 
104 	GType type;
105 	gchar *path;
106 	GModule *handle;
107 
108 	gchar *name;
109 	gchar *display_name;
110 	gchar *author;
111 	gchar *description;
112 	gchar *copyright;
113 	gchar *website;
114 
115 	guint notify_priority;
116 	guint priority_original;
117 	gint priority;
118 
119 	GSList *flags;
120 	GSList *blank_flags;
121 
122 	BraseroPluginProcessFlag process_flags;
123 
124 	guint compulsory:1;
125 };
126 
127 static const gchar *default_icon = "gtk-cdrom";
128 
129 #define BRASERO_PLUGIN_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_PLUGIN, BraseroPluginPrivate))
130 G_DEFINE_TYPE (BraseroPlugin, brasero_plugin, G_TYPE_TYPE_MODULE);
131 
132 enum
133 {
134 	PROP_0,
135 	PROP_PATH,
136 	PROP_PRIORITY
137 };
138 
139 enum
140 {
141 	LOADED_SIGNAL,
142 	ACTIVATED_SIGNAL,
143 	LAST_SIGNAL
144 };
145 
146 static GTypeModuleClass* parent_class = NULL;
147 static guint plugin_signals [LAST_SIGNAL] = { 0 };
148 
149 static void
brasero_plugin_error_free(BraseroPluginError * error)150 brasero_plugin_error_free (BraseroPluginError *error)
151 {
152 	g_free (error->detail);
153 	g_free (error);
154 }
155 
156 void
brasero_plugin_add_error(BraseroPlugin * plugin,BraseroPluginErrorType type,const gchar * detail)157 brasero_plugin_add_error (BraseroPlugin *plugin,
158                           BraseroPluginErrorType type,
159                           const gchar *detail)
160 {
161 	BraseroPluginError *error;
162 	BraseroPluginPrivate *priv;
163 
164 	g_return_if_fail (BRASERO_IS_PLUGIN (plugin));
165 
166 	priv = BRASERO_PLUGIN_PRIVATE (plugin);
167 
168 	error = g_new0 (BraseroPluginError, 1);
169 	error->detail = g_strdup (detail);
170 	error->type = type;
171 
172 	priv->errors = g_slist_prepend (priv->errors, error);
173 }
174 
175 void
brasero_plugin_test_gstreamer_plugin(BraseroPlugin * plugin,const gchar * name)176 brasero_plugin_test_gstreamer_plugin (BraseroPlugin *plugin,
177                                       const gchar *name)
178 {
179 	GstElement *element;
180 
181 	/* Let's see if we've got the plugins we need */
182 	element = gst_element_factory_make (name, NULL);
183 	if (!element)
184 		brasero_plugin_add_error (plugin,
185 		                          BRASERO_PLUGIN_ERROR_MISSING_GSTREAMER_PLUGIN,
186 		                          name);
187 	else
188 		gst_object_unref (element);
189 }
190 
191 void
brasero_plugin_test_app(BraseroPlugin * plugin,const gchar * name,const gchar * version_arg,const gchar * version_format,gint version[3])192 brasero_plugin_test_app (BraseroPlugin *plugin,
193                          const gchar *name,
194                          const gchar *version_arg,
195                          const gchar *version_format,
196                          gint version [3])
197 {
198 	gchar *standard_output = NULL;
199 	gchar *standard_error = NULL;
200 	guint major, minor, sub;
201 	gchar *prog_path;
202 	GPtrArray *argv;
203 	gboolean res;
204 	int i;
205 
206 	/* First see if this plugin can be used, i.e. if cdrecord is in
207 	 * the path */
208 	prog_path = g_find_program_in_path (name);
209 	if (!prog_path) {
210 		brasero_plugin_add_error (plugin,
211 		                          BRASERO_PLUGIN_ERROR_MISSING_APP,
212 		                          name);
213 		return;
214 	}
215 
216 	if (!g_file_test (prog_path, G_FILE_TEST_IS_EXECUTABLE)) {
217 		g_free (prog_path);
218 		brasero_plugin_add_error (plugin,
219 		                          BRASERO_PLUGIN_ERROR_MISSING_APP,
220 		                          name);
221 		return;
222 	}
223 
224 	/* make sure that's not a symlink pointing to something with another
225 	 * name like wodim.
226 	 * NOTE: we used to test the target and see if it had the same name as
227 	 * the symlink with GIO. The problem is, when the symlink pointed to
228 	 * another symlink, then GIO didn't follow that other symlink. And in
229 	 * the end it didn't work. So forbid all symlink. */
230 	if (g_file_test (prog_path, G_FILE_TEST_IS_SYMLINK)) {
231 		brasero_plugin_add_error (plugin,
232 		                          BRASERO_PLUGIN_ERROR_SYMBOLIC_LINK_APP,
233 		                          name);
234 		g_free (prog_path);
235 		return;
236 	}
237 	/* Make sure it's a regular file */
238 	else if (!g_file_test (prog_path, G_FILE_TEST_IS_REGULAR)) {
239 		brasero_plugin_add_error (plugin,
240 		                          BRASERO_PLUGIN_ERROR_MISSING_APP,
241 		                          name);
242 		g_free (prog_path);
243 		return;
244 	}
245 
246 	if (!version_arg) {
247 		g_free (prog_path);
248 		return;
249 	}
250 
251 	/* Check version */
252 	argv = g_ptr_array_new ();
253 	g_ptr_array_add (argv, prog_path);
254 	g_ptr_array_add (argv, (gchar *) version_arg);
255 	g_ptr_array_add (argv, NULL);
256 
257 	res = g_spawn_sync (NULL,
258 	                    (gchar **) argv->pdata,
259 	                    NULL,
260 	                    0,
261 	                    NULL,
262 	                    NULL,
263 	                    &standard_output,
264 	                    &standard_error,
265 	                    NULL,
266 	                    NULL);
267 
268 	g_ptr_array_free (argv, TRUE);
269 	g_free (prog_path);
270 
271 	if (!res) {
272 		brasero_plugin_add_error (plugin,
273 		                          BRASERO_PLUGIN_ERROR_WRONG_APP_VERSION,
274 		                          name);
275 		return;
276 	}
277 
278 	for (i = 0; i < 3 && version [i] >= 0; i++);
279 
280 	if ((standard_output && sscanf (standard_output, version_format, &major, &minor, &sub) == i)
281 	||  (standard_error && sscanf (standard_error, version_format, &major, &minor, &sub) == i)) {
282 		if (major < version [0]
283 		||  (version [1] >= 0 && minor < version [1])
284 		||  (version [2] >= 0 && sub < version [2]))
285 			brasero_plugin_add_error (plugin,
286 						  BRASERO_PLUGIN_ERROR_WRONG_APP_VERSION,
287 						  name);
288 	}
289 	else
290 		brasero_plugin_add_error (plugin,
291 		                          BRASERO_PLUGIN_ERROR_WRONG_APP_VERSION,
292 		                          name);
293 
294 	g_free (standard_output);
295 	g_free (standard_error);
296 }
297 
298 void
brasero_plugin_set_compulsory(BraseroPlugin * self,gboolean compulsory)299 brasero_plugin_set_compulsory (BraseroPlugin *self,
300 			       gboolean compulsory)
301 {
302 	BraseroPluginPrivate *priv;
303 
304 	priv = BRASERO_PLUGIN_PRIVATE (self);
305 	priv->compulsory = compulsory;
306 }
307 
308 gboolean
brasero_plugin_get_compulsory(BraseroPlugin * self)309 brasero_plugin_get_compulsory (BraseroPlugin *self)
310 {
311 	BraseroPluginPrivate *priv;
312 
313 	priv = BRASERO_PLUGIN_PRIVATE (self);
314 	return priv->compulsory;
315 }
316 
317 void
brasero_plugin_set_active(BraseroPlugin * self,gboolean active)318 brasero_plugin_set_active (BraseroPlugin *self, gboolean active)
319 {
320 	BraseroPluginPrivate *priv;
321 	gboolean was_active;
322 	gboolean now_active;
323 
324 	priv = BRASERO_PLUGIN_PRIVATE (self);
325 
326 	was_active = brasero_plugin_get_active (self, FALSE);
327 	priv->active = active;
328 
329 	now_active = brasero_plugin_get_active (self, FALSE);
330 	if (was_active == now_active)
331 		return;
332 
333 	BRASERO_BURN_LOG ("Plugin %s is %s",
334 			  brasero_plugin_get_name (self),
335 			  now_active?"active":"inactive");
336 
337 	g_signal_emit (self,
338 		       plugin_signals [ACTIVATED_SIGNAL],
339 		       0,
340 		       now_active);
341 }
342 
343 gboolean
brasero_plugin_get_active(BraseroPlugin * plugin,gboolean ignore_errors)344 brasero_plugin_get_active (BraseroPlugin *plugin,
345                            gboolean ignore_errors)
346 {
347 	BraseroPluginPrivate *priv;
348 
349 	priv = BRASERO_PLUGIN_PRIVATE (plugin);
350 
351 	if (priv->type == G_TYPE_NONE)
352 		return FALSE;
353 
354 	if (priv->priority < 0)
355 		return FALSE;
356 
357 	if (priv->errors) {
358 		if (!ignore_errors)
359 			return FALSE;
360 	}
361 
362 	return priv->active;
363 }
364 
365 static void
brasero_plugin_cleanup_definition(BraseroPlugin * self)366 brasero_plugin_cleanup_definition (BraseroPlugin *self)
367 {
368 	BraseroPluginPrivate *priv;
369 
370 	priv = BRASERO_PLUGIN_PRIVATE (self);
371 
372 	g_free (priv->name);
373 	priv->name = NULL;
374 	g_free (priv->author);
375 	priv->author = NULL;
376 	g_free (priv->description);
377 	priv->description = NULL;
378 	g_free (priv->copyright);
379 	priv->copyright = NULL;
380 	g_free (priv->website);
381 	priv->website = NULL;
382 }
383 
384 /**
385  * Plugin configure options
386  */
387 
388 static void
brasero_plugin_conf_option_choice_pair_free(BraseroPluginChoicePair * pair)389 brasero_plugin_conf_option_choice_pair_free (BraseroPluginChoicePair *pair)
390 {
391 	g_free (pair->string);
392 	g_free (pair);
393 }
394 
395 static void
brasero_plugin_conf_option_free(BraseroPluginConfOption * option)396 brasero_plugin_conf_option_free (BraseroPluginConfOption *option)
397 {
398 	if (option->type == BRASERO_PLUGIN_OPTION_BOOL)
399 		g_slist_free (option->specifics.suboptions);
400 
401 	if (option->type == BRASERO_PLUGIN_OPTION_CHOICE) {
402 		g_slist_foreach (option->specifics.choices, (GFunc) brasero_plugin_conf_option_choice_pair_free, NULL);
403 		g_slist_free (option->specifics.choices);
404 	}
405 
406 	g_free (option->key);
407 	g_free (option->description);
408 
409 	g_free (option);
410 }
411 
412 BraseroPluginConfOption *
brasero_plugin_get_next_conf_option(BraseroPlugin * self,BraseroPluginConfOption * current)413 brasero_plugin_get_next_conf_option (BraseroPlugin *self,
414 				     BraseroPluginConfOption *current)
415 {
416 	BraseroPluginPrivate *priv;
417 	GSList *node;
418 
419 	priv = BRASERO_PLUGIN_PRIVATE (self);
420 	if (!priv->options)
421 		return NULL;
422 
423 	if (!current)
424 		return priv->options->data;
425 
426 	node = g_slist_find (priv->options, current);
427 	if (!node)
428 		return NULL;
429 
430 	if (!node->next)
431 		return NULL;
432 
433 	return node->next->data;
434 }
435 
436 BraseroBurnResult
brasero_plugin_conf_option_get_info(BraseroPluginConfOption * option,gchar ** key,gchar ** description,BraseroPluginConfOptionType * type)437 brasero_plugin_conf_option_get_info (BraseroPluginConfOption *option,
438 				     gchar **key,
439 				     gchar **description,
440 				     BraseroPluginConfOptionType *type)
441 {
442 	g_return_val_if_fail (option != NULL, BRASERO_BURN_ERR);
443 
444 	if (key)
445 		*key = g_strdup (option->key);
446 
447 	if (description)
448 		*description = g_strdup (option->description);
449 
450 	if (type)
451 		*type = option->type;
452 
453 	return BRASERO_BURN_OK;
454 }
455 
456 BraseroPluginConfOption *
brasero_plugin_conf_option_new(const gchar * key,const gchar * description,BraseroPluginConfOptionType type)457 brasero_plugin_conf_option_new (const gchar *key,
458 				const gchar *description,
459 				BraseroPluginConfOptionType type)
460 {
461 	BraseroPluginConfOption *option;
462 
463 	g_return_val_if_fail (key != NULL, NULL);
464 	g_return_val_if_fail (description != NULL, NULL);
465 	g_return_val_if_fail (type != BRASERO_PLUGIN_OPTION_NONE, NULL);
466 
467 	option = g_new0 (BraseroPluginConfOption, 1);
468 	option->key = g_strdup (key);
469 	option->description = g_strdup (description);
470 	option->type = type;
471 
472 	return option;
473 }
474 
475 BraseroBurnResult
brasero_plugin_add_conf_option(BraseroPlugin * self,BraseroPluginConfOption * option)476 brasero_plugin_add_conf_option (BraseroPlugin *self,
477 				BraseroPluginConfOption *option)
478 {
479 	BraseroPluginPrivate *priv;
480 
481 	priv = BRASERO_PLUGIN_PRIVATE (self);
482 	priv->options = g_slist_append (priv->options, option);
483 
484 	return BRASERO_BURN_OK;
485 }
486 
487 BraseroBurnResult
brasero_plugin_conf_option_bool_add_suboption(BraseroPluginConfOption * option,BraseroPluginConfOption * suboption)488 brasero_plugin_conf_option_bool_add_suboption (BraseroPluginConfOption *option,
489 					       BraseroPluginConfOption *suboption)
490 {
491 	if (option->type != BRASERO_PLUGIN_OPTION_BOOL)
492 		return BRASERO_BURN_ERR;
493 
494 	option->specifics.suboptions = g_slist_prepend (option->specifics.suboptions,
495 						        suboption);
496 	return BRASERO_BURN_OK;
497 }
498 
499 BraseroBurnResult
brasero_plugin_conf_option_int_set_range(BraseroPluginConfOption * option,gint min,gint max)500 brasero_plugin_conf_option_int_set_range (BraseroPluginConfOption *option,
501 					  gint min,
502 					  gint max)
503 {
504 	if (option->type != BRASERO_PLUGIN_OPTION_INT)
505 		return BRASERO_BURN_ERR;
506 
507 	option->specifics.range.max = max;
508 	option->specifics.range.min = min;
509 	return BRASERO_BURN_OK;
510 }
511 
512 BraseroBurnResult
brasero_plugin_conf_option_choice_add(BraseroPluginConfOption * option,const gchar * string,gint value)513 brasero_plugin_conf_option_choice_add (BraseroPluginConfOption *option,
514 				       const gchar *string,
515 				       gint value)
516 {
517 	BraseroPluginChoicePair *pair;
518 
519 	if (option->type != BRASERO_PLUGIN_OPTION_CHOICE)
520 		return BRASERO_BURN_ERR;
521 
522 	pair = g_new0 (BraseroPluginChoicePair, 1);
523 	pair->value = value;
524 	pair->string = g_strdup (string);
525 	option->specifics.choices = g_slist_append (option->specifics.choices, pair);
526 
527 	return BRASERO_BURN_OK;
528 }
529 
530 GSList *
brasero_plugin_conf_option_bool_get_suboptions(BraseroPluginConfOption * option)531 brasero_plugin_conf_option_bool_get_suboptions (BraseroPluginConfOption *option)
532 {
533 	if (option->type != BRASERO_PLUGIN_OPTION_BOOL)
534 		return NULL;
535 	return option->specifics.suboptions;
536 }
537 
538 gint
brasero_plugin_conf_option_int_get_max(BraseroPluginConfOption * option)539 brasero_plugin_conf_option_int_get_max (BraseroPluginConfOption *option)
540 {
541 	if (option->type != BRASERO_PLUGIN_OPTION_INT)
542 		return -1;
543 	return option->specifics.range.max;
544 }
545 
546 gint
brasero_plugin_conf_option_int_get_min(BraseroPluginConfOption * option)547 brasero_plugin_conf_option_int_get_min (BraseroPluginConfOption *option)
548 {
549 	if (option->type != BRASERO_PLUGIN_OPTION_INT)
550 		return -1;
551 	return option->specifics.range.min;
552 }
553 
554 GSList *
brasero_plugin_conf_option_choice_get(BraseroPluginConfOption * option)555 brasero_plugin_conf_option_choice_get (BraseroPluginConfOption *option)
556 {
557 	if (option->type != BRASERO_PLUGIN_OPTION_CHOICE)
558 		return NULL;
559 	return option->specifics.choices;
560 }
561 
562 /**
563  * Used to set the caps of plugin
564  */
565 
566 void
brasero_plugin_define(BraseroPlugin * self,const gchar * name,const gchar * display_name,const gchar * description,const gchar * author,guint priority)567 brasero_plugin_define (BraseroPlugin *self,
568 		       const gchar *name,
569                        const gchar *display_name,
570                        const gchar *description,
571 		       const gchar *author,
572 		       guint priority)
573 {
574 	BraseroPluginPrivate *priv;
575 
576 	priv = BRASERO_PLUGIN_PRIVATE (self);
577 
578 	brasero_plugin_cleanup_definition (self);
579 
580 	priv->name = g_strdup (name);
581 	priv->display_name = g_strdup (display_name);
582 	priv->author = g_strdup (author);
583 	priv->description = g_strdup (description);
584 	priv->priority_original = priority;
585 }
586 
587 void
brasero_plugin_set_group(BraseroPlugin * self,gint group_id)588 brasero_plugin_set_group (BraseroPlugin *self,
589 			  gint group_id)
590 {
591 	BraseroPluginPrivate *priv;
592 
593 	priv = BRASERO_PLUGIN_PRIVATE (self);
594 	priv->group = group_id;
595 }
596 
597 guint
brasero_plugin_get_group(BraseroPlugin * self)598 brasero_plugin_get_group (BraseroPlugin *self)
599 {
600 	BraseroPluginPrivate *priv;
601 
602 	priv = BRASERO_PLUGIN_PRIVATE (self);
603 	return priv->group;
604 }
605 
606 /**
607  * brasero_plugin_get_errors:
608  * @plugin: a #BraseroPlugin.
609  *
610  * This function returns a list of all errors that
611  * prevents the plugin from working properly.
612  *
613  * Returns: a #GSList of #BraseroPluginError structures or %NULL.
614  * It must not be freed.
615  **/
616 
617 GSList *
brasero_plugin_get_errors(BraseroPlugin * plugin)618 brasero_plugin_get_errors (BraseroPlugin *plugin)
619 {
620 	BraseroPluginPrivate *priv;
621 
622 	g_return_val_if_fail (BRASERO_IS_PLUGIN (plugin), NULL);
623 	priv = BRASERO_PLUGIN_PRIVATE (plugin);
624 	return priv->errors;
625 }
626 
627 gchar *
brasero_plugin_get_error_string(BraseroPlugin * plugin)628 brasero_plugin_get_error_string (BraseroPlugin *plugin)
629 {
630 	gchar *error_string = NULL;
631 	BraseroPluginPrivate *priv;
632 	GString *string;
633 	GSList *iter;
634 
635 	g_return_val_if_fail (BRASERO_IS_PLUGIN (plugin), NULL);
636 
637 	priv = BRASERO_PLUGIN_PRIVATE (plugin);
638 
639 	string = g_string_new (NULL);
640 	for (iter = priv->errors; iter; iter = iter->next) {
641 		BraseroPluginError *error;
642 
643 		error = iter->data;
644 		switch (error->type) {
645 			case BRASERO_PLUGIN_ERROR_MISSING_APP:
646 				g_string_append_c (string, '\n');
647 				g_string_append_printf (string, _("\"%s\" could not be found in the path"), error->detail);
648 				break;
649 			case BRASERO_PLUGIN_ERROR_MISSING_GSTREAMER_PLUGIN:
650 				g_string_append_c (string, '\n');
651 				g_string_append_printf (string, _("\"%s\" GStreamer plugin could not be found"), error->detail);
652 				break;
653 			case BRASERO_PLUGIN_ERROR_WRONG_APP_VERSION:
654 				g_string_append_c (string, '\n');
655 				g_string_append_printf (string, _("The version of \"%s\" is too old"), error->detail);
656 				break;
657 			case BRASERO_PLUGIN_ERROR_SYMBOLIC_LINK_APP:
658 				g_string_append_c (string, '\n');
659 				g_string_append_printf (string, _("\"%s\" is a symbolic link pointing to another program"), error->detail);
660 				break;
661 			case BRASERO_PLUGIN_ERROR_MISSING_LIBRARY:
662 				g_string_append_c (string, '\n');
663 				g_string_append_printf (string, _("\"%s\" could not be found"), error->detail);
664 				break;
665 			case BRASERO_PLUGIN_ERROR_LIBRARY_VERSION:
666 				g_string_append_c (string, '\n');
667 				g_string_append_printf (string, _("The version of \"%s\" is too old"), error->detail);
668 				break;
669 			case BRASERO_PLUGIN_ERROR_MODULE:
670 				g_string_append_c (string, '\n');
671 				g_string_append (string, error->detail);
672 				break;
673 
674 			default:
675 				break;
676 		}
677 	}
678 
679 	error_string = string->str;
680 	g_string_free (string, FALSE);
681 	return error_string;
682 }
683 
684 static BraseroPluginFlags *
brasero_plugin_get_flags(GSList * flags,BraseroMedia media)685 brasero_plugin_get_flags (GSList *flags,
686 			  BraseroMedia media)
687 {
688 	GSList *iter;
689 
690 	for (iter = flags; iter; iter = iter->next) {
691 		BraseroPluginFlags *flags;
692 
693 		flags = iter->data;
694 		if ((media & flags->media) == media)
695 			return flags;
696 	}
697 
698 	return NULL;
699 }
700 
701 static GSList *
brasero_plugin_set_flags_real(GSList * flags_list,BraseroMedia media,BraseroBurnFlag supported,BraseroBurnFlag compulsory)702 brasero_plugin_set_flags_real (GSList *flags_list,
703 			       BraseroMedia media,
704 			       BraseroBurnFlag supported,
705 			       BraseroBurnFlag compulsory)
706 {
707 	BraseroPluginFlags *flags;
708 	BraseroPluginFlagPair *pair;
709 
710 	flags = brasero_plugin_get_flags (flags_list, media);
711 	if (!flags) {
712 		flags = g_new0 (BraseroPluginFlags, 1);
713 		flags->media = media;
714 		flags_list = g_slist_prepend (flags_list, flags);
715 	}
716 	else for (pair = flags->pairs; pair; pair = pair->next) {
717 		/* have a look at the BraseroPluginFlagPair to see if there
718 		 * is an exactly similar pair of flags or at least which
719 		 * encompasses it to avoid redundancy. */
720 		if ((pair->supported & supported) == supported
721 		&&  (pair->compulsory & compulsory) == compulsory)
722 			return flags_list;
723 	}
724 
725 	pair = g_new0 (BraseroPluginFlagPair, 1);
726 	pair->supported = supported;
727 	pair->compulsory = compulsory;
728 
729 	pair->next = flags->pairs;
730 	flags->pairs = pair;
731 
732 	return flags_list;
733 }
734 
735 void
brasero_plugin_set_flags(BraseroPlugin * self,BraseroMedia media,BraseroBurnFlag supported,BraseroBurnFlag compulsory)736 brasero_plugin_set_flags (BraseroPlugin *self,
737 			  BraseroMedia media,
738 			  BraseroBurnFlag supported,
739 			  BraseroBurnFlag compulsory)
740 {
741 	BraseroPluginPrivate *priv;
742 	GSList *list;
743 	GSList *iter;
744 
745 	priv = BRASERO_PLUGIN_PRIVATE (self);
746 
747 	list = brasero_media_get_all_list (media);
748 	for (iter = list; iter; iter = iter->next) {
749 		BraseroMedia medium;
750 
751 		medium = GPOINTER_TO_INT (iter->data);
752 		priv->flags = brasero_plugin_set_flags_real (priv->flags,
753 							     medium,
754 							     supported,
755 							     compulsory);
756 	}
757 	g_slist_free (list);
758 }
759 
760 static gboolean
brasero_plugin_get_all_flags(GSList * flags_list,gboolean check_compulsory,BraseroMedia media,BraseroBurnFlag mask,BraseroBurnFlag current,BraseroBurnFlag * supported_retval,BraseroBurnFlag * compulsory_retval)761 brasero_plugin_get_all_flags (GSList *flags_list,
762 			      gboolean check_compulsory,
763 			      BraseroMedia media,
764 			      BraseroBurnFlag mask,
765 			      BraseroBurnFlag current,
766 			      BraseroBurnFlag *supported_retval,
767 			      BraseroBurnFlag *compulsory_retval)
768 {
769 	gboolean found;
770 	BraseroPluginFlags *flags;
771 	BraseroPluginFlagPair *iter;
772 	BraseroBurnFlag supported = BRASERO_BURN_FLAG_NONE;
773 	BraseroBurnFlag compulsory = (BRASERO_BURN_FLAG_ALL & mask);
774 
775 	flags = brasero_plugin_get_flags (flags_list, media);
776 	if (!flags) {
777 		if (supported_retval)
778 			*supported_retval = BRASERO_BURN_FLAG_NONE;
779 		if (compulsory_retval)
780 			*compulsory_retval = BRASERO_BURN_FLAG_NONE;
781 		return FALSE;
782 	}
783 
784 	/* Find all sets of flags that support the current flags */
785 	found = FALSE;
786 	for (iter = flags->pairs; iter; iter = iter->next) {
787 		BraseroBurnFlag compulsory_masked;
788 
789 		if ((current & iter->supported) != current)
790 			continue;
791 
792 		compulsory_masked = (iter->compulsory & mask);
793 		if (check_compulsory
794 		&& (current & compulsory_masked) != compulsory_masked)
795 			continue;
796 
797 		supported |= iter->supported;
798 		compulsory &= compulsory_masked;
799 		found = TRUE;
800 	}
801 
802 	if (!found) {
803 		if (supported_retval)
804 			*supported_retval = BRASERO_BURN_FLAG_NONE;
805 		if (compulsory_retval)
806 			*compulsory_retval = BRASERO_BURN_FLAG_NONE;
807 		return FALSE;
808 	}
809 
810 	if (supported_retval)
811 		*supported_retval = supported;
812 	if (compulsory_retval)
813 		*compulsory_retval = compulsory;
814 
815 	return TRUE;
816 }
817 
818 gboolean
brasero_plugin_check_record_flags(BraseroPlugin * self,BraseroMedia media,BraseroBurnFlag current)819 brasero_plugin_check_record_flags (BraseroPlugin *self,
820 				   BraseroMedia media,
821 				   BraseroBurnFlag current)
822 {
823 	BraseroPluginPrivate *priv;
824 
825 	priv = BRASERO_PLUGIN_PRIVATE (self);
826 	current &= BRASERO_PLUGIN_BURN_FLAG_MASK;
827 
828 	return brasero_plugin_get_all_flags (priv->flags,
829 					     TRUE,
830 					     media,
831 					     BRASERO_PLUGIN_BURN_FLAG_MASK,
832 					     current,
833 					     NULL,
834 					     NULL);
835 }
836 
837 gboolean
brasero_plugin_check_image_flags(BraseroPlugin * self,BraseroMedia media,BraseroBurnFlag current)838 brasero_plugin_check_image_flags (BraseroPlugin *self,
839 				  BraseroMedia media,
840 				  BraseroBurnFlag current)
841 {
842 	BraseroPluginPrivate *priv;
843 
844 	priv = BRASERO_PLUGIN_PRIVATE (self);
845 
846 	current &= BRASERO_PLUGIN_IMAGE_FLAG_MASK;
847 
848 	/* If there is no flag that's no use checking anything. If there is no
849 	 * flag we don't care about the media and therefore it's always possible
850 	 * NOTE: that's no the case for other operation like burn/blank. */
851 	if (current == BRASERO_BURN_FLAG_NONE)
852 		return TRUE;
853 
854 	return brasero_plugin_get_all_flags (priv->flags,
855 					     TRUE,
856 					     media,
857 					     BRASERO_PLUGIN_IMAGE_FLAG_MASK,
858 					     current,
859 					     NULL,
860 					     NULL);
861 }
862 
863 gboolean
brasero_plugin_check_media_restrictions(BraseroPlugin * self,BraseroMedia media)864 brasero_plugin_check_media_restrictions (BraseroPlugin *self,
865 					 BraseroMedia media)
866 {
867 	BraseroPluginPrivate *priv;
868 
869 	priv = BRASERO_PLUGIN_PRIVATE (self);
870 
871 	/* no restrictions */
872 	if (!priv->flags)
873 		return TRUE;
874 
875 	return (brasero_plugin_get_flags (priv->flags, media) != NULL);
876 }
877 
878 gboolean
brasero_plugin_get_record_flags(BraseroPlugin * self,BraseroMedia media,BraseroBurnFlag current,BraseroBurnFlag * supported,BraseroBurnFlag * compulsory)879 brasero_plugin_get_record_flags (BraseroPlugin *self,
880 				 BraseroMedia media,
881 				 BraseroBurnFlag current,
882 				 BraseroBurnFlag *supported,
883 				 BraseroBurnFlag *compulsory)
884 {
885 	BraseroPluginPrivate *priv;
886 	gboolean result;
887 
888 	priv = BRASERO_PLUGIN_PRIVATE (self);
889 	current &= BRASERO_PLUGIN_BURN_FLAG_MASK;
890 
891 	result = brasero_plugin_get_all_flags (priv->flags,
892 					       FALSE,
893 					       media,
894 					       BRASERO_PLUGIN_BURN_FLAG_MASK,
895 					       current,
896 					       supported,
897 					       compulsory);
898 	if (!result)
899 		return FALSE;
900 
901 	if (supported)
902 		*supported &= BRASERO_PLUGIN_BURN_FLAG_MASK;
903 	if (compulsory)
904 		*compulsory &= BRASERO_PLUGIN_BURN_FLAG_MASK;
905 
906 	return TRUE;
907 }
908 
909 gboolean
brasero_plugin_get_image_flags(BraseroPlugin * self,BraseroMedia media,BraseroBurnFlag current,BraseroBurnFlag * supported,BraseroBurnFlag * compulsory)910 brasero_plugin_get_image_flags (BraseroPlugin *self,
911 				BraseroMedia media,
912 				BraseroBurnFlag current,
913 				BraseroBurnFlag *supported,
914 				BraseroBurnFlag *compulsory)
915 {
916 	BraseroPluginPrivate *priv;
917 	gboolean result;
918 
919 	priv = BRASERO_PLUGIN_PRIVATE (self);
920 	current &= BRASERO_PLUGIN_IMAGE_FLAG_MASK;
921 
922 	result = brasero_plugin_get_all_flags (priv->flags,
923 					       FALSE,
924 					       media,
925 					       BRASERO_PLUGIN_IMAGE_FLAG_MASK,
926 					       current,
927 					       supported,
928 					       compulsory);
929 	if (!result)
930 		return FALSE;
931 
932 	if (supported)
933 		*supported &= BRASERO_PLUGIN_IMAGE_FLAG_MASK;
934 	if (compulsory)
935 		*compulsory &= BRASERO_PLUGIN_IMAGE_FLAG_MASK;
936 
937 	return TRUE;
938 }
939 
940 void
brasero_plugin_set_blank_flags(BraseroPlugin * self,BraseroMedia media,BraseroBurnFlag supported,BraseroBurnFlag compulsory)941 brasero_plugin_set_blank_flags (BraseroPlugin *self,
942 				BraseroMedia media,
943 				BraseroBurnFlag supported,
944 				BraseroBurnFlag compulsory)
945 {
946 	BraseroPluginPrivate *priv;
947 
948 	priv = BRASERO_PLUGIN_PRIVATE (self);
949 	priv->blank_flags = brasero_plugin_set_flags_real (priv->blank_flags,
950 							   media,
951 							   supported,
952 							   compulsory);
953 }
954 
955 gboolean
brasero_plugin_check_blank_flags(BraseroPlugin * self,BraseroMedia media,BraseroBurnFlag current)956 brasero_plugin_check_blank_flags (BraseroPlugin *self,
957 				  BraseroMedia media,
958 				  BraseroBurnFlag current)
959 {
960 	BraseroPluginPrivate *priv;
961 
962 	priv = BRASERO_PLUGIN_PRIVATE (self);
963 	current &= BRASERO_PLUGIN_BLANK_FLAG_MASK;
964 
965 	return brasero_plugin_get_all_flags (priv->blank_flags,
966 					     TRUE,
967 					     media,
968 					     BRASERO_PLUGIN_BLANK_FLAG_MASK,
969 					     current,
970 					     NULL,
971 					     NULL);
972 }
973 
974 gboolean
brasero_plugin_get_blank_flags(BraseroPlugin * self,BraseroMedia media,BraseroBurnFlag current,BraseroBurnFlag * supported,BraseroBurnFlag * compulsory)975 brasero_plugin_get_blank_flags (BraseroPlugin *self,
976 				BraseroMedia media,
977 				BraseroBurnFlag current,
978 			        BraseroBurnFlag *supported,
979 			        BraseroBurnFlag *compulsory)
980 {
981 	BraseroPluginPrivate *priv;
982 	gboolean result;
983 
984 	priv = BRASERO_PLUGIN_PRIVATE (self);
985 	current &= BRASERO_PLUGIN_BLANK_FLAG_MASK;
986 
987 	result = brasero_plugin_get_all_flags (priv->blank_flags,
988 					       FALSE,
989 					       media,
990 					       BRASERO_PLUGIN_BLANK_FLAG_MASK,
991 					       current,
992 					       supported,
993 					       compulsory);
994 	if (!result)
995 		return FALSE;
996 
997 	if (supported)
998 		*supported &= BRASERO_PLUGIN_BLANK_FLAG_MASK;
999 	if (compulsory)
1000 		*compulsory &= BRASERO_PLUGIN_BLANK_FLAG_MASK;
1001 
1002 	return TRUE;
1003 }
1004 
1005 void
brasero_plugin_set_process_flags(BraseroPlugin * plugin,BraseroPluginProcessFlag flags)1006 brasero_plugin_set_process_flags (BraseroPlugin *plugin,
1007 				  BraseroPluginProcessFlag flags)
1008 {
1009 	BraseroPluginPrivate *priv;
1010 
1011 	priv = BRASERO_PLUGIN_PRIVATE (plugin);
1012 	priv->process_flags = flags;
1013 }
1014 
1015 gboolean
brasero_plugin_get_process_flags(BraseroPlugin * plugin,BraseroPluginProcessFlag * flags)1016 brasero_plugin_get_process_flags (BraseroPlugin *plugin,
1017 				  BraseroPluginProcessFlag *flags)
1018 {
1019 	BraseroPluginPrivate *priv;
1020 
1021 	g_return_val_if_fail (flags != NULL, FALSE);
1022 
1023 	priv = BRASERO_PLUGIN_PRIVATE (plugin);
1024 	*flags = priv->process_flags;
1025 	return TRUE;
1026 }
1027 
1028 const gchar *
brasero_plugin_get_name(BraseroPlugin * plugin)1029 brasero_plugin_get_name (BraseroPlugin *plugin)
1030 {
1031 	BraseroPluginPrivate *priv;
1032 
1033 	priv = BRASERO_PLUGIN_PRIVATE (plugin);
1034 	return priv->name;
1035 }
1036 
1037 const gchar *
brasero_plugin_get_display_name(BraseroPlugin * plugin)1038 brasero_plugin_get_display_name (BraseroPlugin *plugin)
1039 {
1040 	BraseroPluginPrivate *priv;
1041 
1042 	priv = BRASERO_PLUGIN_PRIVATE (plugin);
1043 	return priv->display_name ? priv->display_name:priv->name;
1044 
1045 }
1046 
1047 const gchar *
brasero_plugin_get_author(BraseroPlugin * plugin)1048 brasero_plugin_get_author (BraseroPlugin *plugin)
1049 {
1050 	BraseroPluginPrivate *priv;
1051 
1052 	priv = BRASERO_PLUGIN_PRIVATE (plugin);
1053 	return priv->author;
1054 }
1055 
1056 const gchar *
brasero_plugin_get_copyright(BraseroPlugin * plugin)1057 brasero_plugin_get_copyright (BraseroPlugin *plugin)
1058 {
1059 	BraseroPluginPrivate *priv;
1060 
1061 	priv = BRASERO_PLUGIN_PRIVATE (plugin);
1062 	return priv->copyright;
1063 }
1064 
1065 const gchar *
brasero_plugin_get_website(BraseroPlugin * plugin)1066 brasero_plugin_get_website (BraseroPlugin *plugin)
1067 {
1068 	BraseroPluginPrivate *priv;
1069 
1070 	priv = BRASERO_PLUGIN_PRIVATE (plugin);
1071 	return priv->website;
1072 }
1073 
1074 const gchar *
brasero_plugin_get_description(BraseroPlugin * plugin)1075 brasero_plugin_get_description (BraseroPlugin *plugin)
1076 {
1077 	BraseroPluginPrivate *priv;
1078 
1079 	priv = BRASERO_PLUGIN_PRIVATE (plugin);
1080 	return priv->description;
1081 }
1082 
1083 const gchar *
brasero_plugin_get_icon_name(BraseroPlugin * plugin)1084 brasero_plugin_get_icon_name (BraseroPlugin *plugin)
1085 {
1086 	return default_icon;
1087 }
1088 
1089 guint
brasero_plugin_get_priority(BraseroPlugin * self)1090 brasero_plugin_get_priority (BraseroPlugin *self)
1091 {
1092 	BraseroPluginPrivate *priv;
1093 
1094 	priv = BRASERO_PLUGIN_PRIVATE (self);
1095 
1096 	if (priv->priority > 0)
1097 		return priv->priority;
1098 
1099 	return priv->priority_original;
1100 }
1101 
1102 GType
brasero_plugin_get_gtype(BraseroPlugin * self)1103 brasero_plugin_get_gtype (BraseroPlugin *self)
1104 {
1105 	BraseroPluginPrivate *priv;
1106 
1107 	priv = BRASERO_PLUGIN_PRIVATE (self);
1108 
1109 	if (priv->errors)
1110 		return G_TYPE_NONE;
1111 
1112 	return priv->type;
1113 }
1114 
1115 /**
1116  * Function to initialize and load
1117  */
1118 
1119 static void
brasero_plugin_unload(GTypeModule * module)1120 brasero_plugin_unload (GTypeModule *module)
1121 {
1122 	BraseroPluginPrivate *priv;
1123 
1124 	priv = BRASERO_PLUGIN_PRIVATE (module);
1125 	if (!priv->handle)
1126 		return;
1127 
1128 	g_module_close (priv->handle);
1129 	priv->handle = NULL;
1130 }
1131 
1132 static gboolean
brasero_plugin_load_real(BraseroPlugin * plugin)1133 brasero_plugin_load_real (BraseroPlugin *plugin)
1134 {
1135 	BraseroPluginPrivate *priv;
1136 	BraseroPluginRegisterType register_func;
1137 
1138 	priv = BRASERO_PLUGIN_PRIVATE (plugin);
1139 
1140 	if (!priv->path)
1141 		return FALSE;
1142 
1143 	if (priv->handle)
1144 		return TRUE;
1145 
1146 	priv->handle = g_module_open (priv->path, G_MODULE_BIND_LAZY);
1147 	if (!priv->handle) {
1148 		brasero_plugin_add_error (plugin, BRASERO_PLUGIN_ERROR_MODULE, g_module_error ());
1149 		BRASERO_BURN_LOG ("Module %s can't be loaded: g_module_open failed ()", priv->name);
1150 		return FALSE;
1151 	}
1152 
1153 	if (!g_module_symbol (priv->handle, "brasero_plugin_register", (gpointer) &register_func)) {
1154 		BRASERO_BURN_LOG ("it doesn't appear to be a valid brasero plugin");
1155 		brasero_plugin_unload (G_TYPE_MODULE (plugin));
1156 		return FALSE;
1157 	}
1158 
1159 	priv->type = register_func (plugin);
1160 	brasero_burn_debug_setup_module (priv->handle);
1161 	return TRUE;
1162 }
1163 
1164 static gboolean
brasero_plugin_load(GTypeModule * module)1165 brasero_plugin_load (GTypeModule *module)
1166 {
1167 	if (!brasero_plugin_load_real (BRASERO_PLUGIN (module)))
1168 		return FALSE;
1169 
1170 	g_signal_emit (BRASERO_PLUGIN (module),
1171 		       plugin_signals [LOADED_SIGNAL],
1172 		       0);
1173 	return TRUE;
1174 }
1175 
1176 static void
brasero_plugin_priority_changed(GSettings * settings,const gchar * key,BraseroPlugin * self)1177 brasero_plugin_priority_changed (GSettings *settings,
1178                                  const gchar *key,
1179                                  BraseroPlugin *self)
1180 {
1181 	BraseroPluginPrivate *priv;
1182 	gboolean is_active;
1183 
1184 	priv = BRASERO_PLUGIN_PRIVATE (self);
1185 
1186 	/* At the moment it can only be the priority key */
1187 	priv->priority = g_settings_get_int (settings, BRASERO_PROPS_PRIORITY_KEY);
1188 
1189 	is_active = brasero_plugin_get_active (self, FALSE);
1190 
1191 	g_object_notify (G_OBJECT (self), "priority");
1192 	if (is_active != brasero_plugin_get_active (self, FALSE))
1193 		g_signal_emit (self,
1194 			       plugin_signals [ACTIVATED_SIGNAL],
1195 			       0,
1196 			       is_active);
1197 }
1198 
1199 typedef void	(* BraseroPluginCheckConfig)	(BraseroPlugin *plugin);
1200 
1201 /**
1202  * brasero_plugin_check_plugin_ready:
1203  * @plugin: a #BraseroPlugin.
1204  *
1205  * Ask a plugin to check whether it can operate.
1206  * brasero_plugin_can_operate () should be called
1207  * afterwards to know whether it can operate or not.
1208  *
1209  **/
1210 void
brasero_plugin_check_plugin_ready(BraseroPlugin * plugin)1211 brasero_plugin_check_plugin_ready (BraseroPlugin *plugin)
1212 {
1213 	GModule *handle;
1214 	BraseroPluginPrivate *priv;
1215 	BraseroPluginCheckConfig function = NULL;
1216 
1217 	g_return_if_fail (BRASERO_IS_PLUGIN (plugin));
1218 	priv = BRASERO_PLUGIN_PRIVATE (plugin);
1219 
1220 	if (priv->errors) {
1221 		g_slist_foreach (priv->errors, (GFunc) brasero_plugin_error_free, NULL);
1222 		g_slist_free (priv->errors);
1223 		priv->errors = NULL;
1224 	}
1225 
1226 	handle = g_module_open (priv->path, 0);
1227 	if (!handle) {
1228 		brasero_plugin_add_error (plugin, BRASERO_PLUGIN_ERROR_MODULE, g_module_error ());
1229 		BRASERO_BURN_LOG ("Module %s can't be loaded: g_module_open failed ()", priv->name);
1230 		return;
1231 	}
1232 
1233 	if (!g_module_symbol (handle, "brasero_plugin_check_config", (gpointer) &function)) {
1234 		g_module_close (handle);
1235 		BRASERO_BURN_LOG ("Module %s has no check config function", priv->name);
1236 		return;
1237 	}
1238 
1239 	function (BRASERO_PLUGIN (plugin));
1240 	g_module_close (handle);
1241 }
1242 
1243 static void
brasero_plugin_init_real(BraseroPlugin * object)1244 brasero_plugin_init_real (BraseroPlugin *object)
1245 {
1246 	GModule *handle;
1247 	gchar *settings_path;
1248 	BraseroPluginPrivate *priv;
1249 	BraseroPluginRegisterType function = NULL;
1250 
1251 	priv = BRASERO_PLUGIN_PRIVATE (object);
1252 
1253 	g_type_module_set_name (G_TYPE_MODULE (object), priv->name);
1254 
1255 	handle = g_module_open (priv->path, 0);
1256 	if (!handle) {
1257 		brasero_plugin_add_error (object, BRASERO_PLUGIN_ERROR_MODULE, g_module_error ());
1258 		BRASERO_BURN_LOG ("Module %s (at %s) can't be loaded: g_module_open failed ()", priv->name, priv->path);
1259 		return;
1260 	}
1261 
1262 	if (!g_module_symbol (handle, "brasero_plugin_register", (gpointer) &function)) {
1263 		g_module_close (handle);
1264 		BRASERO_BURN_LOG ("Module %s can't be loaded: no register function, priv->name", priv->name);
1265 		return;
1266 	}
1267 
1268 	priv->type = function (object);
1269 	if (priv->type == G_TYPE_NONE) {
1270 		g_module_close (handle);
1271 		BRASERO_BURN_LOG ("Module %s encountered an error while registering its capabilities", priv->name);
1272 		return;
1273 	}
1274 
1275 	/* now see if we need to override the hardcoded priority of the plugin */
1276 	settings_path = g_strconcat ("/org/gnome/brasero/plugins/",
1277 	                             priv->name,
1278 	                             G_DIR_SEPARATOR_S,
1279 	                             NULL);
1280 	priv->settings = g_settings_new_with_path (BRASERO_SCHEMA_PLUGINS,
1281 	                                           settings_path);
1282 	g_free (settings_path);
1283 
1284 	priv->priority = g_settings_get_int (priv->settings, BRASERO_PROPS_PRIORITY_KEY);
1285 
1286 	/* Make sure a key is created for each plugin */
1287 	if (!priv->priority)
1288 		g_settings_set_int (priv->settings, BRASERO_PROPS_PRIORITY_KEY, 0);
1289 
1290 	g_signal_connect (priv->settings,
1291 	                  "changed",
1292 	                  G_CALLBACK (brasero_plugin_priority_changed),
1293 	                  object);
1294 
1295 	/* Check if it can operate */
1296 	brasero_plugin_check_plugin_ready (object);
1297 
1298 	g_module_close (handle);
1299 }
1300 
1301 static void
brasero_plugin_finalize(GObject * object)1302 brasero_plugin_finalize (GObject *object)
1303 {
1304 	BraseroPluginPrivate *priv;
1305 
1306 	priv = BRASERO_PLUGIN_PRIVATE (object);
1307 
1308 	if (priv->options) {
1309 		g_slist_foreach (priv->options, (GFunc) brasero_plugin_conf_option_free, NULL);
1310 		g_slist_free (priv->options);
1311 		priv->options = NULL;
1312 	}
1313 
1314 	if (priv->handle) {
1315 		brasero_plugin_unload (G_TYPE_MODULE (object));
1316 		priv->handle = NULL;
1317 	}
1318 
1319 	if (priv->path) {
1320 		g_free (priv->path);
1321 		priv->path = NULL;
1322 	}
1323 
1324 	g_free (priv->name);
1325 	g_free (priv->display_name);
1326 	g_free (priv->author);
1327 	g_free (priv->description);
1328 
1329 	g_slist_foreach (priv->flags, (GFunc) g_free, NULL);
1330 	g_slist_free (priv->flags);
1331 
1332 	g_slist_foreach (priv->blank_flags, (GFunc) g_free, NULL);
1333 	g_slist_free (priv->blank_flags);
1334 
1335 	if (priv->settings) {
1336 		g_object_unref (priv->settings);
1337 		priv->settings = NULL;
1338 	}
1339 
1340 	if (priv->errors) {
1341 		g_slist_foreach (priv->errors, (GFunc) brasero_plugin_error_free, NULL);
1342 		g_slist_free (priv->errors);
1343 		priv->errors = NULL;
1344 	}
1345 
1346 	G_OBJECT_CLASS (parent_class)->finalize (object);
1347 }
1348 
1349 static void
brasero_plugin_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1350 brasero_plugin_set_property (GObject *object,
1351 			     guint prop_id,
1352 			     const GValue *value,
1353 			     GParamSpec *pspec)
1354 {
1355 	BraseroPlugin *self;
1356 	BraseroPluginPrivate *priv;
1357 
1358 	g_return_if_fail (BRASERO_IS_PLUGIN (object));
1359 
1360 	self = BRASERO_PLUGIN (object);
1361 	priv = BRASERO_PLUGIN_PRIVATE (self);
1362 
1363 	switch (prop_id)
1364 	{
1365 	case PROP_PATH:
1366 		/* NOTE: this property can only be set once */
1367 		priv->path = g_strdup (g_value_get_string (value));
1368 		brasero_plugin_init_real (self);
1369 		break;
1370 	case PROP_PRIORITY:
1371 		break;
1372 	default:
1373 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1374 		break;
1375 	}
1376 }
1377 
1378 static void
brasero_plugin_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1379 brasero_plugin_get_property (GObject *object,
1380 			     guint prop_id,
1381 			     GValue *value,
1382 			     GParamSpec *pspec)
1383 {
1384 	BraseroPlugin *self;
1385 	BraseroPluginPrivate *priv;
1386 
1387 	g_return_if_fail (BRASERO_IS_PLUGIN (object));
1388 
1389 	self = BRASERO_PLUGIN (object);
1390 	priv = BRASERO_PLUGIN_PRIVATE (self);
1391 
1392 	switch (prop_id)
1393 	{
1394 	case PROP_PATH:
1395 		g_value_set_string (value, priv->path);
1396 		break;
1397 	case PROP_PRIORITY:
1398 		g_value_set_int (value, priv->priority);
1399 		break;
1400 	default:
1401 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1402 		break;
1403 	}
1404 }
1405 
1406 static void
brasero_plugin_init(BraseroPlugin * object)1407 brasero_plugin_init (BraseroPlugin *object)
1408 {
1409 	BraseroPluginPrivate *priv;
1410 
1411 	priv = BRASERO_PLUGIN_PRIVATE (object);
1412 	priv->type = G_TYPE_NONE;
1413 	priv->compulsory = TRUE;
1414 }
1415 
1416 static void
brasero_plugin_class_init(BraseroPluginClass * klass)1417 brasero_plugin_class_init (BraseroPluginClass *klass)
1418 {
1419 	GObjectClass* object_class = G_OBJECT_CLASS (klass);
1420 	GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (klass);
1421 
1422 	g_type_class_add_private (klass, sizeof (BraseroPluginPrivate));
1423 
1424 	object_class->finalize = brasero_plugin_finalize;
1425 	object_class->set_property = brasero_plugin_set_property;
1426 	object_class->get_property = brasero_plugin_get_property;
1427 
1428 	module_class->load = brasero_plugin_load;
1429 	module_class->unload = brasero_plugin_unload;
1430 
1431 	g_object_class_install_property (object_class,
1432 	                                 PROP_PATH,
1433 	                                 g_param_spec_string ("path",
1434 	                                                      "Path",
1435 	                                                      "Path for the module",
1436 	                                                      NULL,
1437 	                                                      G_PARAM_STATIC_NAME|G_PARAM_READABLE|G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY));
1438 	g_object_class_install_property (object_class,
1439 	                                 PROP_PRIORITY,
1440 	                                 g_param_spec_int ("priority",
1441 							   "Priority",
1442 							   "Priority of the module",
1443 							   1,
1444 							   G_MAXINT,
1445 							   1,
1446 							   G_PARAM_STATIC_NAME|G_PARAM_READABLE));
1447 
1448 	plugin_signals [LOADED_SIGNAL] =
1449 		g_signal_new ("loaded",
1450 		              G_OBJECT_CLASS_TYPE (klass),
1451 		              G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
1452 		              G_STRUCT_OFFSET (BraseroPluginClass, loaded),
1453 		              NULL, NULL,
1454 		              g_cclosure_marshal_VOID__VOID,
1455 		              G_TYPE_NONE, 0);
1456 
1457 	plugin_signals [ACTIVATED_SIGNAL] =
1458 		g_signal_new ("activated",
1459 		              G_OBJECT_CLASS_TYPE (klass),
1460 		              G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
1461 		              G_STRUCT_OFFSET (BraseroPluginClass, activated),
1462 		              NULL, NULL,
1463 		              g_cclosure_marshal_VOID__BOOLEAN,
1464 		              G_TYPE_NONE, 1,
1465 			      G_TYPE_BOOLEAN);
1466 }
1467 
1468 BraseroPlugin *
brasero_plugin_new(const gchar * path)1469 brasero_plugin_new (const gchar *path)
1470 {
1471 	if (!path)
1472 		return NULL;
1473 
1474 	return BRASERO_PLUGIN (g_object_new (BRASERO_TYPE_PLUGIN,
1475 					     "path", path,
1476 					     NULL));
1477 }
1478