diff options
author | Richard Hughes <richard@hughsie.com> | 2011-01-12 14:34:58 +0000 |
---|---|---|
committer | Richard Hughes <richard@hughsie.com> | 2011-01-13 11:17:14 +0000 |
commit | 2f83888a2bf3f32f6aa57bc62e71af96ce27c9e9 (patch) | |
tree | 67d88457da908b6757743c531402395c1b4640fd | |
parent | 385e680fb6d4fc414d7382c43b3feb33cac52982 (diff) | |
download | colord-2f83888a2bf3f32f6aa57bc62e71af96ce27c9e9.tar.gz |
Add a libcolord shared library that can be used in the client tools
This also allows us to create a self test framework, which
uncovered many bugs in the process.
32 files changed, 4228 insertions, 484 deletions
diff --git a/Makefile.am b/Makefile.am index 27346cb..ea435cf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,6 +9,7 @@ SUBDIRS = \ policy \ data \ man \ + libcolord \ client \ src diff --git a/client/.gitignore b/client/.gitignore index b205447..9ac9527 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -1,4 +1,5 @@ colorgui colormgr .deps +.libs *.o diff --git a/client/Makefile.am b/client/Makefile.am index 83a91dc..823c55d 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -1,6 +1,8 @@ INCLUDES = \ $(GLIB_CFLAGS) \ $(GTK_CFLAGS) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/libcolord \ -DG_LOG_DOMAIN=\"Cd\" \ -DLIBEXECDIR=\"$(libexecdir)\" \ -DDATADIR=\"$(datadir)\" \ @@ -8,6 +10,8 @@ INCLUDES = \ -DVERSION="\"$(VERSION)\"" \ -DLOCALEDIR=\""$(localedir)"\" +COLORD_LIBS = $(top_builddir)/libcolord/libcolord.la + bin_PROGRAMS = \ colormgr @@ -15,6 +19,7 @@ colormgr_SOURCES = \ cd-util.c colormgr_LDADD = \ + $(COLORD_LIBS) \ $(GLIB_LIBS) colormgr_CFLAGS = \ @@ -24,9 +29,9 @@ if CD_BUILD_GUI noinst_PROGRAMS = colorgui colorgui_SOURCES = \ - cd-common.h \ cd-gui.c colorgui_LDADD = \ + $(COLORD_LIBS) \ $(GLIB_LIBS) \ $(GTK_LIBS) colorgui_CFLAGS = $(WARNINGFLAGS_C) diff --git a/client/cd-gui.c b/client/cd-gui.c index 419bfa9..65e6c17 100644 --- a/client/cd-gui.c +++ b/client/cd-gui.c @@ -25,8 +25,7 @@ #include <glib/gi18n.h> #include <gtk/gtk.h> #include <locale.h> - -#include "cd-common.h" +#include <colord.h> static gchar *current_device = NULL; static gchar *current_profile = NULL; diff --git a/client/cd-util.c b/client/cd-util.c index ceaa260..49d5040 100644 --- a/client/cd-util.c +++ b/client/cd-util.c @@ -24,164 +24,55 @@ #include <glib/gi18n.h> #include <gio/gio.h> #include <locale.h> - -#include "cd-common.h" +#include <colord.h> /** * cd_util_show_profile: **/ static void -cd_util_show_profile (const gchar *object_path) +cd_util_show_profile (CdProfile *profile) { - const gchar *filename = NULL; - const gchar *profile_id = NULL; - const gchar *qualifier = NULL; - const gchar *title = NULL; - GDBusProxy *proxy; - GError *error = NULL; - GVariant *variant_filename = NULL; - GVariant *variant_profile_id = NULL; - GVariant *variant_qualifier = NULL; - GVariant *variant_title = NULL; - - g_print ("Object Path: %s\n", object_path); - - /* get proxy */ - proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, - NULL, - COLORD_DBUS_SERVICE, - object_path, - COLORD_DBUS_INTERFACE_PROFILE, - NULL, - &error); - if (proxy == NULL) { - g_print ("Failed to get profile properties: %s", - error->message); - g_error_free (error); - goto out; - } - - /* print profile id */ - variant_profile_id = g_dbus_proxy_get_cached_property (proxy, "ProfileId"); - if (variant_profile_id != NULL) - profile_id = g_variant_get_string (variant_profile_id, NULL); - g_print ("ProfileId:\t\t%s\n", profile_id); - - /* print title */ - variant_title = g_dbus_proxy_get_cached_property (proxy, "Title"); - if (variant_title != NULL) - title = g_variant_get_string (variant_title, NULL); - g_print ("Title:\t\t%s\n", title); - - /* print qualifier */ - variant_qualifier = g_dbus_proxy_get_cached_property (proxy, "Qualifier"); - if (variant_qualifier != NULL) - qualifier = g_variant_get_string (variant_qualifier, NULL); - g_print ("Qualifier:\t\t%s\n", qualifier); - - /* print filename */ - variant_filename = g_dbus_proxy_get_cached_property (proxy, "Filename"); - if (variant_filename != NULL) - filename = g_variant_get_string (variant_filename, NULL); - g_print ("Filename:\t\t%s\n", filename); -out: - if (variant_profile_id != NULL) - g_variant_unref (variant_profile_id); - if (variant_title != NULL) - g_variant_unref (variant_title); - if (variant_qualifier != NULL) - g_variant_unref (variant_qualifier); - if (variant_filename != NULL) - g_variant_unref (variant_filename); - if (proxy != NULL) - g_object_unref (proxy); + g_print ("Object Path: %s\n", + cd_profile_get_object_path (profile)); + g_print ("Created:\t%" G_GUINT64_FORMAT "\n", + cd_profile_get_created (profile)); + g_print ("Qualifier:\t\t%s\n", + cd_profile_get_qualifier (profile)); + g_print ("Filename:\t\t%s\n", + cd_profile_get_filename (profile)); + g_print ("Profile ID:\t%s\n", + cd_profile_get_id (profile)); } /** * cd_util_show_device: **/ static void -cd_util_show_device (const gchar *object_path) +cd_util_show_device (CdDevice *device) { - const gchar *device_id; - const gchar *kind; - const gchar *model; - gchar *profile_tmp; - GDBusProxy *proxy; - GError *error = NULL; - gsize len; - guint64 created; + CdProfile *profile_tmp; + GPtrArray *profiles; guint i; - GVariantIter iter; - GVariant *variant_created = NULL; - GVariant *variant_device_id = NULL; - GVariant *variant_kind = NULL; - GVariant *variant_model = NULL; - GVariant *variant_profiles = NULL; - - g_print ("Object Path: %s\n", object_path); - - /* get proxy */ - proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, - NULL, - COLORD_DBUS_SERVICE, - object_path, - COLORD_DBUS_INTERFACE_DEVICE, - NULL, - &error); - if (proxy == NULL) { - g_print ("Failed to get device properties: %s", - error->message); - g_error_free (error); - goto out; - } - - /* print created date */ - variant_created = g_dbus_proxy_get_cached_property (proxy, "Created"); - created = g_variant_get_uint64 (variant_created); - g_print ("Created:\t%" G_GUINT64_FORMAT "\n", created); - - /* print kind */ - variant_kind = g_dbus_proxy_get_cached_property (proxy, "Kind"); - if (variant_kind != NULL) { - kind = g_variant_get_string (variant_kind, NULL); - g_print ("Kind:\t\t%s\n", kind); - } - /* print model */ - variant_model = g_dbus_proxy_get_cached_property (proxy, "Model"); - model = g_variant_get_string (variant_model, NULL); - g_print ("Model:\t\t%s\n", model); - - /* print device id */ - variant_device_id = g_dbus_proxy_get_cached_property (proxy, "DeviceId"); - device_id = g_variant_get_string (variant_device_id, NULL); - g_print ("Device ID:\t%s\n", device_id); + g_print ("Object Path: %s\n", + cd_device_get_object_path (device)); + g_print ("Created:\t%" G_GUINT64_FORMAT "\n", + cd_device_get_created (device)); + g_print ("Kind:\t\t%s\n", + cd_device_kind_to_string (cd_device_get_kind (device))); + g_print ("Model:\t\t%s\n", + cd_device_get_model (device)); + g_print ("Device ID:\t%s\n", + cd_device_get_id (device)); /* print profiles */ - variant_profiles = g_dbus_proxy_get_cached_property (proxy, "Profiles"); - len = g_variant_iter_init (&iter, variant_profiles); - if (len == 0) - g_print ("No assigned profiles!\n"); - for (i=0; i<len; i++) { - g_variant_get_child (variant_profiles, i, - "o", &profile_tmp); - g_print ("Profile %i:\t%s\n", i+1, profile_tmp); - g_free (profile_tmp); + profiles = cd_device_get_profiles (device); + for (i=0; i<profiles->len; i++) { + profile_tmp = g_ptr_array_index (profiles, i); + g_print ("Profile %i:\t%s\n", + i+1, + cd_profile_get_object_path (profile_tmp)); } -out: - if (variant_created != NULL) - g_variant_unref (variant_created); - if (variant_model != NULL) - g_variant_unref (variant_model); - if (variant_device_id != NULL) - g_variant_unref (variant_device_id); - if (variant_profiles != NULL) - g_variant_unref (variant_profiles); - if (proxy != NULL) - g_object_unref (proxy); } /** @@ -206,18 +97,18 @@ cd_util_mask_from_string (const gchar *value) int main (int argc, char *argv[]) { - const gchar *object_path; - gchar *object_path_tmp = NULL; - GDBusConnection *connection; + CdClient *client = NULL; + CdDevice *device = NULL; + CdDevice *device_tmp; + CdProfile *profile = NULL; + CdProfile *profile_tmp; + gboolean ret; GError *error = NULL; GOptionContext *context; - gsize len; + GPtrArray *array = NULL; guint i; guint mask; guint retval = 1; - GVariantIter iter; - GVariant *response_child = NULL; - GVariant *response = NULL; setlocale (LC_ALL, ""); @@ -234,11 +125,12 @@ main (int argc, char *argv[]) g_option_context_parse (context, &argc, &argv, NULL); g_option_context_free (context); - /* get a session bus connection */ - connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); - if (connection == NULL) { - /* TRANSLATORS: no DBus system bus */ - g_print ("%s %s\n", _("Failed to connect to system bus:"), error->message); + /* get connection to colord */ + client = cd_client_new (); + ret = cd_client_connect_sync (client, NULL, &error); + if (!ret) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("No connection to colord:"), error->message); g_error_free (error); goto out; } @@ -252,30 +144,16 @@ main (int argc, char *argv[]) if (g_strcmp0 (argv[1], "get-devices") == 0) { /* execute sync method */ - response = g_dbus_connection_call_sync (connection, - COLORD_DBUS_SERVICE, - COLORD_DBUS_PATH, - COLORD_DBUS_INTERFACE, - "GetDevices", - NULL, - G_VARIANT_TYPE ("(ao)"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, &error); - if (response == NULL) { - /* TRANSLATORS: the DBus method failed */ - g_print ("%s %s\n", _("The request failed:"), error->message); + array = cd_client_get_devices_sync (client, NULL, &error); + if (array == NULL) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to get devices:"), error->message); g_error_free (error); goto out; } - - /* print each device */ - response_child = g_variant_get_child_value (response, 0); - len = g_variant_iter_init (&iter, response_child); - for (i=0; i < len; i++) { - g_variant_get_child (response_child, i, - "o", &object_path_tmp); - cd_util_show_device (object_path_tmp); - g_free (object_path_tmp); + for (i=0; i < array->len; i++) { + device_tmp = g_ptr_array_index (array, i); + cd_util_show_device (device_tmp); } } else if (g_strcmp0 (argv[1], "get-devices-by-kind") == 0) { @@ -286,59 +164,34 @@ main (int argc, char *argv[]) } /* execute sync method */ - response = g_dbus_connection_call_sync (connection, - COLORD_DBUS_SERVICE, - COLORD_DBUS_PATH, - COLORD_DBUS_INTERFACE, - "GetDevicesByKind", - g_variant_new ("(s)", argv[2]), - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, &error); - if (response == NULL) { - /* TRANSLATORS: the DBus method failed */ - g_print ("%s %s\n", _("The request failed:"), error->message); + array = cd_client_get_devices_by_kind_sync (client, + cd_device_kind_from_string (argv[2]), + NULL, + &error); + if (array == NULL) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to get devices:"), error->message); g_error_free (error); goto out; } - - /* print each device */ - response_child = g_variant_get_child_value (response, 0); - len = g_variant_iter_init (&iter, response_child); - for (i=0; i < len; i++) { - g_variant_get_child (response_child, i, - "o", &object_path_tmp); - cd_util_show_device (object_path_tmp); - g_free (object_path_tmp); + for (i=0; i < array->len; i++) { + device_tmp = g_ptr_array_index (array, i); + cd_util_show_device (device_tmp); } } else if (g_strcmp0 (argv[1], "get-profiles") == 0) { /* execute sync method */ - response = g_dbus_connection_call_sync (connection, - COLORD_DBUS_SERVICE, - COLORD_DBUS_PATH, - COLORD_DBUS_INTERFACE, - "GetProfiles", - NULL, - G_VARIANT_TYPE ("(ao)"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, &error); - if (response == NULL) { - /* TRANSLATORS: the DBus method failed */ - g_print ("%s %s\n", _("The request failed:"), error->message); + array = cd_client_get_profiles_sync (client, NULL, &error); + if (array == NULL) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to get profiles:"), error->message); g_error_free (error); goto out; } - - /* print each device */ - response_child = g_variant_get_child_value (response, 0); - len = g_variant_iter_init (&iter, response_child); - for (i=0; i < len; i++) { - g_variant_get_child (response_child, i, - "o", &object_path_tmp); - cd_util_show_profile (object_path_tmp); - g_free (object_path_tmp); + for (i=0; i < array->len; i++) { + profile_tmp = g_ptr_array_index (array, i); + cd_util_show_profile (profile_tmp); } } else if (g_strcmp0 (argv[1], "create-device") == 0) { @@ -350,28 +203,16 @@ main (int argc, char *argv[]) /* execute sync method */ mask = cd_util_mask_from_string (argv[3]); - response = g_dbus_connection_call_sync (connection, - COLORD_DBUS_SERVICE, - COLORD_DBUS_PATH, - COLORD_DBUS_INTERFACE, - "CreateDevice", - g_variant_new ("(su)", - argv[2], - mask), - G_VARIANT_TYPE ("(o)"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, &error); - if (response == NULL) { - /* TRANSLATORS: the DBus method failed */ - g_print ("%s %s\n", _("The request failed:"), error->message); + device = cd_client_create_device_sync (client, argv[2], + mask, NULL, &error); + if (device == NULL) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to create device:"), error->message); g_error_free (error); goto out; } - - /* print the device */ - response_child = g_variant_get_child_value (response, 0); - object_path = g_variant_get_string (response_child, NULL); - g_print ("Created device %s\n", object_path); + g_print ("Created device:\n"); + cd_util_show_device (device); } else if (g_strcmp0 (argv[1], "find-device") == 0) { @@ -381,27 +222,15 @@ main (int argc, char *argv[]) } /* execute sync method */ - response = g_dbus_connection_call_sync (connection, - COLORD_DBUS_SERVICE, - COLORD_DBUS_PATH, - COLORD_DBUS_INTERFACE, - "FindDeviceById", - g_variant_new ("(s)", - argv[2]), - G_VARIANT_TYPE ("(o)"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, &error); - if (response == NULL) { - /* TRANSLATORS: the DBus method failed */ - g_print ("%s %s\n", _("The request failed:"), error->message); + device = cd_client_find_device_sync (client, argv[2], + NULL, &error); + if (device == NULL) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to find device:"), error->message); g_error_free (error); goto out; } - - /* print the device */ - response_child = g_variant_get_child_value (response, 0); - object_path = g_variant_get_string (response_child, NULL); - g_print ("Got device %s\n", object_path); + cd_util_show_device (device); } else if (g_strcmp0 (argv[1], "find-profile") == 0) { @@ -411,26 +240,15 @@ main (int argc, char *argv[]) } /* execute sync method */ - response = g_dbus_connection_call_sync (connection, - COLORD_DBUS_SERVICE, - COLORD_DBUS_PATH, - COLORD_DBUS_INTERFACE, - "FindProfileById", - g_variant_new ("(s)", argv[2]), - G_VARIANT_TYPE ("(o)"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, &error); - if (response == NULL) { - /* TRANSLATORS: the DBus method failed */ - g_print ("%s %s\n", _("The request failed:"), error->message); + profile = cd_client_find_profile_sync (client, argv[2], + NULL, &error); + if (profile == NULL) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to find profile:"), error->message); g_error_free (error); goto out; } - - /* print the device */ - response_child = g_variant_get_child_value (response, 0); - object_path = g_variant_get_string (response_child, NULL); - g_print ("Got profile %s\n", object_path); + cd_util_show_profile (profile); } else if (g_strcmp0 (argv[1], "create-profile") == 0) { @@ -441,28 +259,97 @@ main (int argc, char *argv[]) /* execute sync method */ mask = cd_util_mask_from_string (argv[3]); - response = g_dbus_connection_call_sync (connection, - COLORD_DBUS_SERVICE, - COLORD_DBUS_PATH, - COLORD_DBUS_INTERFACE, - "CreateProfile", - g_variant_new ("(su)", - argv[2], - mask), - G_VARIANT_TYPE ("(o)"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, &error); - if (response == NULL) { - /* TRANSLATORS: the DBus method failed */ - g_print ("%s %s\n", _("The request failed:"), error->message); + profile = cd_client_create_profile_sync (client, argv[2], + mask, NULL, &error); + if (profile == NULL) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to create profile:"), error->message); g_error_free (error); goto out; } + g_print ("Created profile:\n"); + cd_util_show_profile (profile); + + } else if (g_strcmp0 (argv[1], "device-add-profile") == 0) { - /* print the device */ - response_child = g_variant_get_child_value (response, 0); - object_path = g_variant_get_string (response_child, NULL); - g_print ("Created profile %s\n", object_path); + if (argc < 3) { + g_print ("Not enough arguments\n"); + goto out; + } + + device = cd_device_new (); + ret = cd_device_set_object_path_sync (device, + argv[2], + NULL, + &error); + if (!ret) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to create device:"), + error->message); + g_error_free (error); + goto out; + } + profile = cd_profile_new (); + ret = cd_profile_set_object_path_sync (profile, + argv[3], + NULL, + &error); + if (!ret) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to create profile:"), + error->message); + g_error_free (error); + goto out; + } + ret = cd_device_add_profile_sync (device, profile, NULL, &error); + if (!ret) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to add profile to device:"), + error->message); + g_error_free (error); + goto out; + } + + } else if (g_strcmp0 (argv[1], "device-make-profile-default") == 0) { + + if (argc < 3) { + g_print ("Not enough arguments\n"); + goto out; + } + + device = cd_device_new (); + ret = cd_device_set_object_path_sync (device, + argv[2], + NULL, + &error); + if (!ret) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to create device:"), + error->message); + g_error_free (error); + goto out; + } + profile = cd_profile_new (); + ret = cd_profile_set_object_path_sync (profile, + argv[3], + NULL, + &error); + if (!ret) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to create profile:"), + error->message); + g_error_free (error); + goto out; + } + ret = cd_device_make_profile_default_sync (device, profile, + NULL, &error); + if (!ret) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to add profile to device:"), + error->message); + g_error_free (error); + goto out; + } } else if (g_strcmp0 (argv[1], "delete-device") == 0) { @@ -471,127 +358,204 @@ main (int argc, char *argv[]) goto out; } - /* execute sync method */ - response = g_dbus_connection_call_sync (connection, - COLORD_DBUS_SERVICE, - COLORD_DBUS_PATH, - COLORD_DBUS_INTERFACE, - "DeleteDevice", - g_variant_new ("(s)", argv[2]), - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, &error); - if (response == NULL) { - /* TRANSLATORS: the DBus method failed */ - g_print ("%s %s\n", _("The request failed:"), error->message); + device = cd_device_new (); + ret = cd_device_set_object_path_sync (device, + argv[2], + NULL, + &error); + if (!ret) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to create device:"), + error->message); + g_error_free (error); + goto out; + } + ret = cd_client_delete_device_sync (client, device, + NULL, &error); + if (!ret) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to delete device:"), + error->message); g_error_free (error); goto out; } - } else if (g_strcmp0 (argv[1], "device-add-profile") == 0) { + } else if (g_strcmp0 (argv[1], "delete-profile") == 0) { + + if (argc < 2) { + g_print ("Not enough arguments\n"); + goto out; + } + + profile = cd_profile_new (); + ret = cd_profile_set_object_path_sync (profile, + argv[2], + NULL, + &error); + if (!ret) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to create profile:"), + error->message); + g_error_free (error); + goto out; + } + ret = cd_client_delete_profile_sync (client, profile, + NULL, &error); + if (!ret) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to delete profile:"), + error->message); + g_error_free (error); + goto out; + } + + } else if (g_strcmp0 (argv[1], "profile-set-qualifier") == 0) { if (argc < 3) { g_print ("Not enough arguments\n"); goto out; } - /* execute sync method */ - response = g_dbus_connection_call_sync (connection, - COLORD_DBUS_SERVICE, - argv[2], - COLORD_DBUS_INTERFACE_DEVICE, - "AddProfile", - g_variant_new ("(o)", argv[3]), - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, &error); - if (response == NULL) { - /* TRANSLATORS: the DBus method failed */ - g_print ("%s %s\n", _("The request failed:"), error->message); + profile = cd_profile_new (); + ret = cd_profile_set_object_path_sync (profile, + argv[2], + NULL, + &error); + if (!ret) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to create profile:"), + error->message); + g_error_free (error); + goto out; + } + ret = cd_profile_set_qualifier_sync (profile, argv[3], + NULL, &error); + if (!ret) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to set property on profile:"), + error->message); g_error_free (error); goto out; } - } else if (g_strcmp0 (argv[1], "profile-set-property") == 0) { + } else if (g_strcmp0 (argv[1], "profile-set-filename") == 0) { - if (argc < 5) { + if (argc < 3) { g_print ("Not enough arguments\n"); goto out; } - /* execute sync method */ - response = g_dbus_connection_call_sync (connection, - COLORD_DBUS_SERVICE, - argv[2], - COLORD_DBUS_INTERFACE_PROFILE, - "SetProperty", - g_variant_new ("(ss)", - argv[3], - argv[4]), - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, &error); - if (response == NULL) { - /* TRANSLATORS: the DBus method failed */ - g_print ("%s %s\n", _("The request failed:"), error->message); + profile = cd_profile_new (); + ret = cd_profile_set_object_path_sync (profile, + argv[2], + NULL, + &error); + if (!ret) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to create profile:"), + error->message); + g_error_free (error); + goto out; + } + ret = cd_profile_set_filename_sync (profile, argv[3], + NULL, &error); + if (!ret) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to set property on profile:"), + error->message); g_error_free (error); goto out; } - } else if (g_strcmp0 (argv[1], "device-set-property") == 0) { + } else if (g_strcmp0 (argv[1], "device-set-model") == 0) { - if (argc < 5) { + if (argc < 3) { g_print ("Not enough arguments\n"); goto out; } - /* execute sync method */ - response = g_dbus_connection_call_sync (connection, - COLORD_DBUS_SERVICE, - argv[2], - COLORD_DBUS_INTERFACE_DEVICE, - "SetProperty", - g_variant_new ("(ss)", - argv[3], - argv[4]), - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, &error); - if (response == NULL) { - /* TRANSLATORS: the DBus method failed */ - g_print ("%s %s\n", _("The request failed:"), error->message); + device = cd_device_new (); + ret = cd_device_set_object_path_sync (device, + argv[2], + NULL, + &error); + if (!ret) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to create device:"), + error->message); + g_error_free (error); + goto out; + } + ret = cd_device_set_model_sync (device, argv[3], + NULL, &error); + if (!ret) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to set property on device:"), + error->message); g_error_free (error); goto out; } - } else if (g_strcmp0 (argv[1], "device-get-profile-for-qualifier") == 0) { + } else if (g_strcmp0 (argv[1], "device-set-kind") == 0) { - if (argc < 4) { + if (argc < 3) { g_print ("Not enough arguments\n"); goto out; } - /* execute sync method */ - response = g_dbus_connection_call_sync (connection, - COLORD_DBUS_SERVICE, - argv[2], - COLORD_DBUS_INTERFACE_DEVICE, - "GetProfileForQualifier", - g_variant_new ("(s)", argv[3]), - G_VARIANT_TYPE ("(o)"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, &error); - if (response == NULL) { - /* TRANSLATORS: the DBus method failed */ - g_print ("%s %s\n", _("The request failed:"), error->message); + device = cd_device_new (); + ret = cd_device_set_object_path_sync (device, + argv[2], + NULL, + &error); + if (!ret) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to create device:"), + error->message); + g_error_free (error); + goto out; + } + ret = cd_device_set_kind_sync (device, cd_device_kind_from_string (argv[3]), + NULL, &error); + if (!ret) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to set property on device:"), + error->message); g_error_free (error); goto out; } - /* print the device */ - response_child = g_variant_get_child_value (response, 0); - object_path = g_variant_get_string (response_child, NULL); - cd_util_show_profile (object_path); + } else if (g_strcmp0 (argv[1], "device-get-profile-for-qualifier") == 0) { + + if (argc < 3) { + g_print ("Not enough arguments\n"); + goto out; + } + + device = cd_device_new (); + ret = cd_device_set_object_path_sync (device, + argv[2], + NULL, + &error); + if (!ret) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to create device:"), + error->message); + g_error_free (error); + goto out; + } + profile = cd_device_get_profile_for_qualifier_sync (device, + argv[3], + NULL, + &error); + if (profile == NULL) { + /* TRANSLATORS: no colord available */ + g_print ("%s %s\n", _("Failed to get a profile for the qualifier:"), + error->message); + g_error_free (error); + goto out; + } + cd_util_show_profile (profile); } else { @@ -602,8 +566,14 @@ main (int argc, char *argv[]) /* success */ retval = 0; out: - if (response != NULL) - g_variant_unref (response); + if (array != NULL) + g_ptr_array_unref (array); + if (client != NULL) + g_object_unref (client); + if (device != NULL) + g_object_unref (device); + if (profile != NULL) + g_object_unref (profile); return retval; } diff --git a/client/test.sh b/client/test.sh deleted file mode 100755 index 5574045..0000000 --- a/client/test.sh +++ /dev/null @@ -1,14 +0,0 @@ -./colormgr create-device dave normal -./colormgr get-devices -./colormgr create-profile norman normal -./colormgr create-profile victorian temp -./colormgr get-profiles -./colormgr device-add-profile /org/freedesktop/ColorManager/dave /org/freedesktop/ColorManager/norman -./colormgr find-device dave -./colormgr find-profile norman -./colormgr profile-set-property /org/freedesktop/ColorManager/norman Filename /home/hughsie/Code/colord/data/test.icc -./colormgr profile-set-property /org/freedesktop/ColorManager/norman Qualifier "RGB.Plain.300dpi" -./colormgr get-devices -./colormgr device-get-profile-for-qualifier /org/freedesktop/ColorManager/dave "RGB.*.300dpi" -./colormgr delete-device dave -./colormgr get-profiles diff --git a/configure.ac b/configure.ac index 4ed3b76..573a10a 100644 --- a/configure.ac +++ b/configure.ac @@ -1,12 +1,42 @@ # Copyright (C) 2010 Richard Hughes <richard@hughsie.com> AC_PREREQ(2.63) -AC_INIT([colord],0.1.0,[http://hughsie.com]) +m4_define([cd_major_version], [0]) +m4_define([cd_minor_version], [1]) +m4_define([cd_micro_version], [0]) +m4_define([cd_version], + [cd_major_version.cd_minor_version.cd_micro_version]) + +AC_INIT([colord],[cd_version],[http://hughsie.com]) AC_CONFIG_SRCDIR(src) AM_INIT_AUTOMAKE([1.9 tar-ustar dist-bzip2]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIR([m4]) +# use this in cd-version.h +CD_MAJOR_VERSION=cd_major_version +CD_MINOR_VERSION=cd_minor_version +CD_MICRO_VERSION=cd_micro_version +AC_SUBST(VERSION) +AC_SUBST(CD_MAJOR_VERSION) +AC_SUBST(CD_MINOR_VERSION) +AC_SUBST(CD_MICRO_VERSION) + +# libtool versioning - this applies to libcolord +# +# See http://sources.redhat.com/autobook/autobook/autobook_91.html#SEC91 for details +# +# increment; +# CURRENT If the API or ABI interface has changed (reset REVISION to 0) +# REVISION If the API and ABI remains the same, but bugs are fixed. +# AGE Don't use. +LT_CURRENT=1 +LT_REVISION=0 +LT_AGE=0 +AC_SUBST(LT_CURRENT) +AC_SUBST(LT_REVISION) +AC_SUBST(LT_AGE) + # enable nice build output on automake1.11 m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) @@ -118,10 +148,14 @@ AC_CONFIG_FILES([ Makefile man/Makefile data/Makefile +data/tests/Makefile policy/Makefile po/Makefile.in src/Makefile client/Makefile +libcolord/cd-version.h +libcolord/colord.pc +libcolord/Makefile ]) AC_OUTPUT diff --git a/contrib/colord.spec.in b/contrib/colord.spec.in index a2f81e4..03b351b 100644 --- a/contrib/colord.spec.in +++ b/contrib/colord.spec.in @@ -19,6 +19,13 @@ BuildRequires: polkit-devel colord is a low level system activated daemon that maps color devices to color profiles in the system context. +%package devel +Summary: Development package for %{name} +Requires: %{name} = %{version}-%{release} + +%description devel +Files for development with %{name}. + %prep %setup -q @@ -33,8 +40,16 @@ make %{?_smp_mflags} %install make install DESTDIR=$RPM_BUILD_ROOT +# Remove static libs and libtool archives. +find %{buildroot} -name '*.la' -exec rm -f {} ';' +find %{buildroot} -name '*.a' -exec rm -f {} ';' + %find_lang %{name} +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + %files -f %{name}.lang %defattr(-,root,root,-) %doc README AUTHORS NEWS COPYING @@ -45,6 +60,13 @@ make install DESTDIR=$RPM_BUILD_ROOT %{_datadir}/polkit-1/actions/org.freedesktop.color.policy %{_datadir}/dbus-1/system-services/org.freedesktop.ColorManager.service %{_datadir}/man/man1/colormgr.1.gz +%{_libdir}/libcolord.so.* + +%files devel +%defattr(-,root,root,-) +%{_includedir}/libcolord/*.h +%{_libdir}/libcolord.so +%{_libdir}/pkgconfig/colord.pc %changelog * #LONGDATE# Richard Hughes <richard@hughsie.com> #VERSION#-0.#BUILD##ALPHATAG# diff --git a/data/Makefile.am b/data/Makefile.am index 970cb38..1c8965b 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -1,3 +1,7 @@ + +SUBDIRS = \ + tests + dbusdir = $(sysconfdir)/dbus-1/system.d dist_dbus_DATA = org.freedesktop.ColorManager.conf diff --git a/data/tests/Makefile.am b/data/tests/Makefile.am new file mode 100644 index 0000000..9096c39 --- /dev/null +++ b/data/tests/Makefile.am @@ -0,0 +1,2 @@ +EXTRA_DIST = \ + ibm-t61.icc diff --git a/data/tests/ibm-t61.icc b/data/tests/ibm-t61.icc Binary files differnew file mode 100644 index 0000000..93c39f8 --- /dev/null +++ b/data/tests/ibm-t61.icc diff --git a/doc/create.sh b/doc/create.sh index e8e7e9c..570ba88 100755 --- a/doc/create.sh +++ b/doc/create.sh @@ -4,5 +4,5 @@ ../client/colormgr device-add-profile /org/freedesktop/ColorManager/t61xrandr /org/freedesktop/ColorManager/t61xrandr_default ../client/colormgr device-set-property /org/freedesktop/ColorManager/t61xrandr Model "Cray 3000" ../client/colormgr device-set-property /org/freedesktop/ColorManager/t61xrandr Kind "printer" -../client/colormgr profile-set-property /org/freedesktop/ColorManager/t61xrandr_default Filename /home/hughsie/.color/icc/ibm-t61.icc -../client/colormgr profile-set-property /org/freedesktop/ColorManager/t61xrandr_default Qualifier "RGB.Plain.300dpi" +../client/colormgr profile-set-filename /org/freedesktop/ColorManager/t61xrandr_default /home/hughsie/.color/icc/ibm-t61.icc +../client/colormgr profile-set-qualifier /org/freedesktop/ColorManager/t61xrandr_default "RGB.Plain.300dpi" diff --git a/libcolord/.gitignore b/libcolord/.gitignore new file mode 100644 index 0000000..a20b776 --- /dev/null +++ b/libcolord/.gitignore @@ -0,0 +1,8 @@ +.deps +.libs +*.o +*.la +*.lo +*.pc +cd-version.h +cd-self-test diff --git a/libcolord/Makefile.am b/libcolord/Makefile.am new file mode 100644 index 0000000..925fd21 --- /dev/null +++ b/libcolord/Makefile.am @@ -0,0 +1,64 @@ +INCLUDES = \ + $(GLIB_CFLAGS) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/libcolord \ + -DCD_COMPILATION \ + -DG_LOG_DOMAIN=\"libcolord\" \ + -DTESTDATADIR=\""$(top_srcdir)/data/tests"\" \ + -DPACKAGE_DATA_DIR=\""$(datadir)"\" + +lib_LTLIBRARIES = \ + libcolord.la + +libcolord_includedir = $(includedir)/libcolord +libcolord_include_HEADERS = \ + colord.h \ + cd-version.h \ + cd-enum.h \ + cd-device.h \ + cd-profile.h \ + cd-client.h + +libcolord_la_SOURCES = \ + cd-enum.c \ + cd-client.c \ + cd-profile.c \ + cd-device.c + +libcolord_la_LIBADD = \ + $(GLIB_LIBS) + +libcolord_la_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -export-dynamic \ + -no-undefined \ + -export-symbols-regex '^cd_.*' + +libcolord_la_CFLAGS = \ + $(WARNINGFLAGS_C) + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = colord.pc + +check_PROGRAMS = \ + cd-self-test + +cd_self_test_SOURCES = \ + cd-self-test.c + +cd_self_test_LDADD = \ + $(GLIB_LIBS) \ + $(lib_LTLIBRARIES) + +cd_self_test_CFLAGS = $(WARNINGFLAGS_C) + +TESTS = cd-self-test + +EXTRA_DIST = \ + cd-version.h.in \ + colord.pc.in + +CLEANFILES = $(BUILT_SOURCES) + +clean-local: + rm -f *~ diff --git a/libcolord/cd-client.c b/libcolord/cd-client.c new file mode 100644 index 0000000..c92645b --- /dev/null +++ b/libcolord/cd-client.c @@ -0,0 +1,1011 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2010 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** + * SECTION:cd-client + * @short_description: Main client object for accessing the colord daemon + * + * A helper GObject to use for accessing colord information, and to be notified + * when it is changed. + * + * See also: #CdDevice + */ + +#include "config.h" + +#include <stdlib.h> +#include <stdio.h> +#include <glib.h> +#include <gio/gio.h> + +#include "cd-client.h" +#include "cd-device.h" + +static void cd_client_class_init (CdClientClass *klass); +static void cd_client_init (CdClient *client); +static void cd_client_finalize (GObject *object); + +#define CD_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CD_TYPE_CLIENT, CdClientPrivate)) + +/** + * CdClientPrivate: + * + * Private #CdClient data + **/ +struct _CdClientPrivate +{ + GDBusProxy *proxy; + gchar *daemon_version; +}; + +enum { + CD_CLIENT_CHANGED, + CD_CLIENT_DEVICE_ADDED, + CD_CLIENT_DEVICE_REMOVED, + CD_CLIENT_LAST_SIGNAL +}; + +enum { + PROP_0, + PROP_DAEMON_VERSION, + PROP_LAST +}; + +static guint signals [CD_CLIENT_LAST_SIGNAL] = { 0 }; +static gpointer cd_client_object = NULL; + +G_DEFINE_TYPE (CdClient, cd_client, G_TYPE_OBJECT) + +/** + * cd_client_error_quark: + * + * Return value: An error quark. + * + * Since: 0.1.0 + **/ +GQuark +cd_client_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("cd_client_error"); + return quark; +} + +/** + * cd_client_get_device_array_from_variant: + **/ +static GPtrArray * +cd_client_get_device_array_from_variant (GVariant *result, + GCancellable *cancellable, + GError **error) +{ + CdDevice *device; + gboolean ret; + gchar *object_path_tmp; + GError *error_local = NULL; + GPtrArray *array = NULL; + GPtrArray *array_tmp = NULL; + guint i; + guint len; + GVariant *child = NULL; + GVariantIter iter; + + /* add each device */ + array_tmp = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); + child = g_variant_get_child_value (result, 0); + len = g_variant_iter_init (&iter, child); + for (i=0; i < len; i++) { + g_variant_get_child (child, i, + "o", &object_path_tmp); + g_debug ("%s", object_path_tmp); + + /* create device and add to the array */ + device = cd_device_new (); + ret = cd_device_set_object_path_sync (device, + object_path_tmp, + cancellable, + &error_local); + if (!ret) { + g_set_error (error, + CD_CLIENT_ERROR, + CD_CLIENT_ERROR_FAILED, + "Failed to set device object path: %s", + error_local->message); + g_error_free (error_local); + g_object_unref (device); + goto out; + } + g_ptr_array_add (array_tmp, device); + g_free (object_path_tmp); + } + + /* success */ + array = g_ptr_array_ref (array_tmp); +out: + if (child != NULL) + g_variant_unref (child); + if (array_tmp != NULL) + g_ptr_array_unref (array_tmp); + return array; +} + +/** + * cd_client_get_devices_sync: + * @client: a #CdClient instance. + * @cancellable: a #GCancellable, or %NULL + * @error: a #GError, or %NULL + * + * Get an array of the device objects. + * + * Return value: (transfer full): an array of #CdDevice objects, + * free with g_ptr_array_unref() + * + * Since: 0.1.0 + **/ +GPtrArray * +cd_client_get_devices_sync (CdClient *client, + GCancellable *cancellable, + GError **error) +{ + GError *error_local = NULL; + GPtrArray *array = NULL; + GVariant *result; + + g_return_val_if_fail (CD_IS_CLIENT (client), NULL); + g_return_val_if_fail (client->priv->proxy != NULL, NULL); + + result = g_dbus_proxy_call_sync (client->priv->proxy, + "GetDevices", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + &error_local); + if (result == NULL) { + g_set_error (error, + CD_CLIENT_ERROR, + CD_CLIENT_ERROR_FAILED, + "Failed to GetDevices: %s", + error_local->message); + g_error_free (error_local); + goto out; + } + + /* convert to array of CdDevice's */ + array = cd_client_get_device_array_from_variant (result, + cancellable, + error); + if (array == NULL) + goto out; +out: + if (result != NULL) + g_variant_unref (result); + return array; +} + +/** + * cd_client_create_device_sync: + * @client: a #CdClient instance. + * @id: identifier for the device + * @cancellable: a #GCancellable, or %NULL + * @error: a #GError, or %NULL + * + * Creates a color device. + * + * Return value: A #CdDevice object, or %NULL for error + * + * Since: 0.1.0 + **/ +CdDevice * +cd_client_create_device_sync (CdClient *client, + const gchar *id, + guint options, + GCancellable *cancellable, + GError **error) +{ + CdDevice *device = NULL; + CdDevice *device_tmp = NULL; + gboolean ret; + gchar *object_path = NULL; + GError *error_local = NULL; + GVariant *result; + + g_return_val_if_fail (CD_IS_CLIENT (client), NULL); + g_return_val_if_fail (client->priv->proxy != NULL, NULL); + + result = g_dbus_proxy_call_sync (client->priv->proxy, + "CreateDevice", + g_variant_new ("(su)", + id, + options), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + &error_local); + if (result == NULL) { + g_set_error (error, + CD_CLIENT_ERROR, + CD_CLIENT_ERROR_FAILED, + "Failed to CreateDevice: %s", + error_local->message); + g_error_free (error_local); + goto out; + } + + /* create thick CdDevice object */ + g_variant_get (result, "(o)", + &object_path); + device_tmp = cd_device_new (); + ret = cd_device_set_object_path_sync (device_tmp, + object_path, + cancellable, + error); + if (!ret) + goto out; + + /* success */ + device = g_object_ref (device_tmp); +out: + g_free (object_path); + if (device_tmp != NULL) + g_object_unref (device_tmp); + if (result != NULL) + g_variant_unref (result); + return device; +} + +/** + * cd_client_create_profile_sync: + * @client: a #CdClient instance. + * @id: identifier for the device + * @cancellable: a #GCancellable, or %NULL + * @error: a #GError, or %NULL + * + * Creates a color profile. + * + * Return value: A #CdProfile object, or %NULL for error + * + * Since: 0.1.0 + **/ +CdProfile * +cd_client_create_profile_sync (CdClient *client, + const gchar *id, + guint options, + GCancellable *cancellable, + GError **error) +{ + CdProfile *profile = NULL; + CdProfile *profile_tmp = NULL; + gboolean ret; + gchar *object_path = NULL; + GError *error_local = NULL; + GVariant *result; + + g_return_val_if_fail (CD_IS_CLIENT (client), NULL); + g_return_val_if_fail (client->priv->proxy != NULL, NULL); + + result = g_dbus_proxy_call_sync (client->priv->proxy, + "CreateProfile", + g_variant_new ("(su)", + id, + options), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + &error_local); + if (result == NULL) { + g_set_error (error, + CD_CLIENT_ERROR, + CD_CLIENT_ERROR_FAILED, + "Failed to CreateProfile: %s", + error_local->message); + g_error_free (error_local); + goto out; + } + + /* create thick CdDevice object */ + g_variant_get (result, "(o)", + &object_path); + profile_tmp = cd_profile_new (); + ret = cd_profile_set_object_path_sync (profile_tmp, + object_path, + cancellable, + error); + if (!ret) + goto out; + + /* success */ + profile = g_object_ref (profile_tmp); +out: + g_free (object_path); + if (profile_tmp != NULL) + g_object_unref (profile_tmp); + if (result != NULL) + g_variant_unref (result); + return profile; +} + +/** + * cd_client_delete_device_sync: + * @client: a #CdClient instance. + * @device: a #CdDevice instance. + * @cancellable: a #GCancellable, or %NULL + * @error: a #GError, or %NULL + * + * Deletes a color device. + * + * Return value: %TRUE is the device was deleted + * + * Since: 0.1.0 + **/ +gboolean +cd_client_delete_device_sync (CdClient *client, + CdDevice *device, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = TRUE; + GError *error_local = NULL; + GVariant *result; + + g_return_val_if_fail (CD_IS_CLIENT (client), FALSE); + g_return_val_if_fail (CD_IS_DEVICE (device), FALSE); + g_return_val_if_fail (client->priv->proxy != NULL, FALSE); + + result = g_dbus_proxy_call_sync (client->priv->proxy, + "DeleteDevice", + g_variant_new ("(s)", + cd_device_get_object_path (device)), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + &error_local); + if (result == NULL) { + ret = FALSE; + g_set_error (error, + CD_CLIENT_ERROR, + CD_CLIENT_ERROR_FAILED, + "Failed to DeleteDevice: %s", + error_local->message); + g_error_free (error_local); + goto out; + } +out: + if (result != NULL) + g_variant_unref (result); + return ret; +} + +/** + * cd_client_delete_profile_sync: + * @client: a #CdClient instance. + * @profile: a #CdProfile instance. + * @cancellable: a #GCancellable, or %NULL + * @error: a #GError, or %NULL + * + * Deletes a color profile. + * + * Return value: %TRUE is the profile was deleted + * + * Since: 0.1.0 + **/ +gboolean +cd_client_delete_profile_sync (CdClient *client, + CdProfile *profile, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = TRUE; + GError *error_local = NULL; + GVariant *result; + + g_return_val_if_fail (CD_IS_CLIENT (client), FALSE); + g_return_val_if_fail (CD_IS_PROFILE (profile), FALSE); + g_return_val_if_fail (client->priv->proxy != NULL, FALSE); + + result = g_dbus_proxy_call_sync (client->priv->proxy, + "DeleteProfile", + g_variant_new ("(s)", + cd_profile_get_object_path (profile)), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + &error_local); + if (result == NULL) { + ret = FALSE; + g_set_error (error, + CD_CLIENT_ERROR, + CD_CLIENT_ERROR_FAILED, + "Failed to DeleteProfile: %s", + error_local->message); + g_error_free (error_local); + goto out; + } +out: + if (result != NULL) + g_variant_unref (result); + return ret; +} + +/** + * cd_client_find_device_sync: + * @client: a #CdClient instance. + * @id: identifier for the device + * @cancellable: a #GCancellable, or %NULL + * @error: a #GError, or %NULL + * + * Finds a color device. + * + * Return value: A #CdDevice object, or %NULL for error + * + * Since: 0.1.0 + **/ +CdDevice * +cd_client_find_device_sync (CdClient *client, + const gchar *id, + GCancellable *cancellable, + GError **error) +{ + CdDevice *device = NULL; + CdDevice *device_tmp = NULL; + gboolean ret; + gchar *object_path = NULL; + GError *error_local = NULL; + GVariant *result; + + g_return_val_if_fail (CD_IS_CLIENT (client), NULL); + g_return_val_if_fail (client->priv->proxy != NULL, NULL); + + result = g_dbus_proxy_call_sync (client->priv->proxy, + "FindDeviceById", + g_variant_new ("(s)", id), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + &error_local); + if (result == NULL) { + g_set_error (error, + CD_CLIENT_ERROR, + CD_CLIENT_ERROR_FAILED, + "Failed to FindDeviceById: %s", + error_local->message); + g_error_free (error_local); + goto out; + } + + /* create GObject CdDevice object */ + g_variant_get (result, "(o)", + &object_path); + device_tmp = cd_device_new (); + ret = cd_device_set_object_path_sync (device_tmp, + object_path, + cancellable, + error); + if (!ret) + goto out; + + /* success */ + device = g_object_ref (device_tmp); +out: + g_free (object_path); + if (device_tmp != NULL) + g_object_unref (device_tmp); + if (result != NULL) + g_variant_unref (result); + return device; +} + +/** + * cd_client_find_profile_sync: + * @client: a #CdClient instance. + * @id: identifier for the device + * @cancellable: a #GCancellable, or %NULL + * @error: a #GError, or %NULL + * + * Finds a color profile. + * + * Return value: A #CdProfile object, or %NULL for error + * + * Since: 0.1.0 + **/ +CdProfile * +cd_client_find_profile_sync (CdClient *client, + const gchar *id, + GCancellable *cancellable, + GError **error) +{ + CdProfile *profile = NULL; + CdProfile *profile_tmp = NULL; + gboolean ret; + gchar *object_path = NULL; + GError *error_local = NULL; + GVariant *result; + + g_return_val_if_fail (CD_IS_CLIENT (client), NULL); + g_return_val_if_fail (client->priv->proxy != NULL, NULL); + + result = g_dbus_proxy_call_sync (client->priv->proxy, + "FindProfileById", + g_variant_new ("(s)", id), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + &error_local); + if (result == NULL) { + g_set_error (error, + CD_CLIENT_ERROR, + CD_CLIENT_ERROR_FAILED, + "Failed to FindProfileById: %s", + error_local->message); + g_error_free (error_local); + goto out; + } + + /* create GObject CdDevice object */ + g_variant_get (result, "(o)", + &object_path); + profile_tmp = cd_profile_new (); + ret = cd_profile_set_object_path_sync (profile_tmp, + object_path, + cancellable, + error); + if (!ret) + goto out; + + /* success */ + profile = g_object_ref (profile_tmp); +out: + g_free (object_path); + if (profile_tmp != NULL) + g_object_unref (profile_tmp); + if (result != NULL) + g_variant_unref (result); + return profile; +} + +/** + * cd_client_get_devices_by_kind_sync: + * @client: a #CdClient instance. + * @kind: a #CdDeviceKind, e.g. %CD_DEVICE_KIND_DISPLAY + * @cancellable: a #GCancellable, or %NULL + * @error: a #GError, or %NULL + * + * Get an array of the device objects of a specified kind. + * + * Return value: (transfer full): an array of #CdDevice objects, + * free with g_ptr_array_unref() + * + * Since: 0.1.0 + **/ +GPtrArray * +cd_client_get_devices_by_kind_sync (CdClient *client, + CdDeviceKind kind, + GCancellable *cancellable, + GError **error) +{ + GError *error_local = NULL; + GPtrArray *array = NULL; + GVariant *result; + + g_return_val_if_fail (CD_IS_CLIENT (client), NULL); + g_return_val_if_fail (client->priv->proxy != NULL, NULL); + + result = g_dbus_proxy_call_sync (client->priv->proxy, + "GetDevicesByKind", + g_variant_new ("(s)", + cd_device_kind_to_string (kind)), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + &error_local); + if (result == NULL) { + g_set_error (error, + CD_CLIENT_ERROR, + CD_CLIENT_ERROR_FAILED, + "Failed to GetDevicesByKind: %s", + error_local->message); + g_error_free (error_local); + goto out; + } + + /* convert to array of CdDevice's */ + array = cd_client_get_device_array_from_variant (result, + cancellable, + error); + if (array == NULL) + goto out; +out: + if (result != NULL) + g_variant_unref (result); + return array; +} + +/** + * cd_client_get_profile_array_from_variant: + **/ +static GPtrArray * +cd_client_get_profile_array_from_variant (GVariant *result, + GCancellable *cancellable, + GError **error) +{ + CdProfile *profile; + gboolean ret; + gchar *object_path_tmp; + GError *error_local = NULL; + GPtrArray *array = NULL; + GPtrArray *array_tmp = NULL; + guint i; + guint len; + GVariant *child = NULL; + GVariantIter iter; + + /* add each profile */ + array_tmp = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); + child = g_variant_get_child_value (result, 0); + len = g_variant_iter_init (&iter, child); + for (i=0; i < len; i++) { + g_variant_get_child (child, i, + "o", &object_path_tmp); + g_debug ("%s", object_path_tmp); + + /* create profile and add to the array */ + profile = cd_profile_new (); + ret = cd_profile_set_object_path_sync (profile, + object_path_tmp, + cancellable, + &error_local); + if (!ret) { + g_set_error (error, + CD_CLIENT_ERROR, + CD_CLIENT_ERROR_FAILED, + "Failed to set profile object path: %s", + error_local->message); + g_error_free (error_local); + g_object_unref (profile); + goto out; + } + g_ptr_array_add (array_tmp, profile); + g_free (object_path_tmp); + } + + /* success */ + array = g_ptr_array_ref (array_tmp); +out: + if (child != NULL) + g_variant_unref (child); + if (array_tmp != NULL) + g_ptr_array_unref (array_tmp); + return array; +} + +/** + * cd_client_get_profiles_sync: + * @client: a #CdClient instance. + * @cancellable: a #GCancellable, or %NULL + * @error: a #GError, or %NULL + * + * Get an array of the profile objects. + * + * Return value: (transfer full): an array of #CdProfile objects, + * free with g_ptr_array_unref() + * + * Since: 0.1.0 + **/ +GPtrArray * +cd_client_get_profiles_sync (CdClient *client, + GCancellable *cancellable, + GError **error) +{ + GError *error_local = NULL; + GPtrArray *array = NULL; + GVariant *result; + + g_return_val_if_fail (CD_IS_CLIENT (client), NULL); + g_return_val_if_fail (client->priv->proxy != NULL, NULL); + + result = g_dbus_proxy_call_sync (client->priv->proxy, + "GetProfiles", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + &error_local); + if (result == NULL) { + g_set_error (error, + CD_CLIENT_ERROR, + CD_CLIENT_ERROR_FAILED, + "Failed to GetProfiles: %s", + error_local->message); + g_error_free (error_local); + goto out; + } + + /* convert to array of CdProfile's */ + array = cd_client_get_profile_array_from_variant (result, + cancellable, + error); + if (array == NULL) + goto out; +out: + if (result != NULL) + g_variant_unref (result); + return array; +} + +/** + * cd_client_dbus_signal_cb: + **/ +static void +cd_client_dbus_signal_cb (GDBusProxy *proxy, + gchar *sender_name, + gchar *signal_name, + GVariant *parameters, + CdClient *client) +{ + gchar *object_path_tmp = NULL; + + if (g_strcmp0 (signal_name, "Changed") == 0) { + g_warning ("changed"); + } else if (g_strcmp0 (signal_name, "DeviceAdded") == 0) { + g_variant_get (parameters, "(o)", &object_path_tmp); + //EMIT + } else if (g_strcmp0 (signal_name, "DeviceRemoved") == 0) { + g_variant_get (parameters, "(o)", &object_path_tmp); + //EMIT + } else if (g_strcmp0 (signal_name, "ProfileAdded") == 0) { + g_variant_get (parameters, "(o)", &object_path_tmp); + //EMIT + } else if (g_strcmp0 (signal_name, "ProfileRemoved") == 0) { + g_variant_get (parameters, "(o)", &object_path_tmp); + //EMIT + } else { + g_warning ("unhandled signal '%s'", signal_name); + } + g_free (object_path_tmp); +} + +/** + * cd_client_connect_sync: + * @client: a #CdClient instance. + * @cancellable: a #GCancellable or %NULL + * @error: a #GError, or %NULL. + * + * Connects to the colord daemon. + * + * Return value: %TRUE for success, else %FALSE. + * + * Since: 0.1.0 + **/ +gboolean +cd_client_connect_sync (CdClient *client, GCancellable *cancellable, GError **error) +{ + gboolean ret = TRUE; + GError *error_local = NULL; + GVariant *daemon_version = NULL; + + g_return_val_if_fail (CD_IS_CLIENT (client), FALSE); + g_return_val_if_fail (client->priv->proxy == NULL, FALSE); + + /* connect to the daemon */ + client->priv->proxy = + g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + COLORD_DBUS_SERVICE, + COLORD_DBUS_PATH, + COLORD_DBUS_INTERFACE, + cancellable, + &error_local); + if (client->priv->proxy == NULL) { + ret = FALSE; + g_set_error (error, + CD_CLIENT_ERROR, + CD_CLIENT_ERROR_FAILED, + "Failed to connect to colord: %s", + error_local->message); + g_error_free (error_local); + goto out; + } + + /* get daemon version */ + daemon_version = g_dbus_proxy_get_cached_property (client->priv->proxy, + "Title"); + if (daemon_version != NULL) + client->priv->daemon_version = g_variant_dup_string (daemon_version, NULL); + + /* get signals from DBus */ + g_signal_connect (client->priv->proxy, + "g-signal", + G_CALLBACK (cd_client_dbus_signal_cb), + client); + + /* success */ + g_debug ("Connected to colord daemon version %s", + client->priv->daemon_version); +out: + if (daemon_version != NULL) + g_variant_unref (daemon_version); + return ret; +} + +/** + * cd_client_get_daemon_version: + * @client: a #CdClient instance. + * + * Get colord daemon version. + * + * Return value: string containing the daemon version, e.g. 0.1.0 + * + * Since: 0.1.0 + **/ +const gchar * +cd_client_get_daemon_version (CdClient *client) +{ + g_return_val_if_fail (CD_IS_CLIENT (client), NULL); + return client->priv->daemon_version; +} + +/* + * cd_client_get_property: + */ +static void +cd_client_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + CdClient *client; + client = CD_CLIENT (object); + + switch (prop_id) { + case PROP_DAEMON_VERSION: + g_value_set_string (value, client->priv->daemon_version); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* + * cd_client_class_init: + */ +static void +cd_client_class_init (CdClientClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = cd_client_get_property; + object_class->finalize = cd_client_finalize; + + /** + * CdClient:daemon-version: + * + * The daemon version. + * + * Since: 0.1.0 + */ + g_object_class_install_property (object_class, + PROP_DAEMON_VERSION, + g_param_spec_string ("daemon-version", + "Daemon version", + NULL, + NULL, + G_PARAM_READABLE)); + + /** + * CdClient::device-added: + * @client: the #CdClient instance that emitted the signal + * @device: the #CdDevice that was added. + * + * The ::device-added signal is emitted when a device is added. + * + * Since: 0.1.0 + **/ + signals [CD_CLIENT_DEVICE_ADDED] = + g_signal_new ("device-added", + G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CdClientClass, device_added), + NULL, NULL, g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, CD_TYPE_DEVICE); + + /** + * CdClient::device-removed: + * @client: the #CdClient instance that emitted the signal + * @device: the #CdDevice that was removed. + * + * The ::device-added signal is emitted when a device is removed. + * + * Since: 0.1.0 + **/ + signals [CD_CLIENT_DEVICE_REMOVED] = + g_signal_new ("device-removed", + G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CdClientClass, device_removed), + NULL, NULL, g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, CD_TYPE_DEVICE); + + /** + * CdClient::changed: + * @client: the #CdDevice instance that emitted the signal + * + * The ::changed signal is emitted when properties may have changed. + * + * Since: 0.1.0 + **/ + signals [CD_CLIENT_CHANGED] = + g_signal_new ("changed", + G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CdClientClass, changed), + NULL, NULL, g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + g_type_class_add_private (klass, sizeof (CdClientPrivate)); +} + +/* + * cd_client_init: + */ +static void +cd_client_init (CdClient *client) +{ + client->priv = CD_CLIENT_GET_PRIVATE (client); +} + +/* + * cd_client_finalize: + */ +static void +cd_client_finalize (GObject *object) +{ + CdClient *client = CD_CLIENT (object); + + g_return_if_fail (CD_IS_CLIENT (object)); + + g_free (client->priv->daemon_version); + if (client->priv->proxy != NULL) + g_object_unref (client->priv->proxy); + + G_OBJECT_CLASS (cd_client_parent_class)->finalize (object); +} + +/** + * cd_client_new: + * + * Creates a new #CdClient object. + * + * Return value: a new CdClient object. + * + * Since: 0.1.0 + **/ +CdClient * +cd_client_new (void) +{ + if (cd_client_object != NULL) { + g_object_ref (cd_client_object); + } else { + cd_client_object = g_object_new (CD_TYPE_CLIENT, NULL); + g_object_add_weak_pointer (cd_client_object, &cd_client_object); + } + return CD_CLIENT (cd_client_object); +} + diff --git a/libcolord/cd-client.h b/libcolord/cd-client.h new file mode 100644 index 0000000..a2ea5d6 --- /dev/null +++ b/libcolord/cd-client.h @@ -0,0 +1,134 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2010 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined (__COLORD_H_INSIDE__) && !defined (CD_COMPILATION) +#error "Only <colord.h> can be included directly." +#endif + +#ifndef __CD_CLIENT_H +#define __CD_CLIENT_H + +#include <glib-object.h> +#include <gio/gio.h> + +#include <libcolord/cd-device.h> +#include <libcolord/cd-profile.h> + +G_BEGIN_DECLS + +#define CD_TYPE_CLIENT (cd_client_get_type ()) +#define CD_CLIENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CD_TYPE_CLIENT, CdClient)) +#define CD_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CD_TYPE_CLIENT, CdClientClass)) +#define CD_IS_CLIENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CD_TYPE_CLIENT)) +#define CD_IS_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CD_TYPE_CLIENT)) +#define CD_CLIENT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CD_TYPE_CLIENT, CdClientClass)) +#define CD_CLIENT_ERROR (cd_client_error_quark ()) +#define CD_CLIENT_TYPE_ERROR (cd_client_error_get_type ()) + +typedef struct _CdClientPrivate CdClientPrivate; + +typedef struct +{ + GObject parent; + CdClientPrivate *priv; +} CdClient; + +typedef struct +{ + GObjectClass parent_class; + void (*device_added) (CdClient *client, + CdDevice *device); + void (*device_removed) (CdClient *client, + CdDevice *device); + void (*changed) (CdClient *client); + /*< private >*/ + /* Padding for future expansion */ + void (*_cd_client_reserved1) (void); + void (*_cd_client_reserved2) (void); + void (*_cd_client_reserved3) (void); + void (*_cd_client_reserved4) (void); + void (*_cd_client_reserved5) (void); + void (*_cd_client_reserved6) (void); + void (*_cd_client_reserved7) (void); + void (*_cd_client_reserved8) (void); +} CdClientClass; + +/** + * CdClientError: + * @CD_CLIENT_ERROR_FAILED: the transaction failed for an unknown reason + * + * Errors that can be thrown + */ +typedef enum +{ + CD_CLIENT_ERROR_FAILED, + CD_CLIENT_ERROR_LAST +} CdClientError; + +GType cd_client_get_type (void); +GQuark cd_client_error_quark (void); +CdClient *cd_client_new (void); + +CdDevice *cd_client_create_device_sync (CdClient *client, + const gchar *id, + guint options, + GCancellable *cancellable, + GError **error); +CdProfile *cd_client_create_profile_sync (CdClient *client, + const gchar *id, + guint options, + GCancellable *cancellable, + GError **error); +gboolean cd_client_delete_device_sync (CdClient *client, + CdDevice *device, + GCancellable *cancellable, + GError **error); +gboolean cd_client_delete_profile_sync (CdClient *client, + CdProfile *profile, + GCancellable *cancellable, + GError **error); +CdDevice *cd_client_find_device_sync (CdClient *client, + const gchar *id, + GCancellable *cancellable, + GError **error); +CdProfile *cd_client_find_profile_sync (CdClient *client, + const gchar *id, + GCancellable *cancellable, + GError **error); +GPtrArray *cd_client_get_devices_sync (CdClient *client, + GCancellable *cancellable, + GError **error); +GPtrArray *cd_client_get_profiles_sync (CdClient *client, + GCancellable *cancellable, + GError **error); +GPtrArray *cd_client_get_devices_by_kind_sync (CdClient *client, + CdDeviceKind kind, + GCancellable *cancellable, + GError **error); +gboolean cd_client_connect_sync (CdClient *client, + GCancellable *cancellable, + GError **error); +const gchar *cd_client_get_daemon_version (CdClient *client); + +G_END_DECLS + +#endif /* __CD_CLIENT_H */ + diff --git a/libcolord/cd-device.c b/libcolord/cd-device.c new file mode 100644 index 0000000..4edfcae --- /dev/null +++ b/libcolord/cd-device.c @@ -0,0 +1,909 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2010 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** + * SECTION:cd-device + * @short_description: Client object for accessing information about colord devices + * + * A helper GObject to use for accessing colord devices, and to be notified + * when it is changed. + * + * See also: #CdClient + */ + +#include "config.h" + +#include <stdlib.h> +#include <stdio.h> +#include <glib.h> +#include <string.h> + +#include "cd-device.h" +#include "cd-profile.h" + +static void cd_device_class_init (CdDeviceClass *klass); +static void cd_device_init (CdDevice *device); +static void cd_device_finalize (GObject *object); + +#define CD_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CD_TYPE_DEVICE, CdDevicePrivate)) + +/** + * CdDevicePrivate: + * + * Private #PkDevice data + **/ +struct _CdDevicePrivate +{ + GDBusProxy *proxy; + gchar *object_path; + gchar *id; + gchar *model; + guint64 created; + GPtrArray *profiles; + CdDeviceKind kind; +}; + +enum { + PROP_0, + PROP_CREATED, + PROP_ID, + PROP_MODEL, + PROP_KIND, + PROP_LAST +}; + +enum { + SIGNAL_CHANGED, + SIGNAL_LAST +}; + +static guint signals [SIGNAL_LAST] = { 0 }; + +G_DEFINE_TYPE (CdDevice, cd_device, G_TYPE_OBJECT) + +/** + * cd_device_error_quark: + * + * Return value: An error quark. + * + * Since: 0.1.0 + **/ +GQuark +cd_device_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("cd_device_error"); + return quark; +} + +/** + * cd_device_get_id: + * @device: a #CdDevice instance. + * + * Gets the device ID. + * + * Return value: A string, or %NULL for invalid + * + * Since: 0.1.0 + **/ +const gchar * +cd_device_get_id (CdDevice *device) +{ + g_return_val_if_fail (CD_IS_DEVICE (device), NULL); + return device->priv->id; +} + +/** + * cd_device_get_model: + * @device: a #CdDevice instance. + * + * Gets the device model. + * + * Return value: A string, or %NULL for invalid + * + * Since: 0.1.0 + **/ +const gchar * +cd_device_get_model (CdDevice *device) +{ + g_return_val_if_fail (CD_IS_DEVICE (device), NULL); + return device->priv->model; +} + +/** + * cd_device_get_created: + * @device: a #CdDevice instance. + * + * Gets the device ID. + * + * Return value: A value in seconds, or 0 for invalid + * + * Since: 0.1.0 + **/ +guint64 +cd_device_get_created (CdDevice *device) +{ + g_return_val_if_fail (CD_IS_DEVICE (device), 0); + return device->priv->created; +} + +/** + * cd_device_get_kind: + * @device: a #CdDevice instance. + * + * Gets the device kind. + * + * Return value: A device kind, e.g. %CD_DEVICE_KIND_DISPLAY + * + * Since: 0.1.0 + **/ +CdDeviceKind +cd_device_get_kind (CdDevice *device) +{ + g_return_val_if_fail (CD_IS_DEVICE (device), CD_DEVICE_KIND_UNKNOWN); + return device->priv->kind; +} + +/** + * cd_device_get_profiles: + * @device: a #CdDevice instance. + * + * Gets the device profiles. + * + * Return value: An array of #CdProfile's, free with g_ptr_array_unref() + * + * Since: 0.1.0 + **/ +GPtrArray * +cd_device_get_profiles (CdDevice *device) +{ + g_return_val_if_fail (CD_IS_DEVICE (device), NULL); + if (device->priv->profiles == NULL) + return NULL; + return g_ptr_array_ref (device->priv->profiles); +} + +/** + * cd_device_set_profiles_array_from_variant: + **/ +static gboolean +cd_device_set_profiles_array_from_variant (CdDevice *device, + GVariant *profiles, + GCancellable *cancellable, + GError **error) +{ + CdProfile *profile_tmp; + gboolean ret = TRUE; + gchar *object_path_tmp; + GError *error_local = NULL; + gsize len; + guint i; + GVariantIter iter; + + g_ptr_array_set_size (device->priv->profiles, 0); + len = g_variant_iter_init (&iter, profiles); + for (i=0; i<len; i++) { + g_variant_get_child (profiles, i, + "o", &object_path_tmp); + profile_tmp = cd_profile_new (); + ret = cd_profile_set_object_path_sync (profile_tmp, + object_path_tmp, + cancellable, + &error_local); + if (!ret) { + g_set_error (error, + CD_DEVICE_ERROR, + CD_DEVICE_ERROR_FAILED, + "Failed to set profile object path: %s", + error_local->message); + g_error_free (error_local); + g_object_unref (profile_tmp); + goto out; + } + g_ptr_array_add (device->priv->profiles, profile_tmp); + g_free (object_path_tmp); + } +out: + return ret; +} + +/** + * cd_device_dbus_properties_changed: + **/ +static void +cd_device_dbus_properties_changed (GDBusProxy *proxy, + GVariant *changed_properties, + const gchar * const *invalidated_properties, + CdDevice *device) +{ + guint i; + guint len; + GVariantIter iter; + gchar *property_name; + GVariant *property_value; + + len = g_variant_iter_init (&iter, changed_properties); + for (i=0; i < len; i++) { + g_variant_get_child (changed_properties, i, + "{sv}", + &property_name, + &property_value); + if (g_strcmp0 (property_name, "Model") == 0) { + g_free (device->priv->model); + device->priv->model = g_variant_dup_string (property_value, NULL); + } else if (g_strcmp0 (property_name, "Kind") == 0) { + device->priv->kind = + cd_device_kind_from_string (g_variant_get_string (property_value, NULL)); + } else if (g_strcmp0 (property_name, "Profiles") == 0) { + cd_device_set_profiles_array_from_variant (device, + property_value, + NULL, + NULL); + } else { + g_warning ("%s property unhandled", property_name); + } + g_variant_unref (property_value); + } +} + +/** + * cd_device_dbus_signal_cb: + **/ +static void +cd_device_dbus_signal_cb (GDBusProxy *proxy, + gchar *sender_name, + gchar *signal_name, + GVariant *parameters, + CdDevice *device) +{ + gchar *object_path_tmp = NULL; + + if (g_strcmp0 (signal_name, "Changed") == 0) { + g_debug ("emit Changed on %s", device->priv->object_path); + g_signal_emit (device, signals[SIGNAL_CHANGED], 0); + } else { + g_warning ("unhandled signal '%s'", signal_name); + } + g_free (object_path_tmp); +} + +/** + * cd_device_set_object_path_sync: + * @device: a #CdDevice instance. + * @object_path: The colord object path. + * @cancellable: a #GCancellable or %NULL + * @error: a #GError, or %NULL. + * + * Sets the object path of the object and fills up initial properties. + * + * Return value: #TRUE for success, else #FALSE and @error is used + * + * Since: 0.1.0 + **/ +gboolean +cd_device_set_object_path_sync (CdDevice *device, + const gchar *object_path, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = TRUE; + GError *error_local = NULL; + GVariant *created = NULL; + GVariant *id = NULL; + GVariant *kind = NULL; + GVariant *model = NULL; + GVariant *profiles = NULL; + + g_return_val_if_fail (CD_IS_DEVICE (device), FALSE); + g_return_val_if_fail (device->priv->proxy == NULL, FALSE); + + /* connect to the daemon */ + device->priv->proxy = + g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + COLORD_DBUS_SERVICE, + object_path, + COLORD_DBUS_INTERFACE_DEVICE, + cancellable, + &error_local); + if (device->priv->proxy == NULL) { + ret = FALSE; + g_set_error (error, + CD_DEVICE_ERROR, + CD_DEVICE_ERROR_FAILED, + "Failed to connect to device %s: %s", + object_path, + error_local->message); + g_error_free (error_local); + goto out; + } + + /* save object path */ + device->priv->object_path = g_strdup (object_path); + + /* get device id */ + id = g_dbus_proxy_get_cached_property (device->priv->proxy, + "DeviceId"); + if (id != NULL) + device->priv->id = g_variant_dup_string (id, NULL); + + /* get kind */ + kind = g_dbus_proxy_get_cached_property (device->priv->proxy, + "Kind"); + if (kind != NULL) + device->priv->kind = + cd_device_kind_from_string (g_variant_get_string (kind, NULL)); + + /* get model */ + model = g_dbus_proxy_get_cached_property (device->priv->proxy, + "Model"); + if (model != NULL) + device->priv->model = g_variant_dup_string (model, NULL); + + /* get created */ + created = g_dbus_proxy_get_cached_property (device->priv->proxy, + "Created"); + if (created != NULL) + device->priv->created = g_variant_get_uint64 (created); + + /* get profiles */ + profiles = g_dbus_proxy_get_cached_property (device->priv->proxy, + "Profiles"); + ret = cd_device_set_profiles_array_from_variant (device, + profiles, + cancellable, + error); + if (!ret) + goto out; + + /* get signals from DBus */ + g_signal_connect (device->priv->proxy, + "g-signal", + G_CALLBACK (cd_device_dbus_signal_cb), + device); + + /* watch if any remote properties change */ + g_signal_connect (device->priv->proxy, + "g-properties-changed", + G_CALLBACK (cd_device_dbus_properties_changed), + device); + + /* success */ + g_debug ("Connected to device %s", + device->priv->id); +out: + if (id != NULL) + g_variant_unref (id); + if (model != NULL) + g_variant_unref (model); + if (created != NULL) + g_variant_unref (created); + if (kind != NULL) + g_variant_unref (kind); + if (profiles != NULL) + g_variant_unref (profiles); + return ret; +} + +/** + * cd_device_set_property_sync: + **/ +static gboolean +cd_device_set_property_sync (CdDevice *device, + const gchar *name, + const gchar *value, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = TRUE; + GError *error_local = NULL; + GVariant *response = NULL; + + /* execute sync method */ + response = g_dbus_proxy_call_sync (device->priv->proxy, + "SetProperty", + g_variant_new ("(ss)", + name, + value), + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, &error_local); + if (response == NULL) { + ret = FALSE; + g_set_error (error, + CD_DEVICE_ERROR, + CD_DEVICE_ERROR_FAILED, + "Failed to set profile object path: %s", + error_local->message); + g_error_free (error_local); + goto out; + } +out: + if (response != NULL) + g_variant_unref (response); + return ret; +} + +/** + * cd_device_set_model_sync: + * @device: a #CdDevice instance. + * @value: The model. + * @cancellable: a #GCancellable or %NULL + * @error: a #GError, or %NULL. + * + * Sets the device model. + * + * Return value: #TRUE for success, else #FALSE and @error is used + * + * Since: 0.1.0 + **/ +gboolean +cd_device_set_model_sync (CdDevice *device, + const gchar *value, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_fail (CD_IS_DEVICE (device), FALSE); + g_return_val_if_fail (device->priv->proxy != NULL, FALSE); + + /* execute sync helper */ + return cd_device_set_property_sync (device, "Model", value, + cancellable, error); +} + +/** + * cd_device_set_kind_sync: + * @device: a #CdDevice instance. + * @kind: The device kind, e.g. #CD_DEVICE_KIND_DISPLAY + * @cancellable: a #GCancellable or %NULL + * @error: a #GError, or %NULL. + * + * Sets the device kind. + * + * Return value: #TRUE for success, else #FALSE and @error is used + * + * Since: 0.1.0 + **/ +gboolean +cd_device_set_kind_sync (CdDevice *device, + CdDeviceKind kind, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_fail (CD_IS_DEVICE (device), FALSE); + g_return_val_if_fail (device->priv->proxy != NULL, FALSE); + + /* execute sync helper */ + return cd_device_set_property_sync (device, "Kind", + cd_device_kind_to_string (kind), + cancellable, error); +} + +/** + * cd_device_add_profile_sync: + * @device: a #CdDevice instance. + * @profile: a #CdProfile instance + * @cancellable: a #GCancellable or %NULL + * @error: a #GError, or %NULL. + * + * Adds a profile to a device. + * + * Return value: #TRUE for success, else #FALSE and @error is used + * + * Since: 0.1.0 + **/ +gboolean +cd_device_add_profile_sync (CdDevice *device, + CdProfile *profile, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = TRUE; + GError *error_local = NULL; + GVariant *response = NULL; + + g_return_val_if_fail (CD_IS_DEVICE (device), FALSE); + g_return_val_if_fail (CD_IS_PROFILE (profile), FALSE); + g_return_val_if_fail (device->priv->proxy != NULL, FALSE); + + /* execute sync method */ + response = g_dbus_proxy_call_sync (device->priv->proxy, + "AddProfile", + g_variant_new ("(o)", + cd_profile_get_object_path (profile)), + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, &error_local); + if (response == NULL) { + ret = FALSE; + g_set_error (error, + CD_DEVICE_ERROR, + CD_DEVICE_ERROR_FAILED, + "Failed to add profile to device: %s", + error_local->message); + g_error_free (error_local); + goto out; + } +out: + if (response != NULL) + g_variant_unref (response); + return ret; +} + +/** + * cd_device_make_profile_default_sync: + * @device: a #CdDevice instance. + * @profile: a #CdProfile instance + * @cancellable: a #GCancellable or %NULL + * @error: a #GError, or %NULL. + * + * Makes an already added profile default for a device. + * + * Return value: #TRUE for success, else #FALSE and @error is used + * + * Since: 0.1.0 + **/ +gboolean +cd_device_make_profile_default_sync (CdDevice *device, + CdProfile *profile, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = TRUE; + GError *error_local = NULL; + GVariant *response = NULL; + + g_return_val_if_fail (CD_IS_DEVICE (device), FALSE); + g_return_val_if_fail (CD_IS_PROFILE (profile), FALSE); + g_return_val_if_fail (device->priv->proxy != NULL, FALSE); + + /* execute sync method */ + response = g_dbus_proxy_call_sync (device->priv->proxy, + "MakeProfileDefault", + g_variant_new ("(s)", + cd_profile_get_id (profile)), + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, &error_local); + if (response == NULL) { + ret = FALSE; + g_set_error (error, + CD_DEVICE_ERROR, + CD_DEVICE_ERROR_FAILED, + "Failed to make profile default on device: %s", + error_local->message); + g_error_free (error_local); + goto out; + } +out: + if (response != NULL) + g_variant_unref (response); + return ret; +} + +/** + * cd_device_get_profile_for_qualifier_sync: + * @device: a #CdDevice instance. + * @qualifier: a qualifier that can included wildcards + * @cancellable: a #GCancellable or %NULL + * @error: a #GError, or %NULL. + * + * Gets the prefered profile for a qualifier. + * + * Return value: a #CdProfile, free with g_object_unref() + * + * Since: 0.1.0 + **/ +CdProfile * +cd_device_get_profile_for_qualifier_sync (CdDevice *device, + const gchar *qualifier, + GCancellable *cancellable, + GError **error) +{ + CdProfile *profile = NULL; + CdProfile *profile_tmp = NULL; + gboolean ret; + gchar *object_path = NULL; + GError *error_local = NULL; + GVariant *response = NULL; + + g_return_val_if_fail (CD_IS_DEVICE (device), NULL); + g_return_val_if_fail (qualifier != NULL, NULL); + g_return_val_if_fail (device->priv->proxy != NULL, NULL); + + /* execute sync method */ + response = g_dbus_proxy_call_sync (device->priv->proxy, + "GetProfileForQualifier", + g_variant_new ("(s)", + qualifier), + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, &error_local); + if (response == NULL) { + g_set_error (error, + CD_DEVICE_ERROR, + CD_DEVICE_ERROR_FAILED, + "Failed to get a suitable profile: %s", + error_local->message); + g_error_free (error_local); + goto out; + } + + /* create thick CdDevice object */ + g_variant_get (response, "(o)", + &object_path); + profile_tmp = cd_profile_new (); + ret = cd_profile_set_object_path_sync (profile_tmp, + object_path, + cancellable, + error); + if (!ret) + goto out; + + /* success */ + profile = g_object_ref (profile_tmp); +out: + g_free (object_path); + if (profile_tmp != NULL) + g_object_unref (profile_tmp); + if (response != NULL) + g_variant_unref (response); + return profile; +} + +/** + * cd_device_get_object_path: + * @device: a #CdDevice instance. + * + * Gets the object path for the device. + * + * Return value: the object path, or %NULL + * + * Since: 0.1.0 + **/ +const gchar * +cd_device_get_object_path (CdDevice *device) +{ + g_return_val_if_fail (CD_IS_DEVICE (device), NULL); + return device->priv->object_path; +} + +/** + * cd_device_to_string: + * @device: a #CdDevice instance. + * + * Converts the device to a string description. + * + * Return value: text representation of #CdDevice + * + * Since: 0.1.0 + **/ +gchar * +cd_device_to_string (CdDevice *device) +{ + struct tm *time_tm; + time_t t; + gchar time_buf[256]; + GString *string; + + g_return_val_if_fail (CD_IS_DEVICE (device), NULL); + + /* get a human readable time */ + t = (time_t) device->priv->created; + time_tm = localtime (&t); + strftime (time_buf, sizeof time_buf, "%c", time_tm); + + string = g_string_new (""); + g_string_append_printf (string, " object-path: %s\n", + device->priv->object_path); + g_string_append_printf (string, " created: %s\n", + time_buf); + + return g_string_free (string, FALSE); +} + +/* + * cd_device_set_property: + */ +static void +cd_device_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + CdDevice *device = CD_DEVICE (object); + + switch (prop_id) { + case PROP_ID: + g_free (device->priv->id); + device->priv->id = g_strdup (g_value_get_string (value)); + break; + case PROP_MODEL: + g_free (device->priv->model); + device->priv->model = g_strdup (g_value_get_string (value)); + break; + case PROP_CREATED: + device->priv->created = g_value_get_uint64 (value); + break; + case PROP_KIND: + device->priv->kind = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* + * cd_device_get_property: + */ +static void +cd_device_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + CdDevice *device = CD_DEVICE (object); + + switch (prop_id) { + case PROP_CREATED: + g_value_set_uint64 (value, device->priv->created); + break; + case PROP_ID: + g_value_set_string (value, device->priv->id); + break; + case PROP_MODEL: + g_value_set_string (value, device->priv->model); + break; + case PROP_KIND: + g_value_set_uint (value, device->priv->kind); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* + * cd_device_class_init: + */ +static void +cd_device_class_init (CdDeviceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + object_class->finalize = cd_device_finalize; + object_class->set_property = cd_device_set_property; + object_class->get_property = cd_device_get_property; + + /** + * CdDevice::changed: + * @device: the #CdDevice instance that emitted the signal + * + * The ::changed signal is emitted when the device data has changed. + * + * Since: 0.1.0 + **/ + signals [SIGNAL_CHANGED] = + g_signal_new ("changed", + G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CdDeviceClass, changed), + NULL, NULL, g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * CdDevice:created: + * + * The last time the device was updated. + * + * Since: 0.1.0 + **/ + g_object_class_install_property (object_class, + PROP_CREATED, + g_param_spec_uint64 ("created", + NULL, NULL, + 0, G_MAXUINT64, 0, + G_PARAM_READWRITE)); + /** + * CdDevice:id: + * + * The device ID. + * + * Since: 0.1.0 + **/ + g_object_class_install_property (object_class, + PROP_ID, + g_param_spec_string ("id", + NULL, NULL, + NULL, + G_PARAM_READWRITE)); + /** + * CdDevice:model: + * + * The device model. + * + * Since: 0.1.0 + **/ + g_object_class_install_property (object_class, + PROP_MODEL, + g_param_spec_string ("model", + NULL, NULL, + NULL, + G_PARAM_READWRITE)); + /** + * CdDevice:kind: + * + * The device kind, e.g. %CD_DEVICE_KIND_KEYBOARD. + * + * Since: 0.1.0 + **/ + g_object_class_install_property (object_class, + PROP_KIND, + g_param_spec_uint ("kind", + NULL, NULL, + CD_DEVICE_KIND_UNKNOWN, + CD_DEVICE_KIND_LAST, + CD_DEVICE_KIND_UNKNOWN, + G_PARAM_READWRITE)); + + g_type_class_add_private (klass, sizeof (CdDevicePrivate)); +} + +/* + * cd_device_init: + */ +static void +cd_device_init (CdDevice *device) +{ + device->priv = CD_DEVICE_GET_PRIVATE (device); + device->priv->profiles = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); +} + +/* + * cd_device_finalize: + */ +static void +cd_device_finalize (GObject *object) +{ + CdDevice *device; + + g_return_if_fail (CD_IS_DEVICE (object)); + + device = CD_DEVICE (object); + + g_free (device->priv->object_path); + g_free (device->priv->id); + g_free (device->priv->model); + g_ptr_array_unref (device->priv->profiles); + if (device->priv->proxy != NULL) + g_object_unref (device->priv->proxy); + + G_OBJECT_CLASS (cd_device_parent_class)->finalize (object); +} + +/** + * cd_device_new: + * + * Creates a new #CdDevice object. + * + * Return value: a new CdDevice object. + * + * Since: 0.1.0 + **/ +CdDevice * +cd_device_new (void) +{ + CdDevice *device; + device = g_object_new (CD_TYPE_DEVICE, NULL); + return CD_DEVICE (device); +} + diff --git a/libcolord/cd-device.h b/libcolord/cd-device.h new file mode 100644 index 0000000..8208e7e --- /dev/null +++ b/libcolord/cd-device.h @@ -0,0 +1,120 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2010 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined (__COLORD_H_INSIDE__) && !defined (CD_COMPILATION) +#error "Only <colord.h> can be included directly." +#endif + +#ifndef __CD_DEVICE_H +#define __CD_DEVICE_H + +#include <glib-object.h> +#include <gio/gio.h> + +#include <libcolord/cd-enum.h> +#include <libcolord/cd-profile.h> + +G_BEGIN_DECLS + +#define CD_TYPE_DEVICE (cd_device_get_type ()) +#define CD_DEVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CD_TYPE_DEVICE, CdDevice)) +#define CD_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CD_TYPE_DEVICE, CdDeviceClass)) +#define CD_IS_DEVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CD_TYPE_DEVICE)) +#define CD_IS_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CD_TYPE_DEVICE)) +#define CD_DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CD_TYPE_DEVICE, CdDeviceClass)) +#define CD_DEVICE_ERROR (cd_device_error_quark ()) +#define CD_DEVICE_TYPE_ERROR (cd_device_error_get_type ()) + +typedef struct _CdDevicePrivate CdDevicePrivate; + +typedef struct +{ + GObject parent; + CdDevicePrivate *priv; +} CdDevice; + +typedef struct +{ + GObjectClass parent_class; + void (*changed) (CdDevice *device); + /*< private >*/ + /* Padding for future expansion */ + void (*_cd_device_reserved1) (void); + void (*_cd_device_reserved2) (void); + void (*_cd_device_reserved3) (void); + void (*_cd_device_reserved4) (void); + void (*_cd_device_reserved5) (void); + void (*_cd_device_reserved6) (void); + void (*_cd_device_reserved7) (void); + void (*_cd_device_reserved8) (void); +} CdDeviceClass; + +/** + * CdDeviceError: + * @CD_DEVICE_ERROR_FAILED: the transaction failed for an unknown reason + * + * Errors that can be thrown + */ +typedef enum +{ + CD_DEVICE_ERROR_FAILED, + CD_DEVICE_ERROR_LAST +} CdDeviceError; + +GType cd_device_get_type (void); +GQuark cd_device_error_quark (void); +CdDevice *cd_device_new (void); +gchar *cd_device_to_string (CdDevice *device); +gboolean cd_device_set_object_path_sync (CdDevice *device, + const gchar *object_path, + GCancellable *cancellable, + GError **error); +gboolean cd_device_set_model_sync (CdDevice *device, + const gchar *value, + GCancellable *cancellable, + GError **error); +gboolean cd_device_set_kind_sync (CdDevice *device, + CdDeviceKind kind, + GCancellable *cancellable, + GError **error); +gboolean cd_device_add_profile_sync (CdDevice *device, + CdProfile *profile, + GCancellable *cancellable, + GError **error); +CdProfile *cd_device_get_profile_for_qualifier_sync (CdDevice *device, + const gchar *qualifier, + GCancellable *cancellable, + GError **error); +gboolean cd_device_make_profile_default_sync (CdDevice *device, + CdProfile *profile, + GCancellable *cancellable, + GError **error); +const gchar *cd_device_get_id (CdDevice *device); +const gchar *cd_device_get_model (CdDevice *device); +guint64 cd_device_get_created (CdDevice *device); +CdDeviceKind cd_device_get_kind (CdDevice *device); +GPtrArray *cd_device_get_profiles (CdDevice *device); +const gchar *cd_device_get_object_path (CdDevice *device); + +G_END_DECLS + +#endif /* __CD_DEVICE_H */ + diff --git a/libcolord/cd-enum.c b/libcolord/cd-enum.c new file mode 100644 index 0000000..0fa1526 --- /dev/null +++ b/libcolord/cd-enum.c @@ -0,0 +1,94 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2010 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** + * SECTION:cd-types + * @short_description: Types used by colord and libcolord + * + * These helper functions provide a way to marshal enumerated values to + * text and back again. + * + * See also: #CdClient, #CdDevice + */ + +#include "config.h" + +#include <glib.h> + +#include "cd-enum.h" + +/** + * cd_device_kind_to_string: + * + * Converts a #CdDeviceKind to a string. + * + * Return value: identifier string + * + * Since: 0.1.0 + **/ +const gchar * +cd_device_kind_to_string (CdDeviceKind kind_enum) +{ + const gchar *kind = NULL; + switch (kind_enum) { + case CD_DEVICE_KIND_DISPLAY: + kind = "display"; + break; + case CD_DEVICE_KIND_SCANNER: + kind = "scanner"; + break; + case CD_DEVICE_KIND_PRINTER: + kind = "printer"; + break; + case CD_DEVICE_KIND_CAMERA: + kind = "camera"; + break; + default: + kind = "unknown"; + break; + } + return kind; +} + +/** + * cd_device_kind_from_string: + * + * Converts a string to a #CdDeviceKind. + * + * Return value: enumerated value + * + * Since: 0.1.0 + **/ +CdDeviceKind +cd_device_kind_from_string (const gchar *type) +{ + if (type == NULL) + return CD_DEVICE_KIND_UNKNOWN; + if (g_strcmp0 (type, "display") == 0) + return CD_DEVICE_KIND_DISPLAY; + if (g_strcmp0 (type, "scanner") == 0) + return CD_DEVICE_KIND_SCANNER; + if (g_strcmp0 (type, "printer") == 0) + return CD_DEVICE_KIND_PRINTER; + if (g_strcmp0 (type, "camera") == 0) + return CD_DEVICE_KIND_CAMERA; + return CD_DEVICE_KIND_UNKNOWN; +} diff --git a/client/cd-common.h b/libcolord/cd-enum.h index b8f74b8..66bffad 100644 --- a/client/cd-common.h +++ b/libcolord/cd-enum.h @@ -19,10 +19,30 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __CD_COMMON_H__ -#define __CD_COMMON_H__ +#if !defined (__COLORD_H_INSIDE__) && !defined (CD_COMPILATION) +#error "Only <colord.h> can be included directly." +#endif -#include "config.h" +#ifndef __CD_TYPES_H +#define __CD_TYPES_H + +#include <glib-object.h> + +G_BEGIN_DECLS + +/** + * CdDeviceKind: + * + * The device type. + **/ +typedef enum { + CD_DEVICE_KIND_UNKNOWN, + CD_DEVICE_KIND_DISPLAY, + CD_DEVICE_KIND_SCANNER, + CD_DEVICE_KIND_PRINTER, + CD_DEVICE_KIND_CAMERA, + CD_DEVICE_KIND_LAST +} CdDeviceKind; #define COLORD_DBUS_SERVICE "org.freedesktop.ColorManager" #define COLORD_DBUS_PATH "/org/freedesktop/ColorManager" @@ -34,5 +54,10 @@ #define CD_DBUS_OPTIONS_MASK_TEMP 1 #define CD_DBUS_OPTIONS_MASK_DISK 2 -#endif /* __CD_COMMON_H__ */ +const gchar *cd_device_kind_to_string (CdDeviceKind kind_enum); +CdDeviceKind cd_device_kind_from_string (const gchar *kind); + +G_END_DECLS + +#endif /* __CD_TYPES_H */ diff --git a/libcolord/cd-profile.c b/libcolord/cd-profile.c new file mode 100644 index 0000000..f94cea3 --- /dev/null +++ b/libcolord/cd-profile.c @@ -0,0 +1,709 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2010 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** + * SECTION:cd-profile + * @short_description: Client object for accessing information about colord profiles + * + * A helper GObject to use for accessing colord profiles, and to be notified + * when it is changed. + * + * See also: #CdClient + */ + +#include "config.h" + +#include <stdlib.h> +#include <stdio.h> +#include <glib.h> +#include <string.h> + +#include "cd-profile.h" + +static void cd_profile_class_init (CdProfileClass *klass); +static void cd_profile_init (CdProfile *profile); +static void cd_profile_finalize (GObject *object); + +#define CD_PROFILE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CD_TYPE_PROFILE, CdProfilePrivate)) + +/** + * CdProfilePrivate: + * + * Private #PkProfile data + **/ +struct _CdProfilePrivate +{ + gchar *filename; + gchar *id; + gchar *object_path; + gchar *qualifier; + gchar *title; + GDBusProxy *proxy; + guint64 created; +}; + +enum { + PROP_0, + PROP_CREATED, + PROP_ID, + PROP_FILENAME, + PROP_QUALIFIER, + PROP_TITLE, + PROP_LAST +}; + +enum { + SIGNAL_CHANGED, + SIGNAL_LAST +}; + +static guint signals [SIGNAL_LAST] = { 0 }; + +G_DEFINE_TYPE (CdProfile, cd_profile, G_TYPE_OBJECT) + +/** + * cd_profile_error_quark: + * + * Return value: An error quark. + * + * Since: 0.1.0 + **/ +GQuark +cd_profile_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("cd_profile_error"); + return quark; +} + +/** + * cd_profile_get_id: + * @profile: a #CdProfile instance. + * + * Gets the profile ID. + * + * Return value: A string, or %NULL for invalid + * + * Since: 0.1.0 + **/ +const gchar * +cd_profile_get_id (CdProfile *profile) +{ + g_return_val_if_fail (CD_IS_PROFILE (profile), NULL); + return profile->priv->id; +} + +/** + * cd_profile_get_filename: + * @profile: a #CdProfile instance. + * + * Gets the profile filename. + * + * Return value: A string, or %NULL for invalid + * + * Since: 0.1.0 + **/ +const gchar * +cd_profile_get_filename (CdProfile *profile) +{ + g_return_val_if_fail (CD_IS_PROFILE (profile), NULL); + return profile->priv->filename; +} + +/** + * cd_profile_get_qualifier: + * @profile: a #CdProfile instance. + * + * Gets the profile qualifier. + * + * Return value: A string, or %NULL for invalid + * + * Since: 0.1.0 + **/ +const gchar * +cd_profile_get_qualifier (CdProfile *profile) +{ + g_return_val_if_fail (CD_IS_PROFILE (profile), NULL); + return profile->priv->qualifier; +} + +/** + * cd_profile_get_title: + * @profile: a #CdProfile instance. + * + * Gets the profile title. + * + * Return value: A string, or %NULL for invalid + * + * Since: 0.1.0 + **/ +const gchar * +cd_profile_get_title (CdProfile *profile) +{ + g_return_val_if_fail (CD_IS_PROFILE (profile), NULL); + return profile->priv->title; +} + +/** + * cd_profile_get_created: + * @profile: a #CdProfile instance. + * + * Gets the profile ID. + * + * Return value: A value in seconds, or 0 for invalid + * + * Since: 0.1.0 + **/ +guint64 +cd_profile_get_created (CdProfile *profile) +{ + g_return_val_if_fail (CD_IS_PROFILE (profile), 0); + return profile->priv->created; +} + +/** + * cd_profile_dbus_properties_changed: + **/ +static void +cd_profile_dbus_properties_changed (GDBusProxy *proxy, + GVariant *changed_properties, + const gchar * const *invalidated_properties, + CdProfile *profile) +{ + guint i; + guint len; + GVariantIter iter; + gchar *property_name; + GVariant *property_value; + + len = g_variant_iter_init (&iter, changed_properties); + for (i=0; i < len; i++) { + g_variant_get_child (changed_properties, i, + "{sv}", + &property_name, + &property_value); + if (g_strcmp0 (property_name, "Qualifier") == 0) { + g_free (profile->priv->qualifier); + profile->priv->qualifier = g_variant_dup_string (property_value, NULL); + } else if (g_strcmp0 (property_name, "Filename") == 0) { + g_free (profile->priv->filename); + profile->priv->filename = g_variant_dup_string (property_value, NULL); + } else if (g_strcmp0 (property_name, "Title") == 0) { + g_free (profile->priv->title); + profile->priv->title = g_variant_dup_string (property_value, NULL); + } else { + g_warning ("%s property unhandled", property_name); + } + g_variant_unref (property_value); + } +} + +/** + * cd_profile_dbus_signal_cb: + **/ +static void +cd_profile_dbus_signal_cb (GDBusProxy *proxy, + gchar *sender_name, + gchar *signal_name, + GVariant *parameters, + CdProfile *profile) +{ + gchar *object_path_tmp = NULL; + + if (g_strcmp0 (signal_name, "Changed") == 0) { + g_debug ("emit Changed on %s", profile->priv->object_path); + g_signal_emit (profile, signals[SIGNAL_CHANGED], 0); + } else { + g_warning ("unhandled signal '%s'", signal_name); + } + g_free (object_path_tmp); +} + +/** + * cd_profile_set_object_path_sync: + * @profile: a #CdProfile instance. + * @object_path: The colord object path. + * @cancellable: a #GCancellable or %NULL + * @error: a #GError, or %NULL. + * + * Sets the object path of the object and fills up initial properties. + * + * Return value: #TRUE for success, else #FALSE and @error is used + * + * Since: 0.1.0 + **/ +gboolean +cd_profile_set_object_path_sync (CdProfile *profile, + const gchar *object_path, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = TRUE; + GError *error_local = NULL; + GVariant *created = NULL; + GVariant *filename = NULL; + GVariant *id = NULL; + GVariant *profiles = NULL; + GVariant *qualifier = NULL; + GVariant *title = NULL; + + g_return_val_if_fail (CD_IS_PROFILE (profile), FALSE); + g_return_val_if_fail (profile->priv->proxy == NULL, FALSE); + + /* connect to the daemon */ + profile->priv->proxy = + g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + COLORD_DBUS_SERVICE, + object_path, + COLORD_DBUS_INTERFACE_PROFILE, + cancellable, + &error_local); + if (profile->priv->proxy == NULL) { + ret = FALSE; + g_set_error (error, + CD_PROFILE_ERROR, + CD_PROFILE_ERROR_FAILED, + "Failed to connect to profile %s: %s", + object_path, + error_local->message); + g_error_free (error_local); + goto out; + } + + /* save object path */ + profile->priv->object_path = g_strdup (object_path); + + /* get profile id */ + id = g_dbus_proxy_get_cached_property (profile->priv->proxy, + "ProfileId"); + if (id != NULL) + profile->priv->id = g_variant_dup_string (id, NULL); + + /* get filename */ + filename = g_dbus_proxy_get_cached_property (profile->priv->proxy, + "Filename"); + if (filename != NULL) + profile->priv->filename = g_variant_dup_string (filename, NULL); + + /* get qualifier */ + qualifier = g_dbus_proxy_get_cached_property (profile->priv->proxy, + "Qualifier"); + if (qualifier != NULL) + profile->priv->qualifier = g_variant_dup_string (qualifier, NULL); + + /* get title */ + title = g_dbus_proxy_get_cached_property (profile->priv->proxy, + "Title"); + if (title != NULL) + profile->priv->title = g_variant_dup_string (title, NULL); + + /* get created */ + created = g_dbus_proxy_get_cached_property (profile->priv->proxy, + "Created"); + if (created != NULL) + profile->priv->created = g_variant_get_uint64 (created); + + /* get signals from DBus */ + g_signal_connect (profile->priv->proxy, + "g-signal", + G_CALLBACK (cd_profile_dbus_signal_cb), + profile); + + /* watch if any remote properties change */ + g_signal_connect (profile->priv->proxy, + "g-properties-changed", + G_CALLBACK (cd_profile_dbus_properties_changed), + profile); + + /* success */ + g_debug ("Connected to profile %s", + profile->priv->id); +out: + if (id != NULL) + g_variant_unref (id); + if (filename != NULL) + g_variant_unref (filename); + if (created != NULL) + g_variant_unref (created); + if (qualifier != NULL) + g_variant_unref (qualifier); + if (title != NULL) + g_variant_unref (title); + if (profiles != NULL) + g_variant_unref (profiles); + return ret; +} + +/** + * cd_profile_set_property_sync: + **/ +static gboolean +cd_profile_set_property_sync (CdProfile *profile, + const gchar *name, + const gchar *value, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = TRUE; + GError *error_local = NULL; + GVariant *response = NULL; + + /* execute sync method */ + response = g_dbus_proxy_call_sync (profile->priv->proxy, + "SetProperty", + g_variant_new ("(ss)", + name, + value), + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, &error_local); + if (response == NULL) { + ret = FALSE; + g_set_error (error, + CD_PROFILE_ERROR, + CD_PROFILE_ERROR_FAILED, + "Failed to set property: %s", + error_local->message); + g_error_free (error_local); + goto out; + } +out: + if (response != NULL) + g_variant_unref (response); + return ret; +} + +/** + * cd_profile_set_filename_sync: + * @profile: a #CdProfile instance. + * @value: The filename. + * @cancellable: a #GCancellable or %NULL + * @error: a #GError, or %NULL. + * + * Sets the profile model. + * + * Return value: #TRUE for success, else #FALSE and @error is used + * + * Since: 0.1.0 + **/ +gboolean +cd_profile_set_filename_sync (CdProfile *profile, + const gchar *value, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_fail (CD_IS_PROFILE (profile), FALSE); + g_return_val_if_fail (profile->priv->proxy != NULL, FALSE); + + /* execute sync helper */ + return cd_profile_set_property_sync (profile, "Filename", value, + cancellable, error); +} + +/** + * cd_profile_set_qualifier_sync: + * @profile: a #CdProfile instance. + * @value: The qualifier. + * @cancellable: a #GCancellable or %NULL + * @error: a #GError, or %NULL. + * + * Sets the profile model. + * + * Return value: #TRUE for success, else #FALSE and @error is used + * + * Since: 0.1.0 + **/ +gboolean +cd_profile_set_qualifier_sync (CdProfile *profile, + const gchar *value, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_fail (CD_IS_PROFILE (profile), FALSE); + g_return_val_if_fail (profile->priv->proxy != NULL, FALSE); + + /* execute sync helper */ + return cd_profile_set_property_sync (profile, "Qualifier", value, + cancellable, error); +} + +/** + * cd_profile_get_object_path: + * @profile: a #CdProfile instance. + * + * Gets the object path for the profile. + * + * Return value: the object path, or %NULL + * + * Since: 0.1.0 + **/ +const gchar * +cd_profile_get_object_path (CdProfile *profile) +{ + g_return_val_if_fail (CD_IS_PROFILE (profile), NULL); + return profile->priv->object_path; +} + +/** + * cd_profile_to_string: + * @profile: a #CdProfile instance. + * + * Converts the profile to a string description. + * + * Return value: text representation of #CdProfile + * + * Since: 0.1.0 + **/ +gchar * +cd_profile_to_string (CdProfile *profile) +{ + struct tm *time_tm; + time_t t; + gchar time_buf[256]; + GString *string; + + g_return_val_if_fail (CD_IS_PROFILE (profile), NULL); + + /* get a human readable time */ + t = (time_t) profile->priv->created; + time_tm = localtime (&t); + strftime (time_buf, sizeof time_buf, "%c", time_tm); + + string = g_string_new (""); + g_string_append_printf (string, " object-path: %s\n", + profile->priv->object_path); + g_string_append_printf (string, " created: %s\n", + time_buf); + + return g_string_free (string, FALSE); +} + +/* + * cd_profile_set_property: + */ +static void +cd_profile_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + CdProfile *profile = CD_PROFILE (object); + + switch (prop_id) { + case PROP_ID: + g_free (profile->priv->id); + profile->priv->id = g_strdup (g_value_get_string (value)); + break; + case PROP_FILENAME: + g_free (profile->priv->filename); + profile->priv->filename = g_strdup (g_value_get_string (value)); + break; + case PROP_QUALIFIER: + g_free (profile->priv->qualifier); + profile->priv->qualifier = g_strdup (g_value_get_string (value)); + break; + case PROP_TITLE: + g_free (profile->priv->title); + profile->priv->title = g_strdup (g_value_get_string (value)); + break; + case PROP_CREATED: + profile->priv->created = g_value_get_uint64 (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* + * cd_profile_get_property: + */ +static void +cd_profile_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + CdProfile *profile = CD_PROFILE (object); + + switch (prop_id) { + case PROP_CREATED: + g_value_set_uint64 (value, profile->priv->created); + break; + case PROP_ID: + g_value_set_string (value, profile->priv->id); + break; + case PROP_FILENAME: + g_value_set_string (value, profile->priv->filename); + break; + case PROP_QUALIFIER: + g_value_set_string (value, profile->priv->qualifier); + break; + case PROP_TITLE: + g_value_set_string (value, profile->priv->title); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* + * cd_profile_class_init: + */ +static void +cd_profile_class_init (CdProfileClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + object_class->finalize = cd_profile_finalize; + object_class->set_property = cd_profile_set_property; + object_class->get_property = cd_profile_get_property; + + /** + * CdProfile::changed: + * @profile: the #CdProfile instance that emitted the signal + * + * The ::changed signal is emitted when the profile data has changed. + * + * Since: 0.1.0 + **/ + signals [SIGNAL_CHANGED] = + g_signal_new ("changed", + G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CdProfileClass, changed), + NULL, NULL, g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * CdProfile:created: + * + * The last time the profile was updated. + * + * Since: 0.1.0 + **/ + g_object_class_install_property (object_class, + PROP_CREATED, + g_param_spec_uint64 ("created", + NULL, NULL, + 0, G_MAXUINT64, 0, + G_PARAM_READWRITE)); + /** + * CdProfile:id: + * + * The profile ID. + * + * Since: 0.1.0 + **/ + g_object_class_install_property (object_class, + PROP_ID, + g_param_spec_string ("id", + NULL, NULL, + NULL, + G_PARAM_READWRITE)); + /** + * CdProfile:filename: + * + * The profile filename. + * + * Since: 0.1.0 + **/ + g_object_class_install_property (object_class, + PROP_FILENAME, + g_param_spec_string ("filename", + NULL, NULL, + NULL, + G_PARAM_READWRITE)); + /** + * CdProfile:qualifier: + * + * The profile qualifier. + * + * Since: 0.1.0 + **/ + g_object_class_install_property (object_class, + PROP_QUALIFIER, + g_param_spec_string ("qualifier", + NULL, NULL, + NULL, + G_PARAM_READWRITE)); + + /** + * CdProfile:title: + * + * The profile title. + * + * Since: 0.1.0 + **/ + g_object_class_install_property (object_class, + PROP_TITLE, + g_param_spec_string ("title", + NULL, NULL, + NULL, + G_PARAM_READWRITE)); + + g_type_class_add_private (klass, sizeof (CdProfilePrivate)); +} + +/* + * cd_profile_init: + */ +static void +cd_profile_init (CdProfile *profile) +{ + profile->priv = CD_PROFILE_GET_PRIVATE (profile); +} + +/* + * cd_profile_finalize: + */ +static void +cd_profile_finalize (GObject *object) +{ + CdProfile *profile; + + g_return_if_fail (CD_IS_PROFILE (object)); + + profile = CD_PROFILE (object); + + g_free (profile->priv->object_path); + g_free (profile->priv->id); + g_free (profile->priv->filename); + g_free (profile->priv->qualifier); + g_free (profile->priv->title); + if (profile->priv->proxy != NULL) + g_object_unref (profile->priv->proxy); + + G_OBJECT_CLASS (cd_profile_parent_class)->finalize (object); +} + +/** + * cd_profile_new: + * + * Creates a new #CdProfile object. + * + * Return value: a new CdProfile object. + * + * Since: 0.1.0 + **/ +CdProfile * +cd_profile_new (void) +{ + CdProfile *profile; + profile = g_object_new (CD_TYPE_PROFILE, NULL); + return CD_PROFILE (profile); +} + diff --git a/libcolord/cd-profile.h b/libcolord/cd-profile.h new file mode 100644 index 0000000..2ceb543 --- /dev/null +++ b/libcolord/cd-profile.h @@ -0,0 +1,107 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2010 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined (__COLORD_H_INSIDE__) && !defined (CD_COMPILATION) +#error "Only <colord.h> can be included directly." +#endif + +#ifndef __CD_PROFILE_H +#define __CD_PROFILE_H + +#include <glib-object.h> +#include <gio/gio.h> + +#include <libcolord/cd-enum.h> + +G_BEGIN_DECLS + +#define CD_TYPE_PROFILE (cd_profile_get_type ()) +#define CD_PROFILE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CD_TYPE_PROFILE, CdProfile)) +#define CD_PROFILE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CD_TYPE_PROFILE, CdProfileClass)) +#define CD_IS_PROFILE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CD_TYPE_PROFILE)) +#define CD_IS_PROFILE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CD_TYPE_PROFILE)) +#define CD_PROFILE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CD_TYPE_PROFILE, CdProfileClass)) +#define CD_PROFILE_ERROR (cd_profile_error_quark ()) +#define CD_PROFILE_TYPE_ERROR (cd_profile_error_get_type ()) + +typedef struct _CdProfilePrivate CdProfilePrivate; + +typedef struct +{ + GObject parent; + CdProfilePrivate *priv; +} CdProfile; + +typedef struct +{ + GObjectClass parent_class; + void (*changed) (CdProfile *profile); + /*< private >*/ + /* Padding for future expansion */ + void (*_cd_profile_reserved1) (void); + void (*_cd_profile_reserved2) (void); + void (*_cd_profile_reserved3) (void); + void (*_cd_profile_reserved4) (void); + void (*_cd_profile_reserved5) (void); + void (*_cd_profile_reserved6) (void); + void (*_cd_profile_reserved7) (void); + void (*_cd_profile_reserved8) (void); +} CdProfileClass; + +/** + * CdProfileError: + * @CD_PROFILE_ERROR_FAILED: the transaction failed for an unknown reason + * + * Errors that can be thrown + */ +typedef enum +{ + CD_PROFILE_ERROR_FAILED, + CD_PROFILE_ERROR_LAST +} CdProfileError; + +GType cd_profile_get_type (void); +GQuark cd_profile_error_quark (void); +CdProfile *cd_profile_new (void); +gchar *cd_profile_to_string (CdProfile *profile); +gboolean cd_profile_set_object_path_sync (CdProfile *profile, + const gchar *object_path, + GCancellable *cancellable, + GError **error); +gboolean cd_profile_set_filename_sync (CdProfile *profile, + const gchar *value, + GCancellable *cancellable, + GError **error); +gboolean cd_profile_set_qualifier_sync (CdProfile *profile, + const gchar *value, + GCancellable *cancellable, + GError **error); +const gchar *cd_profile_get_id (CdProfile *profile); +const gchar *cd_profile_get_filename (CdProfile *profile); +const gchar *cd_profile_get_qualifier (CdProfile *profile); +const gchar *cd_profile_get_title (CdProfile *profile); +guint64 cd_profile_get_created (CdProfile *profile); +const gchar *cd_profile_get_object_path (CdProfile *profile); + +G_END_DECLS + +#endif /* __CD_PROFILE_H */ + diff --git a/libcolord/cd-self-test.c b/libcolord/cd-self-test.c new file mode 100644 index 0000000..8490ead --- /dev/null +++ b/libcolord/cd-self-test.c @@ -0,0 +1,296 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2010 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include <limits.h> +#include <stdlib.h> + +#include <glib.h> +#include <glib-object.h> + +#include "cd-client.h" + +/** ver:1.0 ***********************************************************/ +static GMainLoop *_test_loop = NULL; +static guint _test_loop_timeout_id = 0; + +static gboolean +_g_test_hang_check_cb (gpointer user_data) +{ + g_main_loop_quit (_test_loop); + _test_loop_timeout_id = 0; + return FALSE; +} + +/** + * _g_test_loop_run_with_timeout: + **/ +static void +_g_test_loop_run_with_timeout (guint timeout_ms) +{ + g_assert (_test_loop_timeout_id == 0); + _test_loop = g_main_loop_new (NULL, FALSE); + _test_loop_timeout_id = g_timeout_add (timeout_ms, _g_test_hang_check_cb, NULL); + g_main_loop_run (_test_loop); +} + +/** + * _g_test_realpath: + **/ +static gchar * +_g_test_realpath (const gchar *relpath) +{ + gchar *full; + char full_tmp[PATH_MAX]; + realpath (relpath, full_tmp); + full = g_strdup (full_tmp); + return full; +} + +/**********************************************************************/ + +static void +colord_client_func (void) +{ + CdClient *client; + CdDevice *device; + CdProfile *profile; + CdProfile *profile_tmp; + gboolean ret; + gchar *filename; + GError *error = NULL; + GPtrArray *array; + GPtrArray *devices; + GPtrArray *profiles; + + /* create */ + client = cd_client_new (); + g_assert (client != NULL); + + /* connect */ + ret = cd_client_connect_sync (client, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + /* get number of devices */ + devices = cd_client_get_devices_sync (client, NULL, &error); + g_assert_no_error (error); + g_assert (devices != NULL); + + /* get number of profiles */ + profiles = cd_client_get_profiles_sync (client, NULL, &error); + g_assert_no_error (error); + g_assert (profiles != NULL); + + /* create device */ + device = cd_client_create_device_sync (client, + "device-self-test", + CD_DBUS_OPTIONS_MASK_TEMP, + NULL, + &error); + + g_assert_cmpstr (cd_device_get_object_path (device), ==, + "/org/freedesktop/ColorManager/device_self_test"); + g_assert_cmpstr (cd_device_get_id (device), ==, "device-self-test"); + + /* get new number of devices */ + array = cd_client_get_devices_sync (client, NULL, &error); + g_assert_no_error (error); + g_assert (array != NULL); + g_assert_cmpint (devices->len + 1, ==, array->len); + g_ptr_array_unref (array); + + /* set device model */ + ret = cd_device_set_model_sync (device, "CRAY 3000", NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + /* set device model */ + ret = cd_device_set_kind_sync (device, CD_DEVICE_KIND_DISPLAY, + NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + /* wait for daemon */ + _g_test_loop_run_with_timeout (50); + + /* check device model */ + g_assert_cmpstr (cd_device_get_model (device), ==, "CRAY 3000"); + + /* check device kind */ + g_assert_cmpint (cd_device_get_kind (device), ==, CD_DEVICE_KIND_DISPLAY); + + /* create profile */ + profile = cd_client_create_profile_sync (client, + "profile-self-test", + CD_DBUS_OPTIONS_MASK_TEMP, + NULL, + &error); + + g_assert_cmpstr (cd_profile_get_object_path (profile), ==, + "/org/freedesktop/ColorManager/profile_self_test"); + g_assert_cmpstr (cd_profile_get_id (profile), ==, "profile-self-test"); + + /* get new number of profiles */ + array = cd_client_get_profiles_sync (client, NULL, &error); + g_assert_no_error (error); + g_assert (array != NULL); + g_assert_cmpint (profiles->len + 1, ==, array->len); + g_ptr_array_unref (array); + + /* set profile filename */ + filename = _g_test_realpath (TESTDATADIR "/ibm-t61.icc"); + ret = cd_profile_set_filename_sync (profile, filename, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + /* set profile qualifier */ + ret = cd_profile_set_qualifier_sync (profile, "Epson.RGB.300dpi", + NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + /* wait for daemon */ + _g_test_loop_run_with_timeout (50); + + /* check profile filename */ + g_assert (g_str_has_suffix (cd_profile_get_filename (profile), "data/tests/ibm-t61.icc")); + + /* check profile qualifier */ + g_assert_cmpstr (cd_profile_get_qualifier (profile), ==, "Epson.RGB.300dpi"); + + /* check profile title set from ICC profile */ + g_assert_cmpstr (cd_profile_get_title (profile), ==, "Huey, LENOVO - 6464Y1H - 15\" (2009-12-23)"); + + /* check none assigned */ + array = cd_device_get_profiles (device); + g_assert_cmpint (array->len, ==, 0); + g_ptr_array_unref (array); + + /* check nothing matches qualifier */ + profile_tmp = cd_device_get_profile_for_qualifier_sync (device, + "Epson.RGB.300dpi", + NULL, + &error); + g_assert_error (error, CD_DEVICE_ERROR, CD_DEVICE_ERROR_FAILED); + g_assert (profile_tmp == NULL); + g_clear_error (&error); + + /* assign profile to device */ + ret = cd_device_add_profile_sync (device, profile, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + /* wait for daemon */ + _g_test_loop_run_with_timeout (50); + + /* check profile assigned */ + array = cd_device_get_profiles (device); + g_assert (array != NULL); + g_assert_cmpint (array->len, ==, 1); + profile_tmp = g_ptr_array_index (array, 0); + g_assert_cmpstr (cd_profile_get_qualifier (profile_tmp), ==, "Epson.RGB.300dpi"); + g_ptr_array_unref (array); + + /* make profile default */ + ret = cd_device_make_profile_default_sync (device, profile, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + /* check matches exact qualifier */ + profile_tmp = cd_device_get_profile_for_qualifier_sync (device, + "Epson.RGB.300dpi", + NULL, + &error); + g_assert_no_error (error); + g_assert (profile_tmp != NULL); + g_assert_cmpstr (cd_profile_get_object_path (profile), ==, + "/org/freedesktop/ColorManager/profile_self_test"); + g_object_unref (profile_tmp); + + /* check matches wildcarded qualifier */ + profile_tmp = cd_device_get_profile_for_qualifier_sync (device, + "Epson.RGB.*", + NULL, + &error); + g_assert_no_error (error); + g_assert (profile_tmp != NULL); + g_assert_cmpstr (cd_profile_get_object_path (profile), ==, + "/org/freedesktop/ColorManager/profile_self_test"); + g_object_unref (profile_tmp); + + /* delete profile */ + ret = cd_client_delete_profile_sync (client, profile, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + /* get new number of profiles */ + array = cd_client_get_profiles_sync (client, NULL, &error); + g_assert_no_error (error); + g_assert (array != NULL); + g_assert_cmpint (profiles->len, ==, array->len); + g_ptr_array_unref (array); + + /* wait for daemon */ + _g_test_loop_run_with_timeout (50); + + /* ensure device no longer lists deleted profile */ + array = cd_device_get_profiles (device); + g_assert (array != NULL); + g_assert_cmpint (array->len, ==, 0); + g_ptr_array_unref (array); + + /* delete device */ + ret = cd_client_delete_device_sync (client, device, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + /* get new number of devices */ + array = cd_client_get_devices_sync (client, NULL, &error); + g_assert_no_error (error); + g_assert (array != NULL); + g_assert_cmpint (devices->len, ==, array->len); + g_ptr_array_unref (array); + + g_free (filename); + g_ptr_array_unref (devices); + g_ptr_array_unref (profiles); + g_object_unref (device); + g_object_unref (profile); + g_object_unref (client); +} + +int +main (int argc, char **argv) +{ + g_type_init (); + g_thread_init (NULL); + g_test_init (&argc, &argv, NULL); + + /* only critical and error are fatal */ + g_log_set_fatal_mask (NULL, G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL); + + /* tests go here */ + g_test_add_func ("/colord/client", colord_client_func); + return g_test_run (); +} + diff --git a/libcolord/cd-version.h.in b/libcolord/cd-version.h.in new file mode 100644 index 0000000..592fb10 --- /dev/null +++ b/libcolord/cd-version.h.in @@ -0,0 +1,69 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2010 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** + * SECTION:cd-version + * @short_description: Obtains the version for the installed colord + * + * These compile time macros allow the user to enable parts of client code + * depending on the version of libcolord installed. + * + * See also: #CdClient, #CdDevice + */ + +#if !defined (__COLORD_H_INSIDE__) && !defined (CD_COMPILATION) +#error "Only <colord.h> can be included directly." +#endif + +#ifndef __CD_VERSION_H +#define __CD_VERSION_H + +/** + * CD_CHECK_VERSION: + * + * The compile-time major version + */ +#define CD_MAJOR_VERSION (@CD_MAJOR_VERSION@) + +/** + * CD_CHECK_MINOR: + * + * The compile-time minor version + */ +#define CD_MINOR_VERSION (@CD_MINOR_VERSION@) + +/** + * CD_MICRO_VERSION: + * + * The compile-time micro version + */ +#define CD_MICRO_VERSION (@CD_MICRO_VERSION@) + +/* check whether a colord version equal to or greater than + * major.minor.micro. + */ +#define CD_CHECK_VERSION(major,minor,micro) \ + (CD_MAJOR_VERSION > (major) || \ + (CD_MAJOR_VERSION == (major) && CD_MINOR_VERSION > (minor)) || \ + (CD_MAJOR_VERSION == (major) && CD_MINOR_VERSION == (minor) && \ + CD_MICRO_VERSION >= (micro))) + +#endif /* __CD_VERSION_H */ diff --git a/libcolord/colord.h b/libcolord/colord.h new file mode 100644 index 0000000..de11f29 --- /dev/null +++ b/libcolord/colord.h @@ -0,0 +1,46 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2010 Richard Hughes <richard@hughsie.com> + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** + * SECTION:colord + * @short_description: Client objects for accessing colord + * + * These objects allow client programs to get access to devices that can + * be color managed and profiles for changing them. + * + * See also: #CdClient, #CdDevice + */ + +#ifndef __COLORD_H__ +#define __COLORD_H__ + +#define __COLORD_H_INSIDE__ + +#include <libcolord/cd-client.h> +#include <libcolord/cd-device.h> +#include <libcolord/cd-enum.h> +#include <libcolord/cd-profile.h> +#include <libcolord/cd-version.h> + +#undef __COLORD_H_INSIDE__ + +#endif /* __COLORD_H__ */ + diff --git a/libcolord/colord.pc.in b/libcolord/colord.pc.in new file mode 100644 index 0000000..a4ae9f4 --- /dev/null +++ b/libcolord/colord.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: colord +Description: colord is a system daemon for managing color devices +Version: @VERSION@ +Requires.private: dbus-1, gthread-2.0 +Requires: glib-2.0, gobject-2.0 +Libs: -L${libdir} -lcolord +Cflags: -I${includedir}/libcolord diff --git a/src/cd-device.c b/src/cd-device.c index 4c1d161..867a482 100644 --- a/src/cd-device.c +++ b/src/cd-device.c @@ -145,13 +145,36 @@ cd_device_set_profiles (CdDevice *device, GPtrArray *profiles) } /** - * cd_device_dbus_emit_changed: + * cd_device_dbus_emit_property_changed: **/ static void -cd_device_dbus_emit_changed (CdDevice *device) +cd_device_dbus_emit_property_changed (CdDevice *device, + const gchar *property_name, + GVariant *property_value) { gboolean ret; - GError *error = NULL; + GError *error_local = NULL; + GVariantBuilder builder; + GVariantBuilder invalidated_builder; + + /* build the dict */ + g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as")); + g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); + g_variant_builder_add (&builder, + "{sv}", + property_name, + property_value); + g_dbus_connection_emit_signal (device->priv->connection, + NULL, + device->priv->object_path, + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + g_variant_new ("(sa{sv}as)", + COLORD_DBUS_INTERFACE_DEVICE, + &builder, + &invalidated_builder), + &error_local); + g_assert_no_error (error_local); /* emit signal */ ret = g_dbus_connection_emit_signal (device->priv->connection, @@ -160,10 +183,10 @@ cd_device_dbus_emit_changed (CdDevice *device) COLORD_DBUS_INTERFACE_DEVICE, "Changed", NULL, - &error); + &error_local); if (!ret) { - g_warning ("failed to send signal %s", error->message); - g_error_free (error); + g_warning ("failed to send signal %s", error_local->message); + g_error_free (error_local); } } @@ -219,6 +242,76 @@ out: } /** + * cd_device_get_profiles_as_variant: + **/ +static GVariant * +cd_device_get_profiles_as_variant (CdDevice *device) +{ + CdProfile *profile; + guint i; + GVariant **profiles = NULL; + GVariant *value; + + /* copy the object paths */ + profiles = g_new0 (GVariant *, device->priv->profiles->len + 1); + for (i=0; i<device->priv->profiles->len; i++) { + profile = g_ptr_array_index (device->priv->profiles, i); + profiles[i] = g_variant_new_object_path (cd_profile_get_object_path (profile)); + } + + /* format the value */ + value = g_variant_new_array (G_VARIANT_TYPE_OBJECT_PATH, + profiles, + device->priv->profiles->len); + g_free (profiles); + return value; +} + +/** + * cd_device_remove_profile: + **/ +gboolean +cd_device_remove_profile (CdDevice *device, + const gchar *profile_object_path, + GError **error) +{ + CdDevicePrivate *priv = device->priv; + CdProfile *profile_tmp; + gboolean ret = FALSE; + guint i; + + /* check the profile exists on this device */ + for (i=0; i<priv->profiles->len; i++) { + profile_tmp = g_ptr_array_index (priv->profiles, i); + if (g_strcmp0 (profile_object_path, + cd_profile_get_object_path (profile_tmp)) == 0) { + ret = TRUE; + break; + } + } + if (!ret) { + g_set_error (error, + CD_MAIN_ERROR, + CD_MAIN_ERROR_FAILED, + "profile object path '%s' does not exist on '%s'", + profile_object_path, + priv->object_path); + goto out; + } + + /* remove from the array */ + ret = g_ptr_array_remove (priv->profiles, profile_tmp); + g_assert (ret); + + /* emit */ + cd_device_dbus_emit_property_changed (device, + "Profiles", + cd_device_get_profiles_as_variant (device)); +out: + return ret; +} + +/** * cd_device_dbus_method_call: **/ static void @@ -237,6 +330,7 @@ cd_device_dbus_method_call (GDBusConnection *connection_, const gchar *sender, gchar *property_name = NULL; gchar *property_value = NULL; gchar *regex = NULL; + GError *error = NULL; guint i; GVariant *tuple = NULL; GVariant *value = NULL; @@ -283,7 +377,35 @@ cd_device_dbus_method_call (GDBusConnection *connection_, const gchar *sender, g_ptr_array_add (priv->profiles, profile); /* emit */ - cd_device_dbus_emit_changed (device); + cd_device_dbus_emit_property_changed (device, + "Profiles", + cd_device_get_profiles_as_variant (device)); + g_dbus_method_invocation_return_value (invocation, NULL); + goto out; + } + + if (g_strcmp0 (method_name, "RemoveProfile") == 0) { + + /* require auth */ + ret = cd_main_sender_authenticated (invocation, + sender, + "org.freedesktop.color-manager.modify-device"); + if (!ret) + goto out; + + /* try to remove */ + g_variant_get (parameters, "(o)", + &profile_object_path); + ret = cd_device_remove_profile (device, + profile_object_path, + &error); + if (!ret) { + g_dbus_method_invocation_return_gerror (invocation, + error); + g_error_free (error); + goto out; + } + g_dbus_method_invocation_return_value (invocation, NULL); goto out; } @@ -359,7 +481,9 @@ cd_device_dbus_method_call (GDBusConnection *connection_, const gchar *sender, } /* emit */ - cd_device_dbus_emit_changed (device); + cd_device_dbus_emit_property_changed (device, + "Profiles", + cd_device_get_profiles_as_variant (device)); g_dbus_method_invocation_return_value (invocation, NULL); goto out; } @@ -378,17 +502,23 @@ cd_device_dbus_method_call (GDBusConnection *connection_, const gchar *sender, g_variant_get (parameters, "(ss)", &property_name, &property_value); + g_debug ("Attempting to set %s to %s", + property_name, property_value); if (g_strcmp0 (property_name, "Model") == 0) { g_free (priv->model); priv->model = g_strdup (property_value); - cd_device_dbus_emit_changed (device); + cd_device_dbus_emit_property_changed (device, + property_name, + g_variant_new_string (priv->model)); g_dbus_method_invocation_return_value (invocation, NULL); goto out; } if (g_strcmp0 (property_name, "Kind") == 0) { g_free (priv->kind); priv->kind = g_strdup (property_value); - cd_device_dbus_emit_changed (device); + cd_device_dbus_emit_property_changed (device, + property_name, + g_variant_new_string (priv->kind)); g_dbus_method_invocation_return_value (invocation, NULL); goto out; } @@ -419,10 +549,8 @@ cd_device_dbus_get_property (GDBusConnection *connection_, const gchar *sender, const gchar *property_name, GError **error, gpointer user_data) { - CdDevicePrivate *priv = CD_DEVICE (user_data)->priv; - CdProfile *profile; - guint i; - GVariant **profiles = NULL; + CdDevice *device = CD_DEVICE (user_data); + CdDevicePrivate *priv = device->priv; GVariant *retval = NULL; if (g_strcmp0 (property_name, "Created") == 0) { @@ -448,18 +576,7 @@ cd_device_dbus_get_property (GDBusConnection *connection_, const gchar *sender, goto out; } if (g_strcmp0 (property_name, "Profiles") == 0) { - - /* copy the object paths */ - profiles = g_new0 (GVariant *, priv->profiles->len + 1); - for (i=0; i<priv->profiles->len; i++) { - profile = g_ptr_array_index (priv->profiles, i); - profiles[i] = g_variant_new_object_path (cd_profile_get_object_path (profile)); - } - - /* format the value */ - retval = g_variant_new_array (G_VARIANT_TYPE_OBJECT_PATH, - profiles, - priv->profiles->len); + retval = cd_device_get_profiles_as_variant (device); goto out; } diff --git a/src/cd-device.h b/src/cd-device.h index f9b5bdf..b47bcaf 100644 --- a/src/cd-device.h +++ b/src/cd-device.h @@ -24,6 +24,8 @@ #include <glib-object.h> +#include "cd-profile.h" + G_BEGIN_DECLS #define CD_TYPE_DEVICE (cd_device_get_type ()) @@ -61,6 +63,9 @@ void cd_device_set_id (CdDevice *device, GPtrArray *cd_device_get_profiles (CdDevice *device); void cd_device_set_profiles (CdDevice *device, GPtrArray *profiles); +gboolean cd_device_remove_profile (CdDevice *device, + const gchar *profile_object_path, + GError **error); const gchar *cd_device_get_object_path (CdDevice *device); gboolean cd_device_register_object (CdDevice *device, GDBusConnection *connection, diff --git a/src/cd-main.c b/src/cd-main.c index fce326e..5095815 100644 --- a/src/cd-main.c +++ b/src/cd-main.c @@ -47,12 +47,29 @@ cd_main_profile_removed (CdProfile *profile) { gboolean ret; gchar *object_path_tmp; + CdDevice *device_tmp; GError *error = NULL; + GPtrArray *devices; + guint i; /* remove from the array before emitting */ object_path_tmp = g_strdup (cd_profile_get_object_path (profile)); cd_profile_array_remove (profiles_array, profile); + /* try to remove this profile from all devices */ + devices = cd_device_array_get_array (devices_array); + for (i=0; i<devices->len; i++) { + device_tmp = g_ptr_array_index (devices, i); + ret = cd_device_remove_profile (device_tmp, + object_path_tmp, + NULL); + if (ret) { + g_debug ("automatically removing %s from %s as removed", + object_path_tmp, + cd_device_get_object_path (device_tmp)); + } + } + /* emit signal */ g_debug ("Emitting ProfileRemoved(%s)", object_path_tmp); ret = g_dbus_connection_emit_signal (connection, @@ -68,6 +85,7 @@ cd_main_profile_removed (CdProfile *profile) g_error_free (error); } g_free (object_path_tmp); + g_ptr_array_unref (devices); } /** @@ -534,10 +552,6 @@ out: g_object_unref (device); if (profile != NULL) g_object_unref (profile); - if (tuple != NULL) - g_variant_unref (tuple); - if (value != NULL) - g_variant_unref (value); return; } diff --git a/src/cd-profile.c b/src/cd-profile.c index 276d466..1f98b4b 100644 --- a/src/cd-profile.c +++ b/src/cd-profile.c @@ -114,13 +114,36 @@ cd_profile_get_filename (CdProfile *profile) } /** - * cd_profile_dbus_emit_changed: + * cd_profile_dbus_emit_property_changed: **/ static void -cd_profile_dbus_emit_changed (CdProfile *profile) +cd_profile_dbus_emit_property_changed (CdProfile *profile, + const gchar *property_name, + GVariant *property_value) { gboolean ret; - GError *error = NULL; + GError *error_local = NULL; + GVariantBuilder builder; + GVariantBuilder invalidated_builder; + + /* build the dict */ + g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as")); + g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); + g_variant_builder_add (&builder, + "{sv}", + property_name, + property_value); + g_dbus_connection_emit_signal (profile->priv->connection, + NULL, + profile->priv->object_path, + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + g_variant_new ("(sa{sv}as)", + COLORD_DBUS_INTERFACE_PROFILE, + &builder, + &invalidated_builder), + &error_local); + g_assert_no_error (error_local); /* emit signal */ ret = g_dbus_connection_emit_signal (profile->priv->connection, @@ -129,10 +152,10 @@ cd_profile_dbus_emit_changed (CdProfile *profile) COLORD_DBUS_INTERFACE_PROFILE, "Changed", NULL, - &error); + &error_local); if (!ret) { - g_warning ("failed to send signal %s", error->message); - g_error_free (error); + g_warning ("failed to send signal %s", error_local->message); + g_error_free (error_local); } } @@ -165,6 +188,8 @@ cd_profile_dbus_method_call (GDBusConnection *connection_, const gchar *sender, g_variant_get (parameters, "(ss)", &property_name, &property_value); + g_debug ("Attempting to set %s to %s", + property_name, property_value); if (g_strcmp0 (property_name, "Filename") == 0) { ret = cd_profile_set_filename (profile, property_value, &error); if (!ret) { @@ -173,13 +198,20 @@ cd_profile_dbus_method_call (GDBusConnection *connection_, const gchar *sender, g_error_free (error); goto out; } - cd_profile_dbus_emit_changed (profile); + cd_profile_dbus_emit_property_changed (profile, + property_name, + g_variant_new_string (property_value)); + cd_profile_dbus_emit_property_changed (profile, + "Title", + g_variant_new_string (profile->priv->title)); g_dbus_method_invocation_return_value (invocation, NULL); goto out; } if (g_strcmp0 (property_name, "Qualifier") == 0) { cd_profile_set_qualifier (profile, property_value); - cd_profile_dbus_emit_changed (profile); + cd_profile_dbus_emit_property_changed (profile, + property_name, + g_variant_new_string (property_value)); g_dbus_method_invocation_return_value (invocation, NULL); goto out; } diff --git a/src/org.freedesktop.ColorManager.Device.xml b/src/org.freedesktop.ColorManager.Device.xml index ca52c00..745ff53 100644 --- a/src/org.freedesktop.ColorManager.Device.xml +++ b/src/org.freedesktop.ColorManager.Device.xml @@ -68,7 +68,6 @@ </doc:doc> </property> - <!--***********************************************************--> <method name='SetProperty'> <annotation name='org.freedesktop.DBus.GLib.Async' value=''/> @@ -141,7 +140,7 @@ </doc:para> </doc:description> </doc:doc> - <arg type='o' name='profile_id' direction='in'> + <arg type='o' name='object_path' direction='in'> <doc:doc> <doc:summary> <doc:para> diff --git a/src/org.freedesktop.ColorManager.xml b/src/org.freedesktop.ColorManager.xml index 4370154..054862e 100644 --- a/src/org.freedesktop.ColorManager.xml +++ b/src/org.freedesktop.ColorManager.xml @@ -24,48 +24,6 @@ <!--***********************************************************--> <!-- - <method name='GetProfilesForType'> - <annotation name='org.freedesktop.DBus.GLib.Async' value=''/> - <doc:doc> - <doc:description> - <doc:para> - Gets the profiles for a device type. - </doc:para> - </doc:description> - </doc:doc> - <arg type='s' name='type' direction='in'> - <doc:doc> - <doc:summary> - <doc:para> - A device type, e.g. <doc:tt>scanner</doc:tt>, <doc:tt>display</doc:tt>, - <doc:tt>printer</doc:tt> or <doc:tt>camera</doc:tt>. - </doc:para> - </doc:summary> - </doc:doc> - </arg> - <arg type='s' name='options' direction='in'> - <doc:doc> - <doc:summary> - <doc:para> - Options to give hints about what profiles to choose. Currently unused. - </doc:para> - </doc:summary> - </doc:doc> - </arg> - <arg type='ao' name='profiles' direction='out'> - <doc:doc> - <doc:summary> - <doc:para> - An array of profile paths to use with this type of device. - </doc:para> - </doc:summary> - </doc:doc> - </arg> - </method> ---> - - <!--***********************************************************--> -<!-- <method name='GetProfilesForFile'> <annotation name='org.freedesktop.DBus.GLib.Async' value=''/> <doc:doc> @@ -84,15 +42,6 @@ </doc:summary> </doc:doc> </arg> - <arg type='s' name='options' direction='in'> - <doc:doc> - <doc:summary> - <doc:para> - Options to give hints about what profiles to choose. Currently unused. - </doc:para> - </doc:summary> - </doc:doc> - </arg> <arg type='ao' name='profiles' direction='out'> <doc:doc> <doc:summary> |