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)
307 gtk_print_backend_class_init (GtkPrintBackendClass *class)
309 GObjectClass *object_class;
310 object_class = (GObjectClass *) class;
312 backend_parent_class = g_type_class_peek_parent (class);
314 object_class->dispose = gtk_print_backend_dispose;
316 g_type_class_add_private (class, sizeof (GtkPrintBackendPrivate));
319 signals[PRINTER_LIST_CHANGED] =
320 g_signal_new ("printer-list-changed",
321 G_TYPE_FROM_CLASS (class),
323 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_changed),
325 g_cclosure_marshal_VOID__VOID,
327 signals[PRINTER_LIST_DONE] =
328 g_signal_new ("printer-list-done",
329 G_TYPE_FROM_CLASS (class),
331 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_done),
333 g_cclosure_marshal_VOID__VOID,
335 signals[PRINTER_ADDED] =
336 g_signal_new ("printer-added",
337 G_TYPE_FROM_CLASS (class),
339 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_added),
341 g_cclosure_marshal_VOID__OBJECT,
342 G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
343 signals[PRINTER_REMOVED] =
344 g_signal_new ("printer-removed",
345 G_TYPE_FROM_CLASS (class),
347 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_removed),
349 g_cclosure_marshal_VOID__OBJECT,
350 G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
351 signals[PRINTER_STATUS_CHANGED] =
352 g_signal_new ("printer-status-changed",
353 G_TYPE_FROM_CLASS (class),
355 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_status_changed),
357 g_cclosure_marshal_VOID__OBJECT,
358 G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
362 gtk_print_backend_init (GtkPrintBackend *backend)
364 GtkPrintBackendPrivate *priv;
366 priv = backend->priv = GTK_PRINT_BACKEND_GET_PRIVATE (backend);
368 priv->printers = g_hash_table_new_full (g_str_hash, g_str_equal,
369 (GDestroyNotify) g_free,
370 (GDestroyNotify) g_object_unref);
374 gtk_print_backend_dispose (GObject *object)
376 GtkPrintBackend *backend;
377 GtkPrintBackendPrivate *priv;
379 backend = GTK_PRINT_BACKEND (object);
380 priv = backend->priv;
382 /* We unref the printers in dispose, not in finalize so that
383 we can break refcount cycles with gtk_print_backend_destroy */
386 g_hash_table_destroy (priv->printers);
387 priv->printers = NULL;
390 backend_parent_class->dispose (object);
395 printer_hash_to_sorted_active_list (const gchar *key,
401 printer = GTK_PRINTER (value);
403 if (gtk_printer_get_name (printer) == NULL)
406 if (!gtk_printer_is_active (printer))
409 *out_list = g_list_insert_sorted (*out_list, value, (GCompareFunc) gtk_printer_compare);
414 gtk_print_backend_add_printer (GtkPrintBackend *backend,
417 GtkPrintBackendPrivate *priv;
419 g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
421 priv = backend->priv;
426 g_hash_table_insert (priv->printers,
427 g_strdup (gtk_printer_get_name (printer)),
428 g_object_ref (printer));
432 gtk_print_backend_remove_printer (GtkPrintBackend *backend,
435 GtkPrintBackendPrivate *priv;
437 g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
438 priv = backend->priv;
443 g_hash_table_remove (priv->printers,
444 gtk_printer_get_name (printer));
448 gtk_print_backend_set_list_done (GtkPrintBackend *backend)
450 if (!backend->priv->printer_list_done)
452 backend->priv->printer_list_done = TRUE;
453 g_signal_emit (backend, signals[PRINTER_LIST_DONE], 0);
459 gtk_print_backend_get_printer_list (GtkPrintBackend *backend)
461 GtkPrintBackendPrivate *priv;
464 g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
466 priv = backend->priv;
469 if (priv->printers != NULL)
470 g_hash_table_foreach (priv->printers,
471 (GHFunc) printer_hash_to_sorted_active_list,
474 if (!priv->printer_list_requested && priv->printers != NULL)
476 if (GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list)
477 GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list (backend);
478 priv->printer_list_requested = TRUE;
485 gtk_print_backend_printer_list_is_done (GtkPrintBackend *print_backend)
487 g_return_val_if_fail (GTK_IS_PRINT_BACKEND (print_backend), TRUE);
489 return print_backend->priv->printer_list_done;
493 gtk_print_backend_find_printer (GtkPrintBackend *backend,
494 const gchar *printer_name)
496 GtkPrintBackendPrivate *priv;
499 g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
501 priv = backend->priv;
504 printer = g_hash_table_lookup (priv->printers, printer_name);
512 gtk_print_backend_print_stream (GtkPrintBackend *backend,
515 GtkPrintJobCompleteFunc callback,
517 GDestroyNotify dnotify)
519 g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
521 GTK_PRINT_BACKEND_GET_CLASS (backend)->print_stream (backend,
530 gtk_print_backend_destroy (GtkPrintBackend *print_backend)
532 /* The lifecycle of print backends and printers are tied, such that
533 the backend owns the printers, but the printers also ref the backend.
534 This is so that if the app has a reference to a printer its backend
535 will be around. However, this results in a cycle, which we break
536 with this call, which causes the print backend to release its printers.
538 g_object_run_dispose (G_OBJECT (print_backend));
541 #define __GTK_PRINT_BACKEND_C__
542 #include "gtkaliasdef.c"