aboutsummaryrefslogtreecommitdiffstats
path: root/libcoopgamma_set_gamma_send.c
blob: d6daf91e22082a7a4a8bf4a2e427a93f2c4edf44 (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
/* See LICENSE file for copyright and license details. */
#include "common.h"


/**
 * Apply, update, or remove a gamma ramp adjustment, send request part
 * 
 * Cannot be used before connecting to the server
 * 
 * @param   filter  The filter to apply, update, or remove, gamma ramp meta-data must match the CRTC's
 * @param   ctx     The state of the library, must be connected
 * @param   async   Information about the request, that is needed to
 *                  identify and parse the response, is stored here
 * @return          Zero on success, -1 on error
 */
int
libcoopgamma_set_gamma_send(const libcoopgamma_filter_t *restrict filter, libcoopgamma_context_t *restrict ctx,
                            libcoopgamma_async_context_t *restrict async)
{
	const void *payload = NULL;
	const char *lifespan;
	char priority[sizeof("Priority: \n") + 3 * sizeof(int64_t)] = {'\0'};
	char length  [sizeof("Length: \n")   + 3 * sizeof(size_t) ] = {'\0'};
	size_t payload_size = 0, stopwidth = 0;

#if defined(__GNUC__) && !defined(__clang__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wnonnull-compare"
#endif
	if (!filter || !filter->crtc || strchr(filter->crtc, '\n') || !filter->class || strchr(filter->class, '\n')) {
		errno = EINVAL;
		goto fail;
	}
#if defined(__GNUC__) && !defined(__clang__)
# pragma GCC diagnostic pop
#endif

	switch (filter->lifespan) {
	case LIBCOOPGAMMA_REMOVE:        lifespan = "remove";        break;
	case LIBCOOPGAMMA_UNTIL_DEATH:   lifespan = "until-death";   break;
	case LIBCOOPGAMMA_UNTIL_REMOVAL: lifespan = "until-removal"; break;
	default:
		errno = EINVAL;
		goto fail;
	}

	if (filter->lifespan != LIBCOOPGAMMA_REMOVE) {
		switch (filter->depth) {
		case LIBCOOPGAMMA_FLOAT:  stopwidth = sizeof(float);  break;
		case LIBCOOPGAMMA_DOUBLE: stopwidth = sizeof(double); break;
		default: INTEGRAL_DEPTHS
			if (filter->depth <= 0 || (filter->depth & 7)) {
				errno = EINVAL;
				goto fail;
			}
			stopwidth = (size_t)(filter->depth / 8);
			break;
		}

		payload_size  = filter->ramps.u8.red_size;
		payload_size += filter->ramps.u8.green_size;
		payload_size += filter->ramps.u8.blue_size;
		payload_size *= stopwidth;
		payload = filter->ramps.u8.red;
		sprintf(priority, "Priority: %" PRIi64 "\n", filter->priority);
		sprintf(length, "Length: %zu\n", payload_size);
	}

	async->message_id = ctx->message_id;
	SEND_MESSAGE(ctx, payload, payload_size,
	             "Command: set-gamma\n"
	             "Message ID: %" PRIu32 "\n"
	             "CRTC: %s\n"
	             "Class: %s\n"
	             "Lifespan: %s\n"
	             "%s"
	             "%s"
	             "\n",
	             ctx->message_id, filter->crtc, filter->class, lifespan, priority, length);

	return 0;
fail:
	copy_errno(ctx);
	return -1;
}