printers: Add async method for listing print devices
This commit adds asynchronous function get_cups_devices_async() which sequentially executes CUPS' backends and returns found devices by a callback. (#683229)
This commit is contained in:
parent
5a2794a7fe
commit
0cb0dab377
2 changed files with 315 additions and 0 deletions
|
@ -4587,6 +4587,292 @@ printer_add_option_async (const gchar *printer_name,
|
|||
data);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GCancellable *cancellable;
|
||||
GCDCallback callback;
|
||||
gpointer user_data;
|
||||
GList *backend_list;
|
||||
} GCDData;
|
||||
|
||||
static gint
|
||||
get_suffix_index (gchar *string)
|
||||
{
|
||||
gchar *number;
|
||||
gchar *endptr;
|
||||
gint index = -1;
|
||||
|
||||
number = g_strrstr (string, ":");
|
||||
if (number)
|
||||
{
|
||||
number++;
|
||||
index = g_ascii_strtoll (number, &endptr, 10);
|
||||
if (index == 0 && endptr == number)
|
||||
index = -1;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
static void
|
||||
get_cups_devices_async_dbus_cb (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
|
||||
{
|
||||
PpPrintDevice **devices = NULL;
|
||||
GVariant *output;
|
||||
GCDData *data = (GCDData *) user_data;
|
||||
GError *error = NULL;
|
||||
GList *result = NULL;
|
||||
gint num_of_devices = 0;
|
||||
|
||||
output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
|
||||
res,
|
||||
&error);
|
||||
|
||||
if (output)
|
||||
{
|
||||
const gchar *ret_error;
|
||||
GVariant *devices_variant = NULL;
|
||||
|
||||
g_variant_get (output, "(&s@a{ss})",
|
||||
&ret_error,
|
||||
&devices_variant);
|
||||
|
||||
if (ret_error[0] != '\0')
|
||||
{
|
||||
g_warning ("%s", ret_error);
|
||||
}
|
||||
|
||||
if (devices_variant)
|
||||
{
|
||||
GVariantIter *iter;
|
||||
GVariant *item;
|
||||
gchar *key;
|
||||
gchar *value;
|
||||
gint index = -1, max_index = -1, i;
|
||||
|
||||
g_variant_get (devices_variant, "a{ss}", &iter);
|
||||
while ((item = g_variant_iter_next_value (iter)))
|
||||
{
|
||||
g_variant_get (item, "{ss}", &key, &value);
|
||||
|
||||
index = get_suffix_index (key);
|
||||
if (index > max_index)
|
||||
max_index = index;
|
||||
|
||||
g_free (key);
|
||||
g_free (value);
|
||||
g_variant_unref (item);
|
||||
}
|
||||
|
||||
if (max_index >= 0)
|
||||
{
|
||||
num_of_devices = max_index + 1;
|
||||
devices = g_new0 (PpPrintDevice *, num_of_devices);
|
||||
|
||||
g_variant_get (devices_variant, "a{ss}", &iter);
|
||||
while ((item = g_variant_iter_next_value (iter)))
|
||||
{
|
||||
g_variant_get (item, "{ss}", &key, &value);
|
||||
|
||||
index = get_suffix_index (key);
|
||||
if (index >= 0)
|
||||
{
|
||||
if (!devices[index])
|
||||
devices[index] = g_new0 (PpPrintDevice, 1);
|
||||
|
||||
if (g_str_has_prefix (key, "device-class"))
|
||||
devices[index]->device_class = g_strdup (value);
|
||||
else if (g_str_has_prefix (key, "device-id"))
|
||||
devices[index]->device_id = g_strdup (value);
|
||||
else if (g_str_has_prefix (key, "device-info"))
|
||||
devices[index]->device_info = g_strdup (value);
|
||||
else if (g_str_has_prefix (key, "device-make-and-model"))
|
||||
{
|
||||
devices[index]->device_make_and_model = g_strdup (value);
|
||||
devices[index]->device_name = g_strdup (value);
|
||||
}
|
||||
else if (g_str_has_prefix (key, "device-uri"))
|
||||
devices[index]->device_uri = g_strdup (value);
|
||||
else if (g_str_has_prefix (key, "device-location"))
|
||||
devices[index]->device_location = g_strdup (value);
|
||||
|
||||
devices[index]->acquisition_method = ACQUISITION_METHOD_DEFAULT_CUPS_SERVER;
|
||||
}
|
||||
|
||||
g_free (key);
|
||||
g_free (value);
|
||||
g_variant_unref (item);
|
||||
}
|
||||
|
||||
for (i = 0; i < num_of_devices; i++)
|
||||
result = g_list_append (result, devices[i]);
|
||||
|
||||
g_free (devices);
|
||||
}
|
||||
|
||||
g_variant_unref (devices_variant);
|
||||
}
|
||||
|
||||
g_variant_unref (output);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (error->domain != G_IO_ERROR ||
|
||||
error->code != G_IO_ERROR_CANCELLED)
|
||||
g_warning ("%s", error->message);
|
||||
g_error_free (error);
|
||||
|
||||
data->callback (result,
|
||||
TRUE,
|
||||
g_cancellable_is_cancelled (data->cancellable),
|
||||
data->user_data);
|
||||
|
||||
g_list_free_full (data->backend_list, g_free);
|
||||
data->backend_list = NULL;
|
||||
g_object_unref (source_object);
|
||||
if (data->cancellable)
|
||||
g_object_unref (data->cancellable);
|
||||
g_free (data);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->backend_list)
|
||||
{
|
||||
if (!g_cancellable_is_cancelled (data->cancellable))
|
||||
{
|
||||
GVariantBuilder include_scheme_builder;
|
||||
|
||||
data->callback (result,
|
||||
FALSE,
|
||||
FALSE,
|
||||
data->user_data);
|
||||
|
||||
g_variant_builder_init (&include_scheme_builder, G_VARIANT_TYPE ("as"));
|
||||
g_variant_builder_add (&include_scheme_builder, "s", data->backend_list->data);
|
||||
|
||||
g_free (data->backend_list->data);
|
||||
data->backend_list = g_list_remove_link (data->backend_list, data->backend_list);
|
||||
|
||||
g_dbus_connection_call (G_DBUS_CONNECTION (g_object_ref (source_object)),
|
||||
MECHANISM_BUS,
|
||||
"/",
|
||||
MECHANISM_BUS,
|
||||
"DevicesGet",
|
||||
g_variant_new ("(iiasas)",
|
||||
0,
|
||||
0,
|
||||
&include_scheme_builder,
|
||||
NULL),
|
||||
G_VARIANT_TYPE ("(sa{ss})"),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
DBUS_TIMEOUT,
|
||||
data->cancellable,
|
||||
get_cups_devices_async_dbus_cb,
|
||||
user_data);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
data->callback (result,
|
||||
TRUE,
|
||||
TRUE,
|
||||
data->user_data);
|
||||
|
||||
g_list_free_full (data->backend_list, g_free);
|
||||
data->backend_list = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
data->callback (result,
|
||||
TRUE,
|
||||
g_cancellable_is_cancelled (data->cancellable),
|
||||
data->user_data);
|
||||
}
|
||||
|
||||
g_object_unref (source_object);
|
||||
if (data->cancellable)
|
||||
g_object_unref (data->cancellable);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
void
|
||||
get_cups_devices_async (GCancellable *cancellable,
|
||||
GCDCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GDBusConnection *bus;
|
||||
GVariantBuilder include_scheme_builder;
|
||||
GCDData *data;
|
||||
GError *error = NULL;
|
||||
gint i;
|
||||
const gchar *backends[] =
|
||||
{"hpfax", "ncp", "beh", "bluetooth", "snmp",
|
||||
"dnssd", "hp", "ipp", "lpd", "parallel",
|
||||
"serial", "socket", "usb", NULL};
|
||||
|
||||
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
|
||||
if (!bus)
|
||||
{
|
||||
g_warning ("Failed to get system bus: %s", error->message);
|
||||
g_error_free (error);
|
||||
callback (NULL, TRUE, FALSE, user_data);
|
||||
return;
|
||||
}
|
||||
|
||||
data = g_new0 (GCDData, 1);
|
||||
if (cancellable)
|
||||
data->cancellable = g_object_ref (cancellable);
|
||||
data->callback = callback;
|
||||
data->user_data = user_data;
|
||||
for (i = 0; backends[i]; i++)
|
||||
data->backend_list = g_list_prepend (data->backend_list, g_strdup (backends[i]));
|
||||
|
||||
g_variant_builder_init (&include_scheme_builder, G_VARIANT_TYPE ("as"));
|
||||
g_variant_builder_add (&include_scheme_builder, "s", data->backend_list->data);
|
||||
|
||||
g_free (data->backend_list->data);
|
||||
data->backend_list = g_list_remove_link (data->backend_list, data->backend_list);
|
||||
|
||||
g_dbus_connection_call (bus,
|
||||
MECHANISM_BUS,
|
||||
"/",
|
||||
MECHANISM_BUS,
|
||||
"DevicesGet",
|
||||
g_variant_new ("(iiasas)",
|
||||
0,
|
||||
0,
|
||||
&include_scheme_builder,
|
||||
NULL),
|
||||
G_VARIANT_TYPE ("(sa{ss})"),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
DBUS_TIMEOUT,
|
||||
cancellable,
|
||||
get_cups_devices_async_dbus_cb,
|
||||
data);
|
||||
}
|
||||
|
||||
void
|
||||
pp_print_device_free (PpPrintDevice *device)
|
||||
{
|
||||
if (device)
|
||||
{
|
||||
g_free (device->device_class);
|
||||
g_free (device->device_id);
|
||||
g_free (device->device_info);
|
||||
g_free (device->device_make_and_model);
|
||||
g_free (device->device_uri);
|
||||
g_free (device->device_location);
|
||||
g_free (device->device_name);
|
||||
g_free (device->device_ppd);
|
||||
g_free (device);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gchar *printer_name;
|
||||
|
|
|
@ -46,6 +46,11 @@ enum
|
|||
PPD_EXACT_CMD_MATCH
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ACQUISITION_METHOD_DEFAULT_CUPS_SERVER = 0
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gchar *ppd_name;
|
||||
|
@ -266,6 +271,30 @@ void job_set_hold_until_async (gint job_id,
|
|||
GCancellable *cancellable,
|
||||
JSHUCallback callback,
|
||||
gpointer user_data);
|
||||
typedef struct{
|
||||
gchar *device_class;
|
||||
gchar *device_id;
|
||||
gchar *device_info;
|
||||
gchar *device_make_and_model;
|
||||
gchar *device_uri;
|
||||
gchar *device_location;
|
||||
gchar *device_name;
|
||||
gchar *device_ppd;
|
||||
gchar *host_name;
|
||||
gint host_port;
|
||||
gint acquisition_method;
|
||||
} PpPrintDevice;
|
||||
|
||||
void pp_print_device_free (PpPrintDevice *device);
|
||||
|
||||
typedef void (*GCDCallback) (GList *devices,
|
||||
gboolean finished,
|
||||
gboolean cancelled,
|
||||
gpointer user_data);
|
||||
|
||||
void get_cups_devices_async (GCancellable *cancellable,
|
||||
GCDCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue