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);
231 /* Increase use-count so that we don't unload print backends.
232 There is a problem with module unloading in the cups module,
233 see cups_dispatch_watch_finalize for details. */
234 g_type_module_use (G_TYPE_MODULE (pb_module));
237 g_free (module_path);
246 gtk_print_backend_initialize (void)
248 static gboolean initialized = FALSE;
252 gtk_settings_install_property (g_param_spec_string ("gtk-print-backends",
253 P_("Default print backend"),
254 P_("List of the GtkPrintBackend backends to use by default"),
256 GTK_PARAM_READWRITE));
265 gtk_print_backend_load_modules ()
268 GtkPrintBackend *backend;
272 GtkSettings *settings;
276 gtk_print_backend_initialize ();
278 settings = gtk_settings_get_default ();
280 g_object_get (settings, "gtk-print-backends", &setting, NULL);
282 backends = g_strsplit (setting, ",", -1);
284 for (i = 0; backends[i]; i++)
286 g_strchug (backends[i]);
287 g_strchomp (backends[i]);
288 backend = _gtk_print_backend_create (backends[i]);
291 result = g_list_append (result, backend);
294 g_strfreev (backends);
300 /*****************************************
302 *****************************************/
304 G_DEFINE_TYPE (GtkPrintBackend, gtk_print_backend, G_TYPE_OBJECT)
306 static void fallback_printer_request_details (GtkPrinter *printer);
307 static gboolean fallback_printer_mark_conflicts (GtkPrinter *printer,
308 GtkPrinterOptionSet *options);
309 static void fallback_printer_get_hard_margins (GtkPrinter *printer,
314 static GList * fallback_printer_list_papers (GtkPrinter *printer);
315 static GtkPrintCapabilities fallback_printer_get_capabilities (GtkPrinter *printer);
318 gtk_print_backend_class_init (GtkPrintBackendClass *class)
320 GObjectClass *object_class;
321 object_class = (GObjectClass *) class;
323 backend_parent_class = g_type_class_peek_parent (class);
325 object_class->dispose = gtk_print_backend_dispose;
327 class->printer_request_details = fallback_printer_request_details;
328 class->printer_mark_conflicts = fallback_printer_mark_conflicts;
329 class->printer_get_hard_margins = fallback_printer_get_hard_margins;
330 class->printer_list_papers = fallback_printer_list_papers;
331 class->printer_get_capabilities = fallback_printer_get_capabilities;
333 g_type_class_add_private (class, sizeof (GtkPrintBackendPrivate));
335 signals[PRINTER_LIST_CHANGED] =
336 g_signal_new ("printer-list-changed",
337 G_TYPE_FROM_CLASS (class),
339 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_changed),
341 g_cclosure_marshal_VOID__VOID,
343 signals[PRINTER_LIST_DONE] =
344 g_signal_new ("printer-list-done",
345 G_TYPE_FROM_CLASS (class),
347 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_done),
349 g_cclosure_marshal_VOID__VOID,
351 signals[PRINTER_ADDED] =
352 g_signal_new ("printer-added",
353 G_TYPE_FROM_CLASS (class),
355 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_added),
357 g_cclosure_marshal_VOID__OBJECT,
358 G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
359 signals[PRINTER_REMOVED] =
360 g_signal_new ("printer-removed",
361 G_TYPE_FROM_CLASS (class),
363 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_removed),
365 g_cclosure_marshal_VOID__OBJECT,
366 G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
367 signals[PRINTER_STATUS_CHANGED] =
368 g_signal_new ("printer-status-changed",
369 G_TYPE_FROM_CLASS (class),
371 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_status_changed),
373 g_cclosure_marshal_VOID__OBJECT,
374 G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
378 gtk_print_backend_init (GtkPrintBackend *backend)
380 GtkPrintBackendPrivate *priv;
382 priv = backend->priv = GTK_PRINT_BACKEND_GET_PRIVATE (backend);
384 priv->printers = g_hash_table_new_full (g_str_hash, g_str_equal,
385 (GDestroyNotify) g_free,
386 (GDestroyNotify) g_object_unref);
390 gtk_print_backend_dispose (GObject *object)
392 GtkPrintBackend *backend;
393 GtkPrintBackendPrivate *priv;
395 backend = GTK_PRINT_BACKEND (object);
396 priv = backend->priv;
398 /* We unref the printers in dispose, not in finalize so that
399 we can break refcount cycles with gtk_print_backend_destroy */
402 g_hash_table_destroy (priv->printers);
403 priv->printers = NULL;
406 backend_parent_class->dispose (object);
411 fallback_printer_request_details (GtkPrinter *printer)
416 fallback_printer_mark_conflicts (GtkPrinter *printer,
417 GtkPrinterOptionSet *options)
423 fallback_printer_get_hard_margins (GtkPrinter *printer,
436 fallback_printer_list_papers (GtkPrinter *printer)
441 static GtkPrintCapabilities
442 fallback_printer_get_capabilities (GtkPrinter *printer)
449 printer_hash_to_sorted_active_list (const gchar *key,
455 printer = GTK_PRINTER (value);
457 if (gtk_printer_get_name (printer) == NULL)
460 if (!gtk_printer_is_active (printer))
463 *out_list = g_list_insert_sorted (*out_list, value, (GCompareFunc) gtk_printer_compare);
468 gtk_print_backend_add_printer (GtkPrintBackend *backend,
471 GtkPrintBackendPrivate *priv;
473 g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
475 priv = backend->priv;
480 g_hash_table_insert (priv->printers,
481 g_strdup (gtk_printer_get_name (printer)),
482 g_object_ref (printer));
486 gtk_print_backend_remove_printer (GtkPrintBackend *backend,
489 GtkPrintBackendPrivate *priv;
491 g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
492 priv = backend->priv;
497 g_hash_table_remove (priv->printers,
498 gtk_printer_get_name (printer));
502 gtk_print_backend_set_list_done (GtkPrintBackend *backend)
504 if (!backend->priv->printer_list_done)
506 backend->priv->printer_list_done = TRUE;
507 g_signal_emit (backend, signals[PRINTER_LIST_DONE], 0);
513 gtk_print_backend_get_printer_list (GtkPrintBackend *backend)
515 GtkPrintBackendPrivate *priv;
518 g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
520 priv = backend->priv;
523 if (priv->printers != NULL)
524 g_hash_table_foreach (priv->printers,
525 (GHFunc) printer_hash_to_sorted_active_list,
528 if (!priv->printer_list_requested && priv->printers != NULL)
530 if (GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list)
531 GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list (backend);
532 priv->printer_list_requested = TRUE;
539 gtk_print_backend_printer_list_is_done (GtkPrintBackend *print_backend)
541 g_return_val_if_fail (GTK_IS_PRINT_BACKEND (print_backend), TRUE);
543 return print_backend->priv->printer_list_done;
547 gtk_print_backend_find_printer (GtkPrintBackend *backend,
548 const gchar *printer_name)
550 GtkPrintBackendPrivate *priv;
553 g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
555 priv = backend->priv;
558 printer = g_hash_table_lookup (priv->printers, printer_name);
566 gtk_print_backend_print_stream (GtkPrintBackend *backend,
569 GtkPrintJobCompleteFunc callback,
571 GDestroyNotify dnotify)
573 g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
575 GTK_PRINT_BACKEND_GET_CLASS (backend)->print_stream (backend,
584 gtk_print_backend_destroy (GtkPrintBackend *print_backend)
586 /* The lifecycle of print backends and printers are tied, such that
587 the backend owns the printers, but the printers also ref the backend.
588 This is so that if the app has a reference to a printer its backend
589 will be around. However, this results in a cycle, which we break
590 with this call, which causes the print backend to release its printers.
592 g_object_run_dispose (G_OBJECT (print_backend));
595 #define __GTK_PRINT_BACKEND_C__
596 #include "gtkaliasdef.c"