1 /* GTK - The GIMP Toolkit
2 * gtkprintbackend.h: Abstract printer backend interfaces
3 * Copyright (C) 2003, Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
27 #include "gtkmodules.h"
28 #include "gtkprivate.h"
29 #include "gtkprintbackend.h"
32 #define GTK_PRINT_BACKEND_GET_PRIVATE(o) \
33 (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_PRINT_BACKEND, GtkPrintBackendPrivate))
35 static void gtk_print_backend_dispose (GObject *object);
37 struct _GtkPrintBackendPrivate
40 guint printer_list_requested : 1;
41 guint printer_list_done : 1;
49 PRINTER_STATUS_CHANGED,
53 static guint signals[LAST_SIGNAL] = { 0 };
55 static GObjectClass *backend_parent_class;
58 gtk_print_backend_error_quark (void)
60 static GQuark quark = 0;
62 quark = g_quark_from_static_string ("gtk-print-backend-error-quark");
66 /*****************************************
67 * GtkPrintBackendModule modules *
68 *****************************************/
70 typedef struct _GtkPrintBackendModule GtkPrintBackendModule;
71 typedef struct _GtkPrintBackendModuleClass GtkPrintBackendModuleClass;
73 struct _GtkPrintBackendModule
75 GTypeModule parent_instance;
79 void (*init) (GTypeModule *module);
81 GtkPrintBackend* (*create) (void);
86 struct _GtkPrintBackendModuleClass
88 GTypeModuleClass parent_class;
91 G_DEFINE_TYPE (GtkPrintBackendModule, _gtk_print_backend_module, G_TYPE_TYPE_MODULE);
92 #define GTK_TYPE_PRINT_BACKEND_MODULE (_gtk_print_backend_module_get_type ())
93 #define GTK_PRINT_BACKEND_MODULE(module) (G_TYPE_CHECK_INSTANCE_CAST ((module), GTK_TYPE_PRINT_BACKEND_MODULE, GtkPrintBackendModule))
95 static GSList *loaded_backends;
98 gtk_print_backend_module_load (GTypeModule *module)
100 GtkPrintBackendModule *pb_module = GTK_PRINT_BACKEND_MODULE (module);
101 gpointer initp, exitp, createp;
103 pb_module->library = g_module_open (pb_module->path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
104 if (!pb_module->library)
106 g_warning (g_module_error());
110 /* extract symbols from the lib */
111 if (!g_module_symbol (pb_module->library, "pb_module_init",
113 !g_module_symbol (pb_module->library, "pb_module_exit",
115 !g_module_symbol (pb_module->library, "pb_module_create",
118 g_warning (g_module_error());
119 g_module_close (pb_module->library);
124 pb_module->init = initp;
125 pb_module->exit = exitp;
126 pb_module->create = createp;
128 /* call the filesystems's init function to let it */
129 /* setup anything it needs to set up. */
130 pb_module->init (module);
136 gtk_print_backend_module_unload (GTypeModule *module)
138 GtkPrintBackendModule *pb_module = GTK_PRINT_BACKEND_MODULE (module);
142 g_module_close (pb_module->library);
143 pb_module->library = NULL;
145 pb_module->init = NULL;
146 pb_module->exit = NULL;
147 pb_module->create = NULL;
150 /* This only will ever be called if an error occurs during
154 gtk_print_backend_module_finalize (GObject *object)
156 GtkPrintBackendModule *module = GTK_PRINT_BACKEND_MODULE (object);
158 g_free (module->path);
160 G_OBJECT_CLASS (_gtk_print_backend_module_parent_class)->finalize (object);
164 _gtk_print_backend_module_class_init (GtkPrintBackendModuleClass *class)
166 GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class);
167 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
169 module_class->load = gtk_print_backend_module_load;
170 module_class->unload = gtk_print_backend_module_unload;
172 gobject_class->finalize = gtk_print_backend_module_finalize;
176 _gtk_print_backend_module_init (GtkPrintBackendModule *pb_module)
180 static GtkPrintBackend *
181 _gtk_print_backend_module_create (GtkPrintBackendModule *pb_module)
185 if (g_type_module_use (G_TYPE_MODULE (pb_module)))
187 pb = pb_module->create ();
188 g_type_module_unuse (G_TYPE_MODULE (pb_module));
195 _gtk_print_backend_create (const char *backend_name)
200 GtkPrintBackendModule *pb_module;
203 /* TODO: make module loading code work */
204 for (l = loaded_backends; l != NULL; l = l->next)
208 if (strcmp (G_TYPE_MODULE (pb_module)->name, backend_name) == 0)
209 return _gtk_print_backend_module_create (pb_module);
213 if (g_module_supported ())
215 full_name = g_strconcat ("printbackend-", backend_name, NULL);
216 module_path = _gtk_find_module (full_name, "printbackends");
221 pb_module = g_object_new (GTK_TYPE_PRINT_BACKEND_MODULE, NULL);
223 g_type_module_set_name (G_TYPE_MODULE (pb_module), backend_name);
224 pb_module->path = g_strdup (module_path);
226 loaded_backends = g_slist_prepend (loaded_backends,
229 pb = _gtk_print_backend_module_create (pb_module);
232 g_free (module_path);
241 gtk_print_backend_initialize (void)
243 static gboolean initialized = FALSE;
247 gtk_settings_install_property (g_param_spec_string ("gtk-print-backends",
248 P_("Default print backend"),
249 P_("List of the GtkPrintBackend backends to use by default"),
251 GTK_PARAM_READWRITE));
260 gtk_print_backend_load_modules ()
263 GtkPrintBackend *backend;
267 GtkSettings *settings;
271 gtk_print_backend_initialize ();
273 settings = gtk_settings_get_default ();
275 g_object_get (settings, "gtk-print-backends", &setting, NULL);
277 backends = g_strsplit (setting, ",", -1);
279 for (i = 0; backends[i]; i++)
281 g_strchug (backends[i]);
282 g_strchomp (backends[i]);
283 backend = _gtk_print_backend_create (backends[i]);
286 result = g_list_append (result, backend);
289 g_strfreev (backends);
295 /*****************************************
297 *****************************************/
299 G_DEFINE_TYPE (GtkPrintBackend, gtk_print_backend, G_TYPE_OBJECT);
302 gtk_print_backend_class_init (GtkPrintBackendClass *class)
304 GObjectClass *object_class;
305 object_class = (GObjectClass *) class;
307 backend_parent_class = g_type_class_peek_parent (class);
309 object_class->dispose = gtk_print_backend_dispose;
311 g_type_class_add_private (class, sizeof (GtkPrintBackendPrivate));
314 signals[PRINTER_LIST_CHANGED] =
315 g_signal_new ("printer-list-changed",
316 G_TYPE_FROM_CLASS (class),
318 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_changed),
320 g_cclosure_marshal_VOID__VOID,
322 signals[PRINTER_LIST_DONE] =
323 g_signal_new ("printer-list-done",
324 G_TYPE_FROM_CLASS (class),
326 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_done),
328 g_cclosure_marshal_VOID__VOID,
330 signals[PRINTER_ADDED] =
331 g_signal_new ("printer-added",
332 G_TYPE_FROM_CLASS (class),
334 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_added),
336 g_cclosure_marshal_VOID__OBJECT,
337 G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
338 signals[PRINTER_REMOVED] =
339 g_signal_new ("printer-removed",
340 G_TYPE_FROM_CLASS (class),
342 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_removed),
344 g_cclosure_marshal_VOID__OBJECT,
345 G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
346 signals[PRINTER_STATUS_CHANGED] =
347 g_signal_new ("printer-status-changed",
348 G_TYPE_FROM_CLASS (class),
350 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_status_changed),
352 g_cclosure_marshal_VOID__OBJECT,
353 G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
357 gtk_print_backend_init (GtkPrintBackend *backend)
359 GtkPrintBackendPrivate *priv;
361 priv = backend->priv = GTK_PRINT_BACKEND_GET_PRIVATE (backend);
363 priv->printers = g_hash_table_new_full (g_str_hash, g_str_equal,
364 (GDestroyNotify) g_free,
365 (GDestroyNotify) g_object_unref);
369 gtk_print_backend_dispose (GObject *object)
371 GtkPrintBackend *backend;
372 GtkPrintBackendPrivate *priv;
374 backend = GTK_PRINT_BACKEND (object);
375 priv = backend->priv;
377 /* We unref the printers in dispose, not in finalize so that
378 we can break refcount cycles with gtk_print_backend_destroy */
381 g_hash_table_destroy (priv->printers);
382 priv->printers = NULL;
385 backend_parent_class->dispose (object);
390 printer_hash_to_sorted_active_list (const gchar *key,
396 printer = GTK_PRINTER (value);
398 if (gtk_printer_get_name (printer) == NULL)
401 if (!gtk_printer_is_active (printer))
404 *out_list = g_list_insert_sorted (*out_list, value, (GCompareFunc) gtk_printer_compare);
409 gtk_print_backend_add_printer (GtkPrintBackend *backend,
412 GtkPrintBackendPrivate *priv;
414 g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
416 priv = backend->priv;
421 g_hash_table_insert (priv->printers,
422 g_strdup (gtk_printer_get_name (printer)),
423 g_object_ref (printer));
427 gtk_print_backend_remove_printer (GtkPrintBackend *backend,
430 GtkPrintBackendPrivate *priv;
432 g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
433 priv = backend->priv;
438 g_hash_table_remove (priv->printers,
439 gtk_printer_get_name (printer));
443 gtk_print_backend_set_list_done (GtkPrintBackend *backend)
445 if (!backend->priv->printer_list_done)
447 backend->priv->printer_list_done = TRUE;
448 g_signal_emit (backend, signals[PRINTER_LIST_DONE], 0);
454 gtk_print_backend_get_printer_list (GtkPrintBackend *backend)
456 GtkPrintBackendPrivate *priv;
459 g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
461 priv = backend->priv;
464 if (priv->printers != NULL)
465 g_hash_table_foreach (priv->printers,
466 (GHFunc) printer_hash_to_sorted_active_list,
469 if (!priv->printer_list_requested && priv->printers != NULL)
471 if (GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list)
472 GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list (backend);
473 priv->printer_list_requested = TRUE;
480 gtk_print_backend_printer_list_is_done (GtkPrintBackend *print_backend)
482 g_return_val_if_fail (GTK_IS_PRINT_BACKEND (print_backend), TRUE);
484 return print_backend->priv->printer_list_done;
488 gtk_print_backend_find_printer (GtkPrintBackend *backend,
489 const gchar *printer_name)
491 GtkPrintBackendPrivate *priv;
494 g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
496 priv = backend->priv;
499 printer = g_hash_table_lookup (priv->printers, printer_name);
507 gtk_print_backend_print_stream (GtkPrintBackend *backend,
510 GtkPrintJobCompleteFunc callback,
512 GDestroyNotify dnotify)
514 g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
516 GTK_PRINT_BACKEND_GET_CLASS (backend)->print_stream (backend,
525 unref_at_idle_cb (gpointer data)
527 g_object_unref (data);
532 gtk_print_backend_unref_at_idle (GtkPrintBackend *print_backend)
534 g_idle_add (unref_at_idle_cb, print_backend);
538 gtk_print_backend_destroy (GtkPrintBackend *print_backend)
540 /* The lifecycle of print backends and printers are tied, such that
541 the backend owns the printers, but the printers also ref the backend.
542 This is so that if the app has a reference to a printer its backend
543 will be around. However, this results in a cycle, which we break
544 with this call, which causes the print backend to release its printers.
546 g_object_run_dispose (G_OBJECT (print_backend));
549 #define __GTK_PRINT_BACKEND_C__
550 #include "gtkaliasdef.c"