diff --git a/src/backends/meta-color-device.c b/src/backends/meta-color-device.c index e86d96ef8..8ec1571c4 100644 --- a/src/backends/meta-color-device.c +++ b/src/backends/meta-color-device.c @@ -62,6 +62,10 @@ struct _MetaColorDevice MetaColorProfile *device_profile; gulong device_profile_ready_handler_id; + MetaColorProfile *assigned_profile; + gulong assigned_profile_ready_handler_id; + GCancellable *assigned_profile_cancellable; + GCancellable *cancellable; PendingState pending_state; @@ -121,6 +125,77 @@ out: return g_string_free (device_id, FALSE); } +static void +ensure_default_profile_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + MetaColorStore *color_store = META_COLOR_STORE (source_object); + MetaColorDevice *color_device; + g_autoptr (MetaColorProfile) color_profile = NULL; + g_autoptr (GError) error = NULL; + + color_profile = meta_color_store_ensure_colord_profile_finish (color_store, + res, + &error); + if (!color_profile) + { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + g_warning ("Failed to create color profile from colord profile: %s", + error->message); + } + + color_device = META_COLOR_DEVICE (user_data); + g_set_object (&color_device->assigned_profile, color_profile); +} + +static void +update_assigned_profile (MetaColorDevice *color_device) +{ + MetaColorManager *color_manager = color_device->color_manager; + MetaColorStore *color_store = + meta_color_manager_get_color_store (color_manager); + CdProfile *default_profile; + GCancellable *cancellable; + + default_profile = cd_device_get_default_profile (color_device->cd_device); + + if (color_device->assigned_profile && + meta_color_profile_get_cd_profile (color_device->assigned_profile) == + default_profile) + return; + + if (color_device->assigned_profile_cancellable) + { + g_cancellable_cancel (color_device->assigned_profile_cancellable); + g_clear_object (&color_device->assigned_profile_cancellable); + } + + if (!default_profile) + { + g_clear_object (&color_device->assigned_profile); + return; + } + + cancellable = g_cancellable_new (); + color_device->assigned_profile_cancellable = cancellable; + + meta_color_store_ensure_colord_profile (color_store, + default_profile, + cancellable, + ensure_default_profile_cb, + color_device); +} + +static void +on_cd_device_changed (CdDevice *cd_device, + MetaColorDevice *color_device) +{ + update_assigned_profile (color_device); +} + typedef struct { GMainLoop *loop; @@ -180,11 +255,18 @@ meta_color_device_dispose (GObject *object) meta_topic (META_DEBUG_COLOR, "Removing color device '%s'", color_device->cd_device_id); + if (color_device->assigned_profile_cancellable) + { + g_cancellable_cancel (color_device->assigned_profile_cancellable); + g_clear_object (&color_device->assigned_profile_cancellable); + } + g_cancellable_cancel (color_device->cancellable); g_clear_object (&color_device->cancellable); g_clear_signal_handler (&color_device->device_profile_ready_handler_id, color_device->device_profile); + g_clear_object (&color_device->assigned_profile); g_clear_object (&color_device->device_profile); cd_device = color_device->cd_device; @@ -284,6 +366,10 @@ on_cd_device_connected (GObject *source_object, color_device->pending_state &= ~PENDING_CONNECTED; + g_signal_connect (cd_device, "changed", + G_CALLBACK (on_cd_device_changed), color_device); + update_assigned_profile (color_device); + maybe_finish_setup (color_device); } @@ -981,3 +1067,9 @@ meta_color_device_is_ready (MetaColorDevice *color_device) { return color_device->is_ready; } + +MetaColorProfile * +meta_color_device_get_assigned_profile (MetaColorDevice *color_device) +{ + return color_device->assigned_profile; +} diff --git a/src/backends/meta-color-device.h b/src/backends/meta-color-device.h index 6022fc0a8..6f03750ff 100644 --- a/src/backends/meta-color-device.h +++ b/src/backends/meta-color-device.h @@ -37,6 +37,7 @@ void meta_color_device_destroy (MetaColorDevice *color_device); void meta_color_device_update_monitor (MetaColorDevice *color_device, MetaMonitor *monitor); +META_EXPORT_TEST const char * meta_color_device_get_id (MetaColorDevice *color_device); META_EXPORT_TEST @@ -45,6 +46,9 @@ MetaMonitor * meta_color_device_get_monitor (MetaColorDevice *color_device); META_EXPORT_TEST MetaColorProfile * meta_color_device_get_device_profile (MetaColorDevice *color_device); +META_EXPORT_TEST +MetaColorProfile * meta_color_device_get_assigned_profile (MetaColorDevice *color_device); + void meta_color_device_generate_profile (MetaColorDevice *color_device, const char *file_path, GCancellable *cancellable, diff --git a/src/backends/meta-color-profile.c b/src/backends/meta-color-profile.c index cfd038d84..201d1c57b 100644 --- a/src/backends/meta-color-profile.c +++ b/src/backends/meta-color-profile.c @@ -46,8 +46,10 @@ struct _MetaColorProfile GBytes *bytes; char *cd_profile_id; + gboolean is_owner; CdProfile *cd_profile; GCancellable *cancellable; + guint notify_ready_id; gboolean is_ready; }; @@ -109,30 +111,35 @@ meta_color_profile_finalize (GObject *object) MetaColorProfile *color_profile = META_COLOR_PROFILE (object); MetaColorManager *color_manager = color_profile->color_manager; CdClient *cd_client = meta_color_manager_get_cd_client (color_manager); - CdProfile *cd_profile; g_cancellable_cancel (color_profile->cancellable); g_clear_object (&color_profile->cancellable); + g_clear_handle_id (&color_profile->notify_ready_id, g_source_remove); - cd_profile = color_profile->cd_profile; - if (!cd_profile) + if (color_profile->is_owner) { - g_autoptr (GError) error = NULL; + CdProfile *cd_profile; - cd_profile = find_profile_sync (cd_client, - color_profile->cd_profile_id, - &error); - if (!cd_profile && - !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) + cd_profile = color_profile->cd_profile; + if (!cd_profile) { - g_warning ("Failed to find colord profile %s: %s", - color_profile->cd_profile_id, - error->message); - } - } + g_autoptr (GError) error = NULL; - if (cd_profile) - cd_client_delete_profile (cd_client, cd_profile, NULL, NULL, NULL); + cd_profile = find_profile_sync (cd_client, + color_profile->cd_profile_id, + &error); + if (!cd_profile && + !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) + { + g_warning ("Failed to find colord profile %s: %s", + color_profile->cd_profile_id, + error->message); + } + } + + if (cd_profile) + cd_client_delete_profile (cd_client, cd_profile, NULL, NULL, NULL); + } g_clear_pointer (&color_profile->cd_profile_id, g_free); g_clear_object (&color_profile->cd_icc); @@ -270,6 +277,7 @@ meta_color_profile_new_from_icc (MetaColorManager *color_manager, color_profile->cd_icc = cd_icc; color_profile->bytes = raw_bytes; color_profile->cancellable = g_cancellable_new (); + color_profile->is_owner = TRUE; color_profile->cd_profile_id = g_strdup_printf ("icc-%s", checksum); @@ -278,6 +286,45 @@ meta_color_profile_new_from_icc (MetaColorManager *color_manager, return color_profile; } +static gboolean +notify_ready_idle (gpointer user_data) +{ + MetaColorProfile *color_profile = user_data; + + color_profile->notify_ready_id = 0; + color_profile->is_ready = TRUE; + g_signal_emit (color_profile, signals[READY], 0); + + return G_SOURCE_REMOVE; +} + +MetaColorProfile * +meta_color_profile_new_from_cd_profile (MetaColorManager *color_manager, + CdProfile *cd_profile, + CdIcc *cd_icc, + GBytes *raw_bytes) +{ + MetaColorProfile *color_profile; + const char *checksum; + + color_profile = g_object_new (META_TYPE_COLOR_PROFILE, NULL); + color_profile->color_manager = color_manager; + color_profile->cd_icc = cd_icc; + color_profile->bytes = raw_bytes; + color_profile->cancellable = g_cancellable_new (); + color_profile->is_owner = FALSE; + + checksum = cd_icc_get_metadata_item (cd_icc, + CD_PROFILE_METADATA_FILE_CHECKSUM); + color_profile->cd_profile_id = g_strdup_printf ("icc-%s", checksum); + color_profile->cd_profile = g_object_ref (cd_profile); + + color_profile->notify_ready_id = g_idle_add (notify_ready_idle, + color_profile); + + return color_profile; +} + gboolean meta_color_profile_equals_bytes (MetaColorProfile *color_profile, GBytes *bytes) @@ -303,8 +350,20 @@ meta_color_profile_get_cd_icc (MetaColorProfile *color_profile) return color_profile->cd_icc; } +CdProfile * +meta_color_profile_get_cd_profile (MetaColorProfile *color_profile) +{ + return color_profile->cd_profile; +} + gboolean meta_color_profile_is_ready (MetaColorProfile *color_profile) { return color_profile->is_ready; } + +const char * +meta_color_profile_get_id (MetaColorProfile *color_profile) +{ + return color_profile->cd_profile_id; +} diff --git a/src/backends/meta-color-profile.h b/src/backends/meta-color-profile.h index 6a80c6452..036786032 100644 --- a/src/backends/meta-color-profile.h +++ b/src/backends/meta-color-profile.h @@ -34,6 +34,11 @@ MetaColorProfile * meta_color_profile_new_from_icc (MetaColorManager *color_mana CdIcc *icc, GBytes *raw_bytes); +MetaColorProfile * meta_color_profile_new_from_cd_profile (MetaColorManager *color_manager, + CdProfile *cd_profile, + CdIcc *cd_icc, + GBytes *raw_bytes); + gboolean meta_color_profile_equals_bytes (MetaColorProfile *color_profile, GBytes *bytes); @@ -44,6 +49,11 @@ size_t meta_color_profile_get_data_size (MetaColorProfile *color_profile); META_EXPORT_TEST CdIcc * meta_color_profile_get_cd_icc (MetaColorProfile *color_profile); +CdProfile * meta_color_profile_get_cd_profile (MetaColorProfile *color_profile); + gboolean meta_color_profile_is_ready (MetaColorProfile *color_profile); +META_EXPORT_TEST +const char * meta_color_profile_get_id (MetaColorProfile *color_profile); + #endif /* META_COLOR_PROFILE_H */ diff --git a/src/backends/meta-color-store.c b/src/backends/meta-color-store.c index 860d81a89..d26789017 100644 --- a/src/backends/meta-color-store.c +++ b/src/backends/meta-color-store.c @@ -54,6 +54,7 @@ meta_color_store_finalize (GObject *object) { MetaColorStore *color_store = META_COLOR_STORE (object); + g_clear_pointer (&color_store->profiles, g_hash_table_unref); g_clear_pointer (&color_store->device_profiles, g_hash_table_unref); g_clear_pointer (&color_store->pending_device_profiles, g_hash_table_unref); @@ -80,6 +81,8 @@ meta_color_store_new (MetaColorManager *color_manager) color_store = g_object_new (META_TYPE_COLOR_STORE, NULL); color_store->color_manager = color_manager; + color_store->profiles = + g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); color_store->device_profiles = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); color_store->pending_device_profiles = @@ -205,5 +208,180 @@ meta_color_store_ensure_device_profile_finish (MetaColorStore *color_store, g_hash_table_insert (color_store->device_profiles, g_steal_pointer (&data->key), g_object_ref (color_profile)); + g_hash_table_insert (color_store->profiles, + g_strdup (meta_color_profile_get_id (color_profile)), + g_object_ref (color_profile)); return color_profile; } + +typedef struct +{ + MetaColorStore *color_store; + CdProfile *cd_profile; + + MetaColorProfile *created_profile; +} EnsureColordProfileData; + +static void +ensure_colord_profile_data_free (EnsureColordProfileData *data) +{ + g_clear_object (&data->cd_profile); + g_free (data); +} + +static void +on_cd_profile_contents_loaded (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GFile *file = G_FILE (source_object); + g_autoptr (GTask) task = G_TASK (user_data); + EnsureColordProfileData *data = g_task_get_task_data (task); + MetaColorStore *color_store = data->color_store; + MetaColorManager *color_manager = color_store->color_manager; + CdProfile *cd_profile = data->cd_profile; + g_autoptr (GError) error = NULL; + g_autofree char *contents = NULL; + size_t length; + g_autoptr (CdIcc) cd_icc = NULL; + g_autofree char *file_md5_checksum = NULL; + GBytes *bytes; + MetaColorProfile *color_profile; + + if (!g_file_load_contents_finish (file, res, + &contents, + &length, + NULL, + &error)) + { + g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + cd_icc = cd_icc_new (); + if (!cd_icc_load_data (cd_icc, + (uint8_t *) contents, + length, + CD_ICC_LOAD_FLAGS_METADATA, + &error)) + { + g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + cd_icc_add_metadata (cd_icc, CD_PROFILE_PROPERTY_FILENAME, + g_file_peek_path (file)); + + file_md5_checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5, + (uint8_t *) contents, + length); + cd_icc_add_metadata (cd_icc, CD_PROFILE_METADATA_FILE_CHECKSUM, + file_md5_checksum); + + bytes = g_bytes_new_take (g_steal_pointer (&contents), length); + color_profile = + meta_color_profile_new_from_cd_profile (color_manager, + cd_profile, + g_steal_pointer (&cd_icc), + bytes); + + g_hash_table_insert (color_store->profiles, + g_strdup (meta_color_profile_get_id (color_profile)), + color_profile); + + meta_topic (META_DEBUG_COLOR, "Created colord profile '%s' from '%s'", + cd_profile_get_id (cd_profile), + cd_profile_get_filename (cd_profile)); + + g_task_return_pointer (task, g_object_ref (color_profile), g_object_unref); +} + +static void +on_cd_profile_connected (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + CdProfile *cd_profile = CD_PROFILE (source_object); + g_autoptr (GTask) task = G_TASK (user_data); + EnsureColordProfileData *data = g_task_get_task_data (task); + MetaColorStore *color_store = data->color_store; + g_autoptr (GError) error = NULL; + const char *file_path; + g_autoptr (GFile) file = NULL; + MetaColorProfile *color_profile; + GCancellable *cancellable; + + if (!cd_profile_connect_finish (cd_profile, res, &error)) + { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + color_profile = g_hash_table_lookup (color_store->profiles, + cd_profile_get_id (cd_profile)); + if (color_profile) + { + meta_topic (META_DEBUG_COLOR, "Found existing colord profile '%s'", + cd_profile_get_id (cd_profile)); + g_task_return_pointer (task, + g_object_ref (color_profile), + g_object_unref); + return; + } + + file_path = cd_profile_get_filename (cd_profile); + if (!file_path) + { + g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, + "Tried to assign non-local profile"); + return; + } + + file = g_file_new_for_path (file_path); + cancellable = g_task_get_cancellable (task); + g_file_load_contents_async (file, + cancellable, + on_cd_profile_contents_loaded, + g_steal_pointer (&task)); +} + +void +meta_color_store_ensure_colord_profile (MetaColorStore *color_store, + CdProfile *cd_profile, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + EnsureColordProfileData *data; + + task = g_task_new (G_OBJECT (color_store), cancellable, callback, user_data); + g_task_set_source_tag (task, meta_color_store_ensure_colord_profile); + + data = g_new0 (EnsureColordProfileData, 1); + data->color_store = color_store; + data->cd_profile = g_object_ref (cd_profile); + g_task_set_task_data (task, data, + (GDestroyNotify) ensure_colord_profile_data_free); + + cd_profile_connect (cd_profile, + cancellable, + on_cd_profile_connected, + task); +} + +MetaColorProfile * +meta_color_store_ensure_colord_profile_finish (MetaColorStore *color_store, + GAsyncResult *res, + GError **error) +{ + GTask *task = G_TASK (res); + + g_assert (g_task_get_source_tag (task) == + meta_color_store_ensure_colord_profile); + + return g_task_propagate_pointer (G_TASK (res), error); +} diff --git a/src/backends/meta-color-store.h b/src/backends/meta-color-store.h index 74bac9688..5634dae76 100644 --- a/src/backends/meta-color-store.h +++ b/src/backends/meta-color-store.h @@ -18,6 +18,7 @@ #ifndef META_COLOR_STORE_H #define META_COLOR_STORE_H +#include #include #include @@ -40,4 +41,14 @@ MetaColorProfile * meta_color_store_ensure_device_profile_finish (MetaColorStore GAsyncResult *res, GError **error); +void meta_color_store_ensure_colord_profile (MetaColorStore *color_store, + CdProfile *cd_profile, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +MetaColorProfile * meta_color_store_ensure_colord_profile_finish (MetaColorStore *color_store, + GAsyncResult *res, + GError **error); + #endif /* META_COLOR_STORE_H */ diff --git a/src/tests/color-management-tests.c b/src/tests/color-management-tests.c index 7fefd3314..754326faf 100644 --- a/src/tests/color-management-tests.c +++ b/src/tests/color-management-tests.c @@ -28,6 +28,9 @@ static MetaContext *test_context; +/* Profile ID is 'icc-$(md5sum sRGB.icc)' */ +#define SRGB_ICC_PROFILE_ID "icc-112034c661b5e0c91c51f109684612a0"; + #define PRIMARY_EPSILON 0.000015 static MonitorTestCaseSetup base_monitor_setup = { @@ -101,6 +104,82 @@ static MonitorTestCaseSetup base_monitor_setup = { .white_y = 0.329102, \ }) +static GDBusProxy * +get_colord_mock_proxy (void) +{ + GDBusProxy *proxy; + g_autoptr (GError) error = NULL; + g_autoptr (GVariant) ret = NULL; + + proxy = + g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START | + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + NULL, + "org.freedesktop.ColorManager", + "/org/freedesktop/ColorManager", + "org.freedesktop.DBus.Mock", + NULL, &error); + if (!proxy) + { + g_error ("Failed to find mocked color manager system service, %s", + error->message); + } + + return proxy; +} + +static void +set_colord_device_profiles (const char *cd_device_id, + const char **cd_profile_ids, + int n_cd_profile_ids) +{ + GDBusProxy *proxy; + g_autoptr (GError) error = NULL; + GVariantBuilder params_builder; + GVariantBuilder profiles_builder; + int i; + + proxy = get_colord_mock_proxy (); + + g_variant_builder_init (¶ms_builder, G_VARIANT_TYPE ("(sas)")); + g_variant_builder_add (¶ms_builder, "s", cd_device_id); + + g_variant_builder_init (&profiles_builder, G_VARIANT_TYPE ("as")); + for (i = 0; i < n_cd_profile_ids; i++) + g_variant_builder_add (&profiles_builder, "s", cd_profile_ids[i]); + g_variant_builder_add (¶ms_builder, "as", &profiles_builder); + + if (!g_dbus_proxy_call_sync (proxy, + "SetDeviceProfiles", + g_variant_builder_end (¶ms_builder), + G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, + &error)) + g_error ("Failed to set device profile: %s", error->message); +} + +static void +add_colord_system_profile (const char *cd_profile_id, + const char *file_path) +{ + GDBusProxy *proxy; + g_autoptr (GError) error = NULL; + GVariantBuilder params_builder; + + proxy = get_colord_mock_proxy (); + + g_variant_builder_init (¶ms_builder, G_VARIANT_TYPE ("(ss)")); + g_variant_builder_add (¶ms_builder, "s", cd_profile_id); + g_variant_builder_add (¶ms_builder, "s", file_path); + + if (!g_dbus_proxy_call_sync (proxy, + "AddSystemProfile", + g_variant_builder_end (¶ms_builder), + G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, + &error)) + g_error ("Failed to add system profile: %s", error->message); +} + static void meta_test_color_management_device_basic (void) { @@ -269,6 +348,63 @@ meta_test_color_management_profile_device (void) g_assert_cmpfloat_with_epsilon (white->Z, 1.10479736, PRIMARY_EPSILON); } +static void +meta_test_color_management_profile_system (void) +{ + MetaBackend *backend = meta_context_get_backend (test_context); + MetaMonitorManager *monitor_manager = + meta_backend_get_monitor_manager (backend); + MetaMonitorManagerTest *monitor_manager_test = + META_MONITOR_MANAGER_TEST (monitor_manager); + MetaColorManager *color_manager = + meta_backend_get_color_manager (backend); + MetaEdidInfo edid_info; + MonitorTestCaseSetup test_case_setup = base_monitor_setup; + MetaMonitorTestSetup *test_setup; + MetaMonitor *monitor; + MetaColorDevice *color_device; + const char *path; + const char *color_profiles[1]; + MetaColorProfile *color_profile; + const char *srgb_profile_id = SRGB_ICC_PROFILE_ID; + + edid_info = CALTECH_MONITOR_EDID; + test_case_setup.outputs[0].edid_info = edid_info; + test_case_setup.outputs[0].has_edid_info = TRUE; + test_setup = meta_create_monitor_test_setup (backend, &test_case_setup, + MONITOR_TEST_FLAG_NO_STORED); + meta_monitor_manager_test_emulate_hotplug (monitor_manager_test, test_setup); + + monitor = meta_monitor_manager_get_monitors (monitor_manager)->data; + color_device = meta_color_manager_get_color_device (color_manager, monitor); + g_assert_nonnull (color_device); + + while (!meta_color_device_is_ready (color_device)) + g_main_context_iteration (NULL, TRUE); + + g_assert_null (meta_color_device_get_assigned_profile (color_device)); + + path = g_test_get_filename (G_TEST_DIST, "tests", "icc-profiles", "sRGB.icc", + NULL); + add_colord_system_profile (srgb_profile_id, path); + color_profiles[0] = srgb_profile_id; + set_colord_device_profiles (meta_color_device_get_id (color_device), + color_profiles, G_N_ELEMENTS (color_profiles)); + + while (TRUE) + { + color_profile = meta_color_device_get_assigned_profile (color_device); + if (color_profile) + break; + + g_main_context_iteration (NULL, TRUE); + } + + g_assert_cmpstr (meta_color_profile_get_id (color_profile), + ==, + srgb_profile_id); +} + static MetaMonitorTestSetup * create_stage_view_test_setup (MetaBackend *backend) { @@ -296,18 +432,28 @@ init_tests (void) meta_test_color_management_device_basic); g_test_add_func ("/color-management/profile/device", meta_test_color_management_profile_device); + g_test_add_func ("/color-management/profile/system", + meta_test_color_management_profile_system); } int main (int argc, char **argv) { g_autoptr (MetaContext) context = NULL; + char *path; context = meta_create_test_context (META_CONTEXT_TEST_TYPE_NESTED, META_CONTEXT_TEST_FLAG_NONE); g_assert (meta_context_configure (context, &argc, &argv, NULL)); + path = g_test_build_filename (G_TEST_BUILT, + "tests", + "share", + NULL); + g_setenv ("XDG_DATA_HOME", path, TRUE); + g_free (path); + test_context = context; init_tests (); diff --git a/src/tests/dbusmock-templates/colord.py b/src/tests/dbusmock-templates/colord.py index d1912af44..f51d06579 100644 --- a/src/tests/dbusmock-templates/colord.py +++ b/src/tests/dbusmock-templates/colord.py @@ -13,7 +13,7 @@ __copyright__ = '(c) 2021 Red Hat Inc.' import dbus import os import pwd -from dbusmock import MOCK_IFACE +from dbusmock import MOCK_IFACE, mockobject BUS_PREFIX = 'org.freedesktop.ColorManager' @@ -65,7 +65,9 @@ def CreateDevice(self, device_id, scope, props): DEVICE_IFACE, { 'DeviceId': device_id, + 'Profiles': dbus.types.Array(signature='o'), 'Enabled': True, + 'ProfilingInhibitors': dbus.types.Array(signature='s'), }, []) self.EmitSignal(MAIN_IFACE, 'DeviceAdded', 'o', [device_path]) @@ -119,3 +121,32 @@ def Reset(self): for profile_path in self.profiles.values(): self.RemoveObject(profile_path) self.profiles = {} + +@dbus.service.method(MOCK_IFACE, in_signature='ss') +def AddSystemProfile(self, profile_id, file_path): + uid = os.getuid() + username = get_username(uid) + profile_path = PATH_PREFIX + '/profiles/' + \ + escape_unit_name(profile_id) + \ + '_' + username + '_' + str(uid) + self.profiles[profile_id] = profile_path + self.AddObject(profile_path, + PROFILE_IFACE, + { + 'ProfileId': profile_id, + 'Filename': file_path, + 'Enabled': True, + }, + []) + self.EmitSignal(MAIN_IFACE, 'ProfileAdded', 'o', [profile_path]) + +@dbus.service.method(MOCK_IFACE, in_signature='sas') +def SetDeviceProfiles(self, device_id, profile_ids): + device_path = self.devices[device_id] + device = mockobject.objects[device_path] + profile_paths = [ + dbus.types.ObjectPath(self.profiles[profile_id]) + for profile_id in profile_ids + ] + device.UpdateProperties(DEVICE_IFACE, {'Profiles': dbus.types.Array(profile_paths)}) + device.EmitSignal(DEVICE_IFACE, 'Changed', '', []) diff --git a/src/tests/icc-profiles/sRGB.icc b/src/tests/icc-profiles/sRGB.icc new file mode 100644 index 000000000..9844b8c33 Binary files /dev/null and b/src/tests/icc-profiles/sRGB.icc differ