Re: Speeding up the startup time of the print dialog (1/2)



On Fri, 2004-08-27 at 16:12, Matthias Clasen wrote:
> Here is the first of two patches to address these issues. It is 
> against libgnomecups and does the following:
> 

The libgnomecups patch had a couple of problems which prevented
it from working as intended. Here is an updated version.

Matthias


Index: libgnomecups/gnome-cups-printer.c
===================================================================
RCS file: /cvs/gnome/libgnomecups/libgnomecups/gnome-cups-printer.c,v
retrieving revision 1.26
diff -u -r1.26 gnome-cups-printer.c
--- libgnomecups/gnome-cups-printer.c	19 Aug 2004 20:46:19 -0000	1.26
+++ libgnomecups/gnome-cups-printer.c	31 Aug 2004 16:34:04 -0000
@@ -27,6 +27,8 @@
 
 #include <cups/cups.h>
 #include <time.h>
+#include <stdlib.h>
+#include <ctype.h>
 
 #include "util.h"
 #include "gnome-cups-request.h"
@@ -323,6 +325,185 @@
 	g_free (host);
 }
 
+/*
+ * cups_get_dest() is copied from the cups libraries, file cups/dest.c,
+ * which is 
+ *   Copyright 1997-2004 by Easy Software Products.
+ */
+static int				/* O - Number of destinations */
+cups_get_dests(const char  *filename,	/* I - File to read from */
+               int         num_dests,	/* I - Number of destinations */
+               cups_dest_t **dests)	/* IO - Destinations */
+{
+  int		i;			/* Looping var */
+  cups_dest_t	*dest;			/* Current destination */
+  FILE		*fp;			/* File pointer */
+  char		line[8192],		/* Line from file */
+		*lineptr,		/* Pointer into line */
+		*name,			/* Name of destination/option */
+		*instance;		/* Instance of destination */
+  const char	*printer;		/* PRINTER or LPDEST */
+
+
+ /*
+  * Check environment variables...
+  */
+
+  if ((printer = getenv("LPDEST")) == NULL)
+    if ((printer = getenv("PRINTER")) != NULL)
+      if (strcmp(printer, "lp") == 0)
+        printer = NULL;
+
+ /*
+  * Try to open the file...
+  */
+
+  if ((fp = fopen(filename, "r")) == NULL)
+    return (num_dests);
+
+ /*
+  * Read each printer; each line looks like:
+  *
+  *    Dest name[/instance] options
+  *    Default name[/instance] options
+  */
+
+  while (fgets(line, sizeof(line), fp) != NULL)
+  {
+   /*
+    * See what type of line it is...
+    */
+
+    if (strncasecmp(line, "dest", 4) == 0 && isspace(line[4] & 255))
+      lineptr = line + 4;
+    else if (strncasecmp(line, "default", 7) == 0 && isspace(line[7] & 255))
+      lineptr = line + 7;
+    else
+      continue;
+
+   /*
+    * Skip leading whitespace...
+    */
+
+    while (isspace(*lineptr & 255))
+      lineptr ++;
+
+    if (!*lineptr)
+      continue;
+
+    name = lineptr;
+
+   /*
+    * Search for an instance...
+    */
+
+    while (!isspace(*lineptr & 255) && *lineptr && *lineptr != '/')
+      lineptr ++;
+
+    if (!*lineptr)
+      continue;
+
+    if (*lineptr == '/')
+    {
+     /*
+      * Found an instance...
+      */
+
+      *lineptr++ = '\0';
+      instance = lineptr;
+
+     /*
+      * Search for an instance...
+      */
+
+      while (!isspace(*lineptr & 255) && *lineptr)
+	lineptr ++;
+    }
+    else
+      instance = NULL;
+
+    *lineptr++ = '\0';
+
+   /*
+    * See if the primary instance of the destination exists; if not,
+    * ignore this entry and move on...
+    */
+#if 0
+    /* Don't do this here, since we call this with an empty dests array */
+    if (cupsGetDest(name, NULL, num_dests, *dests) == NULL)
+      continue;
+#endif
+
+   /*
+    * Add the destination...
+    */
+
+    num_dests = cupsAddDest(name, instance, num_dests, dests);
+
+    if ((dest = cupsGetDest(name, instance, num_dests, *dests)) == NULL)
+    {
+     /*
+      * Out of memory!
+      */
+
+      fclose(fp);
+      return (num_dests);
+    }
+
+   /*
+    * Add options until we hit the end of the line...
+    */
+
+    dest->num_options = cupsParseOptions(lineptr, dest->num_options,
+                                         &(dest->options));
+
+   /*
+    * Set this as default if needed...
+    */
+
+    if (strncasecmp(line, "default", 7) == 0 && printer == NULL)
+    {
+      for (i = 0; i < num_dests; i ++)
+        (*dests)[i].is_default = 0;
+
+      dest->is_default = 1;
+    }
+  }
+
+ /*
+  * Close the file and return...
+  */
+
+  fclose(fp);      
+
+  return (num_dests);
+}
+
+static int
+parse_lpoptions (cups_dest_t **dests)
+{
+	gchar *filename;
+	const gchar *home;
+	int num_dests;
+
+	num_dests = 0;
+	*dests = NULL;
+
+	home = g_getenv("CUPS_SERVERROOT");
+	if (!home)
+		home = "/etc/cups";
+	filename = g_build_filename (home, "lpoptions", NULL);
+	num_dests = cups_get_dests (filename, num_dests, dests);
+					  
+	g_free (filename);
+	
+	filename = g_build_filename (g_get_home_dir (), ".lpoptions", NULL);
+	num_dests = cups_get_dests (filename, num_dests, dests);
+	g_free (filename);
+
+	return num_dests;
+}
+
 static char *
 get_default (void)
 {
@@ -333,11 +514,11 @@
 	ipp_attribute_t *attr;
 	GError *error = NULL;
 	int num_dests;
-	cups_dest_t *dests;
+	cups_dest_t *dests = NULL;
 	cups_dest_t *default_dest;
 
 	/* First look in the environment */
-	
+
 	env = g_getenv ("LPDEST");
 	if (env) {
 		return g_strdup (env);
@@ -349,7 +530,7 @@
 	}
 	
 	/* Then look in .lpoptions */	
-	num_dests = cupsGetDests (&dests);
+	num_dests = parse_lpoptions (&dests);
 	default_dest = cupsGetDest (NULL, NULL, num_dests, dests);
 	if (default_dest) {
 		name = g_strdup (default_dest->name);
@@ -580,7 +761,7 @@
 	} else if (!should_timeout && update_timeout_id) {
 		g_source_remove (update_timeout_id);
 		update_timeout_id = 0;
-	} 
+	}
 }
 
 guint
@@ -685,32 +866,6 @@
 	return NULL;
 }
 
-static gboolean 
-check_exists (const char *printer)
-{
-	GError *error = NULL;
-	ipp_t *request;
-	ipp_t *response;
-	char *printer_uri;
-
-	request = gnome_cups_request_new (IPP_GET_PRINTER_ATTRIBUTES);
-
-	printer_uri = g_strdup_printf ("ipp://localhost/printers/%s", printer);
-	ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
-		      "printer-uri", NULL, printer_uri);
-	response = gnome_cups_request_execute (request, NULL, "/", &error);
-	g_free (printer_uri);
-
-	ippDelete (response);
-
-	if (error) {
-		g_error_free (error);
-		return FALSE;
-	} else {
-		return TRUE;
-	}
-}
-
 GnomeCupsPrinter *
 gnome_cups_printer_get (const char *printer_name)
 {
@@ -726,7 +881,7 @@
 		printer_name = default_printer;
 	}
 
-	if (!check_exists (printer_name)) {
+	if (!name_in_list (printer_name, printer_names)) {
 		return NULL;
 	}
 	
@@ -857,23 +1012,167 @@
 	return printer->details->full_state;
 }
 
+static char *
+get_ppd_uri_path (GnomeCupsPrinter *printer)
+{
+	return g_strdup_printf ("/printers/%s.ppd", printer->details->printer_name);
+}
+
+static int
+get_tmp_ppd_file (GnomeCupsPrinter *printer,
+		  char **filename,
+		  GError **error)
+{
+	int fd;
+	char *tmpname;
+	char *tmp_filename;
+
+	tmpname = gnome_cups_util_escape_uri_string (printer->details->printer_name, GNOME_CUPS_UNSAFE_ALL);
+	tmp_filename = g_strdup_printf ("%s-printer-ppd-%s-XXXXXX",
+					g_get_user_name (),
+					tmpname);
+	g_free (tmpname);
+	fd = g_file_open_tmp (tmp_filename, filename, error);
+	g_free (tmp_filename);
+	return fd;
+}
+
+static GHashTable *get_ppd_options (GnomeCupsPrinter *printer, ppd_file_t *ppd);
+
 ppd_file_t *
 gnome_cups_printer_get_ppd (GnomeCupsPrinter *printer)
 {
-	const char *filename;
+	GError *error = NULL;
+	int fd;
+	char *host;
+	char *ppdpath;
+	char *filename;
 	ppd_file_t *ppd;
 
 	g_return_val_if_fail (GNOME_CUPS_IS_PRINTER (printer), NULL);
 
-	filename = cupsGetPPD (printer->details->printer_name);
+	fd = get_tmp_ppd_file (printer, &filename, &error);
+	if (error != NULL) {
+		g_warning ("Couldn't create temporary file: %s",
+			   error->message);
+		g_error_free (error);
+		return NULL;
+	}
+
+	host = _gnome_cups_printer_get_host (printer);
+	ppdpath = get_ppd_uri_path (printer);
+
+	gnome_cups_request_file (host, ppdpath, fd, &error);
+	if (error != NULL) {
+		g_warning ("Couldn't retrieve PPD for %s: %s",
+			   printer->details->printer_name,
+			   error->message);
+		g_error_free (error);
+		return NULL;
+	}
+
+	close (fd);
 	ppd = ppdOpenFile (filename);
+	g_free (filename);
 
 	/* This is loaded in to memory now, so we can free it. */
 	unlink (filename);
 
+	if (!printer->details->ppd_options)
+		printer->details->ppd_options = get_ppd_options (printer, ppd);
+
 	return ppd;
 }
 
+typedef struct
+{
+	GnomeCupsPrinter *printer;
+	GnomeCupsPrinterGetPPDCallback cb;	
+	gpointer user_data;
+	GDestroyNotify destroy_notify;
+	char *filename;
+	int fd;
+} GnomeCupsPrinterGetPPDWrapData;
+
+static void
+free_get_ppd_wrapper_data (gpointer p)
+{
+	GnomeCupsPrinterGetPPDWrapData *data = p;
+	g_object_unref (data->printer);
+	unlink (data->filename);
+	g_free (data->filename);
+	if (data->destroy_notify)
+		data->destroy_notify (data->user_data);
+	close (data->fd);
+	g_free (data);
+}
+
+static void
+wrap_ppd_request_cb (guint id,
+		     const char *path,
+		     ipp_t *response,
+		     GError **error,
+		     gpointer cb_data)
+{
+	GnomeCupsPrinterGetPPDWrapData *data = cb_data;
+	ppd_file_t *ppd;
+
+	if (error && *error != NULL) {
+		data->cb (id, NULL, error, data->user_data);
+		g_clear_error (error);
+	} else {
+		ppd = ppdOpenFile (data->filename);
+		if (!data->printer->details->ppd_options)
+			data->printer->details->ppd_options = 
+				get_ppd_options (data->printer, ppd);
+
+		data->cb (id, ppd, NULL, data->user_data);
+	}
+}
+
+guint
+gnome_cups_printer_get_ppd_async (GnomeCupsPrinter *printer,
+				  GnomeCupsPrinterGetPPDCallback cb,
+				  gpointer user_data,
+				  GDestroyNotify destroy_notify)
+{
+	GError *error = NULL;
+	guint opid;
+	int fd;
+	char *host;
+	char *ppdpath;
+	char *filename;
+	GnomeCupsPrinterGetPPDWrapData *data;
+
+	g_return_val_if_fail (GNOME_CUPS_IS_PRINTER (printer), 0);
+
+	fd = get_tmp_ppd_file (printer, &filename, &error);
+	if (error != NULL) {
+		g_warning ("Couldn't create temporary file: %s",
+			   error->message);
+		g_error_free (error);
+		return 0;
+	}
+
+	host = _gnome_cups_printer_get_host (printer);
+	ppdpath = get_ppd_uri_path (printer);
+
+	data = g_new0 (GnomeCupsPrinterGetPPDWrapData, 1);
+	data->printer = g_object_ref (printer);
+	data->filename = filename;
+	data->fd = fd;
+	data->cb = cb;
+	data->user_data = user_data;
+	data->destroy_notify = destroy_notify;
+
+	opid = gnome_cups_request_file_async (host, ppdpath, fd,
+					      wrap_ppd_request_cb,
+					      data,
+					      free_get_ppd_wrapper_data);
+	g_free (ppdpath);
+	return opid;
+}
+
 const char *
 gnome_cups_printer_get_device_uri (GnomeCupsPrinter const *printer)
 {
@@ -1091,9 +1390,9 @@
 }
 
 static GHashTable *
-get_ppd_options (GnomeCupsPrinter *printer)
+get_ppd_options (GnomeCupsPrinter *printer,
+		 ppd_file_t       *ppd)
 {
-	ppd_file_t *ppd;
 	int i;
 	GHashTable *options;
 	
@@ -1101,7 +1400,6 @@
 					 NULL,
 					 (GDestroyNotify)gnome_cups_printer_option_free);
 	
-	ppd = gnome_cups_printer_get_ppd (printer);
 	if (!ppd)
 		return options;
 	
@@ -1116,7 +1414,6 @@
 			g_hash_table_insert (options, option->id, option);
 		}
 	}
-	ppdClose (ppd);
 
 	return options;
 }
@@ -1124,40 +1421,43 @@
 static GHashTable *
 get_dest_options (GnomeCupsPrinter *printer)
 {
-	GHashTable *dest_options;
-	int num_dests;
-	cups_dest_t *dests;
+	int num_dests, i;
 	cups_dest_t *dest;
-	
-	dest_options = g_hash_table_new_full (g_str_hash, g_str_equal,
-					      g_free, g_free);
+	cups_dest_t *dests = NULL;
+	GHashTable *dest_options;
 
-	num_dests = cupsGetDests (&dests);
+	/* just parse lpoptions */
+	num_dests = parse_lpoptions (&dests);
 
-	dest = cupsGetDest (printer->details->printer_name, NULL, 
-			    num_dests, dests);	
+	dest = cupsGetDest (printer->details->printer_name, NULL, num_dests, dests);	
 
+	dest_options = g_hash_table_new_full (g_str_hash, g_str_equal,
+					      g_free, g_free);
+	
 	if (dest) {
-		int i;
 		for (i = 0; i < dest->num_options; i++) {
 			g_hash_table_insert (dest_options, 
 					     g_strdup (dest->options[i].name),
 					     g_strdup (dest->options[i].value));
 		}
 	}
+	printer->details->options_invalid = FALSE;
 
 	cupsFreeDests (num_dests, dests);
 
-	printer->details->options_invalid = FALSE;
-
 	return dest_options;
 }
 
 static void
 update_options (GnomeCupsPrinter *printer)
-{
+{ 
 	if (!printer->details->ppd_options) {
-		printer->details->ppd_options = get_ppd_options (printer);
+		ppd_file_t *ppd;
+		
+		ppd = gnome_cups_printer_get_ppd (printer);
+		
+		if (ppd)
+			ppdClose (ppd);
 	}
 	
 	if (printer->details->options_invalid) {
@@ -1233,6 +1533,10 @@
 	
 	return ret;
 }
+
+extern int	cups_get_dests(const char *filename, int num_dests,
+		               cups_dest_t **dests);
+
 
 GnomeCupsPrinterOption *
 gnome_cups_printer_get_option (GnomeCupsPrinter *printer,
Index: libgnomecups/gnome-cups-printer.h
===================================================================
RCS file: /cvs/gnome/libgnomecups/libgnomecups/gnome-cups-printer.h,v
retrieving revision 1.11
diff -u -r1.11 gnome-cups-printer.h
--- libgnomecups/gnome-cups-printer.h	19 Aug 2004 20:46:19 -0000	1.11
+++ libgnomecups/gnome-cups-printer.h	31 Aug 2004 16:34:04 -0000
@@ -29,6 +29,9 @@
 					       gpointer user_data);
 typedef void (*GnomeCupsPrinterRemovedCallback) (const char *name, 
 						 gpointer user_data);
+typedef void (*GnomeCupsPrinterGetPPDCallback) (guint id, ppd_file_t *ppd,
+						GError **error,
+						gpointer user_data);
 
 struct _GnomeCupsPrinter {
 	GObject parent;
@@ -150,6 +153,10 @@
 
 /* Configuration */
 ppd_file_t        *     gnome_cups_printer_get_ppd           (GnomeCupsPrinter        *printer);
+guint			gnome_cups_printer_get_ppd_async     (GnomeCupsPrinter        *printer,
+							      GnomeCupsPrinterGetPPDCallback cb,
+							      gpointer user_data,
+							      GDestroyNotify destroy_notify);
 char              *     gnome_cups_printer_get_option_value  (GnomeCupsPrinter        *printer,
 							      const char              *id);
 void                    gnome_cups_printer_set_option_value  (GnomeCupsPrinter        *printer,
Index: libgnomecups/gnome-cups-request.c
===================================================================
RCS file: /cvs/gnome/libgnomecups/libgnomecups/gnome-cups-request.c,v
retrieving revision 1.18
diff -u -r1.18 gnome-cups-request.c
--- libgnomecups/gnome-cups-request.c	25 Aug 2004 02:19:23 -0000	1.18
+++ libgnomecups/gnome-cups-request.c	31 Aug 2004 16:34:04 -0000
@@ -3,6 +3,7 @@
 #include <glib.h>
 
 #include <stdlib.h>
+#include <stdio.h>
 #include <cups/cups.h>
 #include <cups/language.h>
 #include <cups/http.h>
@@ -41,12 +42,19 @@
 
 	ipp_t *request;
 	char *path;
+	int output_fd;
 } GnomeCupsRequest;
 
 static void request_thread_main (GnomeCupsRequest *request, gpointer unused);
+static ipp_t * gnome_cups_request_execute_sync_internal (ipp_t *request,
+							 const char *server,
+							 const char *path,
+							 int output_fd,
+							 GError **error);
 static guint gnome_cups_request_execute_async_internal (ipp_t      *request, 
 							const char *server, 
 							const char *path, 
+							int output_fd,
 							gboolean direct_callback,
 							GnomeCupsAsyncRequestCallback callback,
 							gpointer cb_data,
@@ -227,7 +235,7 @@
 	g_static_mutex_unlock (&request_mutex);
 	return TRUE;
 }
-
+ 
 static gboolean
 close_unused_connection (const char *server,
 			 GnomeCupsConnection *connection,
@@ -291,14 +299,15 @@
 static gboolean
 idle_signal_request_complete (GnomeCupsRequest *request)
 {
-	if (!request->cancelled && request->callback)
+	if (!request->cancelled && request->callback) {
 		request->callback (request->id,
 				   request->path,
 				   request->response,
 				   request->error,
 				   request->cb_data);
-	else {
-		ippDelete (request->response);
+	} else {
+		if (request->response)
+			ippDelete (request->response);
 	}
 
 	g_static_mutex_lock (&request_mutex);
@@ -326,7 +335,6 @@
 request_thread_main (GnomeCupsRequest *request,
 		     gpointer unused)
 {
-	ipp_t *response;
 	ipp_status_t status;
 
 	if (request->cancelled) {
@@ -343,16 +351,24 @@
 		request->connection->http = httpConnectEncrypt (request->connection->server, ippPort(), cupsEncryption());
 
 
-	response = cupsDoRequest (request->connection->http, request->request,
-				  request->path);
-
-	/* FIXME - not currently threadsafe, but cups returns NULL on
-	 * any error.  Thus we just set the status to an internal error
-	 * for now.
-	 */
-	status = cupsLastError ();
-	if (response == NULL)
-		status = IPP_INTERNAL_ERROR;
+	if (request->request) {
+		request->response = cupsDoRequest (request->connection->http, request->request,
+						   request->path);
+		/* FIXME - not currently threadsafe, but cups returns NULL on
+		 * any error.  Thus we just set the status to an internal error
+		 * for now.
+		 */
+		status = cupsLastError ();
+		if (request->response == NULL)
+			status = IPP_INTERNAL_ERROR;
+	} else if (request->output_fd >= 0) {
+		status = cupsGetFd(request->connection->http, request->path, request->output_fd);
+		request->response = NULL;
+	}
+	else {
+	  status = IPP_INTERNAL_ERROR;
+	  g_warning ("Neither request nor output_fd set\n");
+	}
 
 	g_atomic_int_dec_and_test (&request->connection->refcount);
 	g_mutex_unlock (request->connection->mutex);
@@ -363,7 +379,6 @@
 						 get_error_string (status));
 	}
 
-	request->response = response;
 	do_signal_complete (request);
 	
 	return;
@@ -497,6 +512,33 @@
 ipp_t *
 gnome_cups_request_execute (ipp_t *request, const char *server, const char *path, GError **err)
 {
+	return gnome_cups_request_execute_sync_internal (request, server, path, -1, err);
+}
+
+/**
+ * gnome_cups_request_file:
+ * @server: The hostname of the IPP server to connect to
+ * @path: The URI of the file to retrieve 
+ * @output_fd: The file descriptor to which to write the retrieved file
+ * @err: A #GError for storing errors
+ *
+ * Retrieve the file named by @path via IPP, writing * the data to @output_fd.
+ **/
+void
+gnome_cups_request_file (const char *server, const char *path,
+			 int output_fd,
+			 GError **err)
+{
+	(void) gnome_cups_request_execute_sync_internal (NULL, server, path, output_fd, err);
+}
+
+static ipp_t *
+gnome_cups_request_execute_sync_internal (ipp_t *request,
+					  const char *server,
+					  const char *path,
+					  int output_fd,
+					  GError **err)
+{
 	guint id;
 	GnomeCupsAsyncWrapperData data;
 
@@ -507,7 +549,7 @@
 	data.error = err;
 
 	id = gnome_cups_request_execute_async_internal (request, server, path,
-							TRUE,
+							output_fd, TRUE,
 							async_wrapper_cb,
 							&data,
 							NULL);
@@ -520,7 +562,7 @@
 
 	g_mutex_free (data.mutex);
 	g_cond_free (data.cond);
-	
+
 	return data.response;
 }
 
@@ -546,15 +588,44 @@
 				  GDestroyNotify destroy_notify)
 {
 	return gnome_cups_request_execute_async_internal (request, server,
-							  path, FALSE,
-							  callback, cb_data,
-							  destroy_notify);
+							  path, -1,
+							  FALSE, callback,
+							  cb_data, destroy_notify);
+}
+
+/**
+ * gnome_cups_request_file_async:
+ * @server: The hostname of the IPP server to connect to
+ * @path: The URI of the file to retrieve 
+ * @output_fd: The file descriptor to which to write the retrieved file
+ * @callback: A #GnomeCupsAsyncRequestCallback.
+ * @cb_data: Data for the callback
+ * @destroy_notify: A function to free the callback data
+ * @returns: an operation ID, suitable for passing to gnome_cups_request_cancel
+ *
+ * Creates a new asynchronous IPP request to retrieve the specified file, which will
+ * invoke @cb_data when complete.  Note that the "response" parameter of the callback
+ * will always be #NULL.
+ **/
+guint
+gnome_cups_request_file_async (const char *server, 
+			       const char *path, 
+			       int output_fd,
+			       GnomeCupsAsyncRequestCallback callback,
+			       gpointer cb_data,
+			       GDestroyNotify destroy_notify)
+{
+	return gnome_cups_request_execute_async_internal (NULL, server,
+							  path, output_fd,
+							  FALSE, callback,
+							  cb_data, destroy_notify);
 }
 
 static guint
 gnome_cups_request_execute_async_internal (ipp_t      *request, 
 					   const char *server, 
 					   const char *path, 
+					   int output_fd, 
 					   gboolean direct_callback,
 					   GnomeCupsAsyncRequestCallback callback,
 					   gpointer cb_data,
@@ -593,6 +664,7 @@
 	req->cb_data = cb_data;
 	req->destroy_notify = destroy_notify;
 	req->path = g_strdup (path);
+	req->output_fd = output_fd;
 	req->direct_callback = direct_callback;
 	req->error = NULL;
 
Index: libgnomecups/gnome-cups-request.h
===================================================================
RCS file: /cvs/gnome/libgnomecups/libgnomecups/gnome-cups-request.h,v
retrieving revision 1.9
diff -u -r1.9 gnome-cups-request.h
--- libgnomecups/gnome-cups-request.h	13 Aug 2004 21:17:54 -0000	1.9
+++ libgnomecups/gnome-cups-request.h	31 Aug 2004 16:34:04 -0000
@@ -38,9 +38,19 @@
 						    const char  *server,
 						    const char  *path,
 						    GError     **err);
+void  gnome_cups_request_file			   (const char  *server,
+						    const char  *path,
+						    int fd,
+						    GError     **err);
 guint gnome_cups_request_execute_async             (ipp_t       *request,
-						    const char *server,
+						    const char  *server,
+						    const char  *path,
+						    GnomeCupsAsyncRequestCallback callback,
+						    gpointer cb_data,
+						    GDestroyNotify destroy_notify);
+guint gnome_cups_request_file_async                (const char  *server,
 						    const char  *path,
+						    int outfile_fd,
 						    GnomeCupsAsyncRequestCallback callback,
 						    gpointer cb_data,
 						    GDestroyNotify destroy_notify);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]