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



We noticed that the print dialog is a bit slow to start up
initially, and traced that down to 

a) requesting ppd files for all printers
b) doing unnecessary server requests (e.g multiple calls to
  cupsGetDests() per printer)

Here is the first of two patches to address these issues. It is 
against libgnomecups and does the following:

1) add API to request ppd files asynchronously
2) reduce the amount of server requests by not calling cupsGetDests()
  if we're only interested in the contents of .lpoptions and not
  doing a request to check the mere existence of printers

This has reduced the time to bring up the print dialog in gedit from
over 2 seconds to ~0.25 seconds for me.

Matthias


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	27 Aug 2004 20:02:50 -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.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	27 Aug 2004 20:02:50 -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);
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	27 Aug 2004 20:02:50 -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,183 @@
 	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 (cupsGetDest(name, NULL, num_dests, *dests) == NULL)
+      continue;
+
+   /*
+    * 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,7 +512,7 @@
 	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 */
@@ -349,7 +528,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 +759,7 @@
 	} else if (!should_timeout && update_timeout_id) {
 		g_source_remove (update_timeout_id);
 		update_timeout_id = 0;
-	} 
+	}
 }
 
 guint
@@ -685,32 +864,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 +879,7 @@
 		printer_name = default_printer;
 	}
 
-	if (!check_exists (printer_name)) {
+	if (!name_in_list (printer_name, printer_names)) {
 		return NULL;
 	}
 	
@@ -857,23 +1010,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 +1388,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 +1398,6 @@
 					 NULL,
 					 (GDestroyNotify)gnome_cups_printer_option_free);
 	
-	ppd = gnome_cups_printer_get_ppd (printer);
 	if (!ppd)
 		return options;
 	
@@ -1116,7 +1412,6 @@
 			g_hash_table_insert (options, option->id, option);
 		}
 	}
-	ppdClose (ppd);
 
 	return options;
 }
@@ -1124,40 +1419,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 +1531,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-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	27 Aug 2004 20:02:50 -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;
 


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