aboutsummaryrefslogtreecommitdiffstats
path: root/libcoopgamma_get_gamma_info_recv.c
blob: 763abf25988ee1a3385cfe9aa5deedea065decb7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/* See LICENSE file for copyright and license details. */
#include "common.h"


/**
 * Retrieve information about a CRTC:s gamma ramps, receive response part
 * 
 * @param   info   Output parameter for the information, must be initialised
 * @param   ctx    The state of the library, must be connected
 * @param   async  Information about the request
 * @return         Zero on success, -1 on error, in which case `ctx->error`
 *                 (rather than `errno`) is read for information about the error
 */
int
libcoopgamma_get_gamma_info_recv(libcoopgamma_crtc_info_t *restrict info, libcoopgamma_context_t *restrict ctx,
                                 libcoopgamma_async_context_t *restrict async)
{
	char temp[3 * sizeof(size_t) + 1];
	char *line;
	char *value;
	size_t _n;
	int have_cooperative = 0, have_gamma_support = 0, have_colourspace = 0;
	int have_depth       = 0, have_white_x = 0, have_white_y = 0;
	int have_red_size    = 0, have_red_x   = 0, have_red_y   = 0;
	int have_green_size  = 0, have_green_x = 0, have_green_y = 0;
	int have_blue_size   = 0, have_blue_x  = 0, have_blue_y  = 0;
	int bad = 0, r = 0, g = 0, b = 0, x = 0;
	size_t *outz;
	unsigned *outu;
	int *have;

	if (libcoopgamma_check_error__(ctx, async))
		return -1;

	info->cooperative = 0; /* Should be in the response, but ... */
	info->colourspace = LIBCOOPGAMMA_UNKNOWN;

	for (;;) {
		line = libcoopgamma_next_header__(ctx);
		value = &strchr(line, ':')[2U];
		if (!*line) {
			break;
		} else if (strstr(line, "Cooperative: ") == line) {
			have_cooperative = 1 + !!have_cooperative;
			if      (!strcmp(value, "yes")) info->cooperative = 1;
			else if (!strcmp(value, "no"))  info->cooperative = 0;
			else
				bad = 1;
		} else if (strstr(line, "Depth: ") == line) {
			have_depth = 1 + !!have_depth;
			if      (!strcmp(value, "8"))  info->depth = LIBCOOPGAMMA_UINT8;
			else if (!strcmp(value, "16")) info->depth = LIBCOOPGAMMA_UINT16;
			else if (!strcmp(value, "32")) info->depth = LIBCOOPGAMMA_UINT32;
			else if (!strcmp(value, "64")) info->depth = LIBCOOPGAMMA_UINT64;
			else if (!strcmp(value, "f"))  info->depth = LIBCOOPGAMMA_FLOAT;
			else if (!strcmp(value, "d"))  info->depth = LIBCOOPGAMMA_DOUBLE;
			else
				bad = 1;
		} else if (strstr(line, "Gamma support: ") == line) {
			have_gamma_support = 1 + !!have_gamma_support;
			if      (!strcmp(value, "yes"))   info->supported = LIBCOOPGAMMA_YES;
			else if (!strcmp(value, "no"))    info->supported = LIBCOOPGAMMA_NO;
			else if (!strcmp(value, "maybe")) info->supported = LIBCOOPGAMMA_MAYBE;
			else
				bad = 1;
		} else if ((r = (strstr(line, "Red size: ")   == line)) ||
			   (g = (strstr(line, "Green size: ") == line)) ||
			         strstr(line, "Blue size: ")  == line) {
			if (r)      have_red_size   = 1 + !!have_red_size,   outz = &info->red_size;
			else if (g) have_green_size = 1 + !!have_green_size, outz = &info->green_size;
			else        have_blue_size  = 1 + !!have_blue_size,  outz = &info->blue_size;
			*outz = (size_t)atol(value);
			sprintf(temp, "%zu", *outz);
			if (strcmp(value, temp))
				bad = 1;
		} else if ((x = r = (strstr(line, "Red x: ")   == line)) ||
			       (r = (strstr(line, "Red y: ")   == line)) ||
			   (x = g = (strstr(line, "Green x: ") == line)) ||
			       (g = (strstr(line, "Green y: ") == line)) ||
			   (x = b = (strstr(line, "Blue x: ")  == line)) ||
			       (b = (strstr(line, "Blue y: ")  == line)) ||
			   (x =     (strstr(line, "White x: ") == line)) ||
			             strstr(line, "White y: ") == line) {
			if      (r && x) have = &have_red_x,   outu = &info->red_x;
			else if (r)      have = &have_red_y,   outu = &info->red_y;
			else if (g && x) have = &have_green_x, outu = &info->green_x;
			else if (g)      have = &have_green_y, outu = &info->green_y;
			else if (b && x) have = &have_blue_x,  outu = &info->blue_x;
			else if (b)      have = &have_blue_y,  outu = &info->blue_y;
			else if (x)      have = &have_white_x, outu = &info->white_x;
			else             have = &have_white_y, outu = &info->white_y;
			*have = 1 + !!*have;
			*outu = (unsigned)atoi(value);
			sprintf(temp, "%u", *outu);
			if (strcmp(value, temp))
				bad = 1;
		} else if (strstr(line, "Colour space: ") == line) {
			have_colourspace = 1 + !!have_colourspace;
			if      (!strcmp(value, "sRGB"))    info->colourspace = LIBCOOPGAMMA_SRGB;
			else if (!strcmp(value, "RGB"))     info->colourspace = LIBCOOPGAMMA_RGB;
			else if (!strcmp(value, "non-RGB")) info->colourspace = LIBCOOPGAMMA_NON_RGB;
			else if (!strcmp(value, "grey"))    info->colourspace = LIBCOOPGAMMA_GREY;
			else
				info->colourspace = LIBCOOPGAMMA_UNKNOWN;
		}
	}

	(void) libcoopgamma_next_payload__(ctx, &_n);

	info->have_gamut = (have_red_x && have_green_x && have_blue_x && have_white_x &&
			    have_red_y && have_green_y && have_blue_y && have_white_y);

	if (bad || have_gamma_support != 1 || have_red_x > 1 || have_red_y > 1 ||
	    have_green_x > 1 || have_green_y > 1 || have_blue_x > 1 || have_blue_y > 1 ||
	    have_white_x > 1 || have_white_y > 1 || have_colourspace > 1) {
		errno = EBADMSG;
		copy_errno(ctx);
		return -1;
	}
	if (info->supported != LIBCOOPGAMMA_NO) {
		if (have_cooperative > 1 || have_depth != 1 || have_gamma_support != 1 ||
		    have_red_size != 1 || have_green_size != 1 || have_blue_size != 1) {
			errno = EBADMSG;
			copy_errno(ctx);
			return -1;
		}
	}

	return 0;
}