mirror of
https://github.com/brl/mutter.git
synced 2024-11-23 00:20:42 -05:00
color-profile: Create colord profiles
This works similiarly to how MetaColorDevice works, by creating them asynchronously then signalling the 'ready' signal when done. Also similarly to MetaColorDevice, the on-demand sync cleanup on finalize is added, to avoid race conditions when hotplugs happens very rapidly, e.g. in tests. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2164>
This commit is contained in:
parent
60d0394468
commit
cc84a45b56
@ -45,7 +45,8 @@ static guint signals[N_SIGNALS];
|
|||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
PENDING_EDID_PROFILE = 1 << 0,
|
PENDING_EDID_PROFILE = 1 << 0,
|
||||||
PENDING_CONNECTED = 1 << 1,
|
PENDING_PROFILE_READY = 1 << 1,
|
||||||
|
PENDING_CONNECTED = 1 << 2,
|
||||||
} PendingState;
|
} PendingState;
|
||||||
|
|
||||||
struct _MetaColorDevice
|
struct _MetaColorDevice
|
||||||
@ -59,6 +60,7 @@ struct _MetaColorDevice
|
|||||||
CdDevice *cd_device;
|
CdDevice *cd_device;
|
||||||
|
|
||||||
MetaColorProfile *device_profile;
|
MetaColorProfile *device_profile;
|
||||||
|
gulong device_profile_ready_handler_id;
|
||||||
|
|
||||||
GCancellable *cancellable;
|
GCancellable *cancellable;
|
||||||
|
|
||||||
@ -180,6 +182,8 @@ meta_color_device_dispose (GObject *object)
|
|||||||
|
|
||||||
g_cancellable_cancel (color_device->cancellable);
|
g_cancellable_cancel (color_device->cancellable);
|
||||||
g_clear_object (&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->device_profile);
|
g_clear_object (&color_device->device_profile);
|
||||||
|
|
||||||
@ -283,6 +287,14 @@ on_cd_device_connected (GObject *source_object,
|
|||||||
maybe_finish_setup (color_device);
|
maybe_finish_setup (color_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_profile_ready (MetaColorProfile *color_profile,
|
||||||
|
MetaColorDevice *color_device)
|
||||||
|
{
|
||||||
|
color_device->pending_state &= ~PENDING_PROFILE_READY;
|
||||||
|
maybe_finish_setup (color_device);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ensure_device_profile_cb (GObject *source_object,
|
ensure_device_profile_cb (GObject *source_object,
|
||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
@ -314,7 +326,18 @@ ensure_device_profile_cb (GObject *source_object,
|
|||||||
color_device->pending_state &= ~PENDING_EDID_PROFILE;
|
color_device->pending_state &= ~PENDING_EDID_PROFILE;
|
||||||
g_set_object (&color_device->device_profile, color_profile);
|
g_set_object (&color_device->device_profile, color_profile);
|
||||||
|
|
||||||
maybe_finish_setup (color_device);
|
if (!meta_color_profile_is_ready (color_profile))
|
||||||
|
{
|
||||||
|
color_device->device_profile_ready_handler_id =
|
||||||
|
g_signal_connect (color_profile, "ready",
|
||||||
|
G_CALLBACK (on_profile_ready),
|
||||||
|
color_device);
|
||||||
|
color_device->pending_state |= PENDING_PROFILE_READY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
maybe_finish_setup (color_device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -863,6 +886,7 @@ on_efi_panel_color_info_loaded (GObject *source_object,
|
|||||||
/* Set metadata needed by colord */
|
/* Set metadata needed by colord */
|
||||||
cd_icc_add_metadata (cd_icc, CD_PROFILE_PROPERTY_FILENAME,
|
cd_icc_add_metadata (cd_icc, CD_PROFILE_PROPERTY_FILENAME,
|
||||||
file_path);
|
file_path);
|
||||||
|
|
||||||
file_md5_checksum = g_compute_checksum_for_bytes (G_CHECKSUM_MD5,
|
file_md5_checksum = g_compute_checksum_for_bytes (G_CHECKSUM_MD5,
|
||||||
bytes);
|
bytes);
|
||||||
cd_icc_add_metadata (cd_icc, CD_PROFILE_METADATA_FILE_CHECKSUM,
|
cd_icc_add_metadata (cd_icc, CD_PROFILE_METADATA_FILE_CHECKSUM,
|
||||||
|
@ -25,6 +25,17 @@
|
|||||||
#include <colord.h>
|
#include <colord.h>
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
#include "backends/meta-color-manager-private.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
READY,
|
||||||
|
|
||||||
|
N_SIGNALS
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals[N_SIGNALS];
|
||||||
|
|
||||||
struct _MetaColorProfile
|
struct _MetaColorProfile
|
||||||
{
|
{
|
||||||
GObject parent;
|
GObject parent;
|
||||||
@ -33,18 +44,100 @@ struct _MetaColorProfile
|
|||||||
|
|
||||||
CdIcc *cd_icc;
|
CdIcc *cd_icc;
|
||||||
GBytes *bytes;
|
GBytes *bytes;
|
||||||
|
|
||||||
|
char *cd_profile_id;
|
||||||
|
CdProfile *cd_profile;
|
||||||
|
GCancellable *cancellable;
|
||||||
|
|
||||||
|
gboolean is_ready;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (MetaColorProfile, meta_color_profile,
|
G_DEFINE_TYPE (MetaColorProfile, meta_color_profile,
|
||||||
G_TYPE_OBJECT)
|
G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GMainLoop *loop;
|
||||||
|
CdProfile *cd_profile;
|
||||||
|
GError *error;
|
||||||
|
} FindProfileData;
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_find_profile (GObject *source_object,
|
||||||
|
GAsyncResult *res,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
CdClient *cd_client = CD_CLIENT (source_object);
|
||||||
|
FindProfileData *data = user_data;
|
||||||
|
|
||||||
|
data->cd_profile = cd_client_find_profile_finish (cd_client, res,
|
||||||
|
&data->error);
|
||||||
|
g_main_loop_quit (data->loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
static CdProfile *
|
||||||
|
find_profile_sync (CdClient *cd_client,
|
||||||
|
const char *cd_profile_id,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_autoptr (GMainContext) main_context = NULL;
|
||||||
|
g_autoptr (GMainLoop) main_loop = NULL;
|
||||||
|
FindProfileData data = {};
|
||||||
|
|
||||||
|
main_context = g_main_context_new ();
|
||||||
|
main_loop = g_main_loop_new (main_context, FALSE);
|
||||||
|
g_main_context_push_thread_default (main_context);
|
||||||
|
|
||||||
|
data = (FindProfileData) {
|
||||||
|
.loop = main_loop,
|
||||||
|
};
|
||||||
|
cd_client_find_profile (cd_client, cd_profile_id, NULL,
|
||||||
|
on_find_profile,
|
||||||
|
&data);
|
||||||
|
g_main_loop_run (main_loop);
|
||||||
|
|
||||||
|
g_main_context_pop_thread_default (main_context);
|
||||||
|
|
||||||
|
if (data.error)
|
||||||
|
g_propagate_error (error, data.error);
|
||||||
|
return data.cd_profile;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_color_profile_finalize (GObject *object)
|
meta_color_profile_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
MetaColorProfile *color_profile = META_COLOR_PROFILE (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);
|
||||||
|
|
||||||
|
cd_profile = color_profile->cd_profile;
|
||||||
|
if (!cd_profile)
|
||||||
|
{
|
||||||
|
g_autoptr (GError) error = 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);
|
g_clear_object (&color_profile->cd_icc);
|
||||||
g_clear_pointer (&color_profile->bytes, g_bytes_unref);
|
g_clear_pointer (&color_profile->bytes, g_bytes_unref);
|
||||||
|
g_clear_object (&color_profile->cd_profile);
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_color_profile_parent_class)->finalize (object);
|
G_OBJECT_CLASS (meta_color_profile_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
@ -55,6 +148,13 @@ meta_color_profile_class_init (MetaColorProfileClass *klass)
|
|||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
object_class->finalize = meta_color_profile_finalize;
|
object_class->finalize = meta_color_profile_finalize;
|
||||||
|
|
||||||
|
signals[READY] =
|
||||||
|
g_signal_new ("ready",
|
||||||
|
G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST, 0,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -62,17 +162,118 @@ meta_color_profile_init (MetaColorProfile *color_profile)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_cd_profile_connected (GObject *source_object,
|
||||||
|
GAsyncResult *res,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
CdProfile *cd_profile = CD_PROFILE (source_object);
|
||||||
|
MetaColorProfile *color_profile = user_data;
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
|
||||||
|
if (!cd_profile_connect_finish (cd_profile, res, &error))
|
||||||
|
{
|
||||||
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_warning ("Failed to connect to colord profile %s: %s",
|
||||||
|
color_profile->cd_profile_id,
|
||||||
|
error->message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_warn_if_fail (g_strcmp0 (cd_profile_get_id (cd_profile),
|
||||||
|
color_profile->cd_profile_id) == 0);
|
||||||
|
|
||||||
|
meta_topic (META_DEBUG_COLOR, "Color profile '%s' connected",
|
||||||
|
color_profile->cd_profile_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
color_profile->is_ready = TRUE;
|
||||||
|
g_signal_emit (color_profile, signals[READY], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_cd_profile_created (GObject *source_object,
|
||||||
|
GAsyncResult *res,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
CdClient *cd_client = CD_CLIENT (source_object);
|
||||||
|
MetaColorProfile *color_profile = META_COLOR_PROFILE (user_data);
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
CdProfile *cd_profile;
|
||||||
|
|
||||||
|
cd_profile = cd_client_create_profile_finish (cd_client, res, &error);
|
||||||
|
if (!cd_profile)
|
||||||
|
{
|
||||||
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_warning ("Failed to create colord color profile: %s", error->message);
|
||||||
|
|
||||||
|
color_profile->is_ready = TRUE;
|
||||||
|
g_signal_emit (color_profile, signals[READY], 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_topic (META_DEBUG_COLOR, "Created colord color profile '%s'",
|
||||||
|
color_profile->cd_profile_id);
|
||||||
|
|
||||||
|
color_profile->cd_profile = cd_profile;
|
||||||
|
|
||||||
|
cd_profile_connect (cd_profile, color_profile->cancellable,
|
||||||
|
on_cd_profile_connected, color_profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
create_cd_profile (MetaColorProfile *color_profile,
|
||||||
|
const char *checksum)
|
||||||
|
{
|
||||||
|
MetaColorManager *color_manager = color_profile->color_manager;
|
||||||
|
CdClient *cd_client = meta_color_manager_get_cd_client (color_manager);
|
||||||
|
const char *filename;
|
||||||
|
g_autoptr (GHashTable) profile_props = NULL;
|
||||||
|
|
||||||
|
filename = cd_icc_get_metadata_item (color_profile->cd_icc,
|
||||||
|
CD_PROFILE_PROPERTY_FILENAME);
|
||||||
|
|
||||||
|
profile_props = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
|
NULL, NULL);
|
||||||
|
g_hash_table_insert (profile_props,
|
||||||
|
(gpointer) CD_PROFILE_PROPERTY_FILENAME,
|
||||||
|
(gpointer) filename);
|
||||||
|
g_hash_table_insert (profile_props,
|
||||||
|
(gpointer) CD_PROFILE_METADATA_FILE_CHECKSUM,
|
||||||
|
(gpointer) checksum);
|
||||||
|
cd_client_create_profile (cd_client,
|
||||||
|
color_profile->cd_profile_id,
|
||||||
|
CD_OBJECT_SCOPE_TEMP,
|
||||||
|
profile_props,
|
||||||
|
color_profile->cancellable,
|
||||||
|
on_cd_profile_created,
|
||||||
|
color_profile);
|
||||||
|
}
|
||||||
|
|
||||||
MetaColorProfile *
|
MetaColorProfile *
|
||||||
meta_color_profile_new_from_icc (MetaColorManager *color_manager,
|
meta_color_profile_new_from_icc (MetaColorManager *color_manager,
|
||||||
CdIcc *cd_icc,
|
CdIcc *cd_icc,
|
||||||
GBytes *raw_bytes)
|
GBytes *raw_bytes)
|
||||||
{
|
{
|
||||||
MetaColorProfile *color_profile;
|
MetaColorProfile *color_profile;
|
||||||
|
const char *checksum;
|
||||||
|
|
||||||
|
checksum = cd_icc_get_metadata_item (cd_icc,
|
||||||
|
CD_PROFILE_METADATA_FILE_CHECKSUM);
|
||||||
|
|
||||||
color_profile = g_object_new (META_TYPE_COLOR_PROFILE, NULL);
|
color_profile = g_object_new (META_TYPE_COLOR_PROFILE, NULL);
|
||||||
color_profile->color_manager = color_manager;
|
color_profile->color_manager = color_manager;
|
||||||
color_profile->cd_icc = cd_icc;
|
color_profile->cd_icc = cd_icc;
|
||||||
color_profile->bytes = raw_bytes;
|
color_profile->bytes = raw_bytes;
|
||||||
|
color_profile->cancellable = g_cancellable_new ();
|
||||||
|
|
||||||
|
color_profile->cd_profile_id = g_strdup_printf ("icc-%s", checksum);
|
||||||
|
|
||||||
|
create_cd_profile (color_profile, checksum);
|
||||||
|
|
||||||
return color_profile;
|
return color_profile;
|
||||||
}
|
}
|
||||||
@ -101,3 +302,9 @@ meta_color_profile_get_cd_icc (MetaColorProfile *color_profile)
|
|||||||
{
|
{
|
||||||
return color_profile->cd_icc;
|
return color_profile->cd_icc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
meta_color_profile_is_ready (MetaColorProfile *color_profile)
|
||||||
|
{
|
||||||
|
return color_profile->is_ready;
|
||||||
|
}
|
||||||
|
@ -44,4 +44,6 @@ size_t meta_color_profile_get_data_size (MetaColorProfile *color_profile);
|
|||||||
META_EXPORT_TEST
|
META_EXPORT_TEST
|
||||||
CdIcc * meta_color_profile_get_cd_icc (MetaColorProfile *color_profile);
|
CdIcc * meta_color_profile_get_cd_icc (MetaColorProfile *color_profile);
|
||||||
|
|
||||||
|
gboolean meta_color_profile_is_ready (MetaColorProfile *color_profile);
|
||||||
|
|
||||||
#endif /* META_COLOR_PROFILE_H */
|
#endif /* META_COLOR_PROFILE_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user