diff options
Diffstat (limited to 'src/servers/coopgamma.c')
-rw-r--r-- | src/servers/coopgamma.c | 558 |
1 files changed, 0 insertions, 558 deletions
diff --git a/src/servers/coopgamma.c b/src/servers/coopgamma.c deleted file mode 100644 index 6e544be..0000000 --- a/src/servers/coopgamma.c +++ /dev/null @@ -1,558 +0,0 @@ -/** - * coopgammad -- Cooperative gamma server - * Copyright (C) 2016 Mattias Andrée (maandree@kth.se) - * - * 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 3 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, see <http://www.gnu.org/licenses/>. - */ -#include "coopgamma.h" -#include "gamma.h" -#include "../state.h" -#include "../communication.h" -#include "../util.h" -#include "../types/output.h" - -#include <libclut.h> - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - - - -/** - * Apply a filter on top of another filter - * - * @param dest The output for the resulting ramp-trio, must be initialised - * @param application The red, green and blue ramps, as one single raw array, - * of the filter that should be applied - * @param depth -1: `float` stops - * -2: `double` stops - * Other: the number of bits of each (integral) stop - * @param base The CLUT on top of which the new filter should be applied, - * this can be the same pointer as `dest` - */ -static void apply_filter(union gamma_ramps* restrict dest, void* restrict application, - int depth, union gamma_ramps* restrict base) -{ - union gamma_ramps app; - size_t bytedepth; - size_t red_width, green_width, blue_width; - - if (depth == -1) - bytedepth = sizeof(float); - else if (depth == -2) - bytedepth = sizeof(double); - else - bytedepth = (size_t)depth / 8; - - red_width = (app.u8.red_size = base->u8.red_size) * bytedepth; - green_width = (app.u8.green_size = base->u8.green_size) * bytedepth; - blue_width = (app.u8.blue_size = base->u8.blue_size) * bytedepth; - - app.u8.red = application; - app.u8.green = app.u8.red + red_width; - app.u8.blue = app.u8.green + green_width; - - if (dest != base) - { - memcpy(dest->u8.red, base->u8.red, red_width); - memcpy(dest->u8.green, base->u8.green, green_width); - memcpy(dest->u8.blue, base->u8.blue, blue_width); - } - - switch (depth) - { - case 8: - libclut_apply(&(dest->u8), UINT8_MAX, uint8_t, &(app.u8), UINT8_MAX, uint8_t, 1, 1, 1); - break; - case 16: - libclut_apply(&(dest->u16), UINT16_MAX, uint16_t, &(app.u16), UINT16_MAX, uint16_t, 1, 1, 1); - break; - case 32: - libclut_apply(&(dest->u32), UINT32_MAX, uint32_t, &(app.u32), UINT32_MAX, uint32_t, 1, 1, 1); - break; - case 64: - libclut_apply(&(dest->u64), UINT64_MAX, uint64_t, &(app.u64), UINT64_MAX, uint64_t, 1, 1, 1); - break; - case -1: - libclut_apply(&(dest->f), 1.0f, float, &(app.d), 1.0f, float, 1, 1, 1); - break; - case -2: - libclut_apply(&(dest->d), (double)1, double, &(app.f), (double)1, double, 1, 1, 1); - break; - default: - abort(); - } -} - - - -/** - * Remove a filter from an output - * - * @param out The output - * @param filter The filter - * @return The index of the filter, `out->table_size` if not found - */ -static ssize_t remove_filter(struct output* restrict out, struct filter* restrict filter) -{ - size_t i, n = out->table_size; - - for (i = 0; i < n; i++) - if (!strcmp(filter->class, out->table_filters[i].class)) - break; - - if (i == out->table_size) - { - fprintf(stderr, "%s: ignoring attempt to removing non-existing filter on CRTC %s: %s\n", - argv0, out->name, filter->class); - return (ssize_t)(out->table_size); - } - - filter_destroy(out->table_filters + i); - libgamma_gamma_ramps8_destroy(&(out->table_sums[i].u8)); - - n = n - i - 1; - memmove(out->table_filters + i, out->table_filters + i + 1, n * sizeof(*(out->table_filters))); - memmove(out->table_sums + i, out->table_sums + i + 1, n * sizeof(*(out->table_sums))); - out->table_size--; - - return (ssize_t)i; -} - - -/** - * Add a filter to an output - * - * @param out The output - * @param filter The filter - * @return The index given to the filter, -1 on error - */ -static ssize_t add_filter(struct output* restrict out, struct filter* restrict filter) -{ - size_t i, n = out->table_size; - int r = -1; - - /* Remove? */ - if (filter->lifespan == LIFESPAN_REMOVE) - return remove_filter(out, filter); - - /* Update? */ - for (i = 0; i < n; i++) - if (!strcmp(filter->class, out->table_filters[i].class)) - break; - if (i != n) - { - filter_destroy(out->table_filters + i); - out->table_filters[i] = *filter; - filter->class = NULL; - filter->ramps = NULL; - return (ssize_t)i; - } - - /* Add! */ - for (i = 0; i < n; i++) - if (filter->priority > out->table_filters[i].priority) - break; - - if (n == out->table_alloc) - { - void* new; - - new = realloc(out->table_filters, (n + 10) * sizeof(*(out->table_filters))); - if (new == NULL) - return -1; - out->table_filters = new; - - new = realloc(out->table_sums, (n + 10) * sizeof(*(out->table_sums))); - if (new == NULL) - return -1; - out->table_sums = new; - - out->table_alloc += 10; - } - - memmove(out->table_filters + i + 1, out->table_filters + i, (n - i) * sizeof(*(out->table_filters))); - memmove(out->table_sums + i + 1, out->table_sums + i, (n - i) * sizeof(*(out->table_sums))); - out->table_size++; - - out->table_filters[i] = *filter; - filter->class = NULL; - filter->ramps = NULL; - - COPY_RAMP_SIZES(&(out->table_sums[i].u8), out); - switch (out->depth) - { - case 8: r = libgamma_gamma_ramps8_initialise(&(out->table_sums[i].u8)); break; - case 16: r = libgamma_gamma_ramps16_initialise(&(out->table_sums[i].u16)); break; - case 32: r = libgamma_gamma_ramps32_initialise(&(out->table_sums[i].u32)); break; - case 64: r = libgamma_gamma_ramps64_initialise(&(out->table_sums[i].u64)); break; - case -1: r = libgamma_gamma_rampsf_initialise(&(out->table_sums[i].f)); break; - case -2: r = libgamma_gamma_rampsd_initialise(&(out->table_sums[i].d)); break; - default: - abort(); - } - if (r < 0) - return -1; - - return (ssize_t)i; -} - - -/** - * Handle a closed connection - * - * @param client The file descriptor for the client - * @return Zero on success, -1 on error - */ -int connection_closed(int client) -{ - size_t i, j, k; - int remove; - - for (i = 0; i < outputs_n; i++) - { - struct output* output = outputs + i; - ssize_t updated = -1; - for (j = k = 0; j < output->table_size; j += !remove, k++) - { - if (j != k) - { - output->table_filters[j] = output->table_filters[k]; - output->table_sums[j] = output->table_sums[k]; - } - remove = output->table_filters[j].client == client; - remove = remove && (output->table_filters[j].lifespan == LIFESPAN_UNTIL_DEATH); - if (remove) - { - filter_destroy(output->table_filters + j); - libgamma_gamma_ramps8_destroy(&(output->table_sums[j].u8)); - output->table_size -= 1; - if (updated == -1) - updated = (ssize_t)j; - } - } - if (updated >= 0) - if (flush_filters(output, (size_t)updated) < 0) - return -1; - } - - return 0; -} - - -/** - * Handle a ‘Command: get-gamma’ message - * - * @param conn The index of the connection - * @param message_id The value of the ‘Message ID’ header - * @param crtc The value of the ‘CRTC’ header - * @param coalesce The value of the ‘Coalesce’ header - * @param high_priority The value of the ‘High priority’ header - * @param low_priority The value of the ‘Low priority’ header - * @return Zero on success (even if ignored), -1 on error, - * 1 if connection closed - */ -int handle_get_gamma(size_t conn, const char* restrict message_id, const char* restrict crtc, - const char* restrict coalesce, const char* restrict high_priority, - const char* restrict low_priority) -{ - struct output* restrict output; - int64_t high, low; - int coal; - char* restrict buf; - size_t start, end, len, n, i; - char depth[3]; - char tables[sizeof("Tables: \n") + 3 * sizeof(size_t)]; - - if (crtc == NULL) return send_error("protocol error: 'CRTC' header omitted"); - if (coalesce == NULL) return send_error("protocol error: 'Coalesce' header omitted"); - if (high_priority == NULL) return send_error("protocol error: 'High priority' header omitted"); - if (low_priority == NULL) return send_error("protocol error: 'Low priority' header omitted"); - - high = (int64_t)atoll(high_priority); - low = (int64_t)atoll(low_priority); - - if (!strcmp(coalesce, "yes")) - coal = 1; - else if (!strcmp(coalesce, "no")) - coal = 0; - else - return send_error("protocol error: recognised value for 'Coalesce' header"); - - output = output_find_by_name(crtc, outputs, outputs_n); - if (output == NULL) - return send_error("selected CRTC does not exist"); - else if (output->supported == LIBGAMMA_NO) - return send_error("selected CRTC does not support gamma adjustments"); - - for (start = 0; start < output->table_size; start++) - if (output->table_filters[start].priority <= high) - break; - - for (end = output->table_size; end > 0; end--) - if (output->table_filters[end - 1].priority >= low) - break; - - switch (output->depth) - { - case -2: strcpy(depth, "d"); break; - case -1: strcpy(depth, "f"); break; - default: - sprintf(depth, "%i", output->depth); - break; - } - - if (coal) - { - *tables = '\0'; - n = output->ramps_size; - } - else - { - sprintf(tables, "Tables: %zu\n", end - start); - n = (sizeof(int64_t) + output->ramps_size) * (end - start); - for (i = start; i < end; i++) - n += strlen(output->table_filters[i].class) + 1; - } - - MAKE_MESSAGE(&buf, &n, n, - "In response to: %s\n" - "Depth: %s\n" - "Red size: %zu\n" - "Green size: %zu\n" - "Blue size: %zu\n" - "%s" - "Length: %zu\n" - "\n", - message_id, depth, output->red_size, output->green_size, - output->blue_size, tables, n); - - if (coal) - { - if ((start == 0) && (start < end)) - memcpy(buf + n, output->table_sums[end - 1].u8.red, output->ramps_size); - else - { - union gamma_ramps ramps; - if (make_plain_ramps(&ramps, output)) - { - int saved_errno = errno; - free(buf); - errno = saved_errno; - return -1; - } - for (i = start; i < end; i++) - apply_filter(&ramps, output->table_filters[i].ramps, output->depth, &ramps); - memcpy(buf + n, ramps.u8.red, output->ramps_size); - libgamma_gamma_ramps8_destroy(&(ramps.u8)); - } - n += output->ramps_size; - } - else - for (i = start; i < end; i++) - { -#if defined(__clang__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wcast-align" -#endif - *(int64_t*)(buf + n) = output->table_filters[i].priority; -#if defined(__clang__) -# pragma GCC diagnostic pop -#endif - n += sizeof(int64_t); - len = strlen(output->table_filters[i].class) + 1; - memcpy(buf + n, output->table_filters[i].class, len); - n += len; - memcpy(buf + n, output->table_filters[i].ramps, output->ramps_size); - n += output->ramps_size; - } - - return send_message(conn, buf, n); -} - - -/** - * Handle a ‘Command: set-gamma’ message - * - * @param conn The index of the connection - * @param message_id The value of the ‘Message ID’ header - * @param crtc The value of the ‘CRTC’ header - * @param priority The value of the ‘Priority’ header - * @param class The value of the ‘Class’ header - * @param lifespan The value of the ‘Lifespan’ header - * @return Zero on success (even if ignored), -1 on error, - * 1 if connection closed - */ -int handle_set_gamma(size_t conn, const char* restrict message_id, const char* restrict crtc, - const char* restrict priority, const char* restrict class, const char* restrict lifespan) -{ - struct message* restrict msg = inbound + conn; - struct output* restrict output = NULL; - struct filter filter; - char* restrict p; - char* restrict q; - int saved_errno; - ssize_t r; - - if (crtc == NULL) return send_error("protocol error: 'CRTC' header omitted"); - if (class == NULL) return send_error("protocol error: 'Class' header omitted"); - if (lifespan == NULL) return send_error("protocol error: 'Lifespan' header omitted"); - - filter.client = connections[conn]; - filter.priority = priority == NULL ? 0 : (int64_t)atoll(priority); - filter.ramps = NULL; - - output = output_find_by_name(crtc, outputs, outputs_n); - if (output == NULL) - return send_error("CRTC does not exists"); - - p = strstr(class, "::"); - if ((p == NULL) || (p == class)) - return send_error("protocol error: malformatted value for 'Class' header"); - q = strstr(p + 2, "::"); - if ((q == NULL) || (q == p)) - return send_error("protocol error: malformatted value for 'Class' header"); - - if (!strcmp(lifespan, "until-removal")) - filter.lifespan = LIFESPAN_UNTIL_REMOVAL; - else if (!strcmp(lifespan, "until-death")) - filter.lifespan = LIFESPAN_UNTIL_DEATH; - else if (!strcmp(lifespan, "remove")) - filter.lifespan = LIFESPAN_REMOVE; - else - return send_error("protocol error: recognised value for 'Lifespan' header"); - - if (filter.lifespan == LIFESPAN_REMOVE) - { - if (msg->payload_size) - fprintf(stderr, "%s: ignoring superfluous payload on Command: set-gamma message with " - "Lifespan: remove\n", argv0); - if (priority != NULL) - fprintf(stderr, "%s: ignoring superfluous Priority header on Command: set-gamma message with " - "Lifespan: remove\n", argv0); - } - else if (msg->payload_size != output->ramps_size) - return send_error("invalid payload: size of message payload does matched the expectancy"); - else if (priority == NULL) - return send_error("protocol error: 'Priority' header omitted"); - - filter.class = memdup(class, strlen(class) + 1); - if (filter.class == NULL) - goto fail; - - if (filter.lifespan != LIFESPAN_REMOVE) - { - filter.ramps = memdup(msg->payload, msg->payload_size); - if (filter.ramps == NULL) - goto fail; - } - - if ((r = add_filter(output, &filter)) < 0) - goto fail; - if (flush_filters(output, (size_t)r)) - goto fail; - - free(filter.class); - free(filter.ramps); - return send_errno(0); - - fail: - saved_errno = errno; - send_errno(saved_errno); - free(filter.class); - free(filter.ramps); - errno = saved_errno; - return -1; -} - - - -/** - * Recalculate the resulting gamma and - * update push the new gamma ramps to the CRTC - * - * @param output The output - * @param first_updated The index of the first added or removed filter - * @return Zero on success, -1 on error - */ -int flush_filters(struct output* restrict output, size_t first_updated) -{ - union gamma_ramps plain; - union gamma_ramps* last; - size_t i; - - if (first_updated == 0) - { - if (make_plain_ramps(&plain, output) < 0) - return -1; - last = &plain; - } - else - last = output->table_sums + (first_updated - 1); - - for (i = first_updated; i < output->table_size; i++) - { - apply_filter(output->table_sums + i, output->table_filters[i].ramps, output->depth, last); - last = output->table_sums + i; - } - - set_gamma(output, last); - - if (first_updated == 0) - libgamma_gamma_ramps8_destroy(&(plain.u8)); - - return 0; -} - - - -/** - * Preserve current gamma ramps at priority 0 for all outputs - * - * @return Zero on success, -1 on error - */ -int preserve_gamma(void) -{ - size_t i; - - for (i = 0; i < outputs_n; i++) - { - struct filter filter = { - .client = -1, - .priority = 0, - .class = NULL, - .lifespan = LIFESPAN_UNTIL_REMOVAL, - .ramps = NULL - }; - outputs[i].table_filters = calloc(4, sizeof(*(outputs[i].table_filters))); - outputs[i].table_sums = calloc(4, sizeof(*(outputs[i].table_sums))); - outputs[i].table_alloc = 4; - outputs[i].table_size = 1; - filter.class = memdup(PKGNAME "::" COMMAND "::preserved", sizeof(PKGNAME "::" COMMAND "::preserved")); - if (filter.class == NULL) - return -1; - filter.ramps = memdup(outputs[i].saved_ramps.u8.red, outputs[i].ramps_size); - if (filter.ramps == NULL) - return -1; - outputs[i].table_filters[0] = filter; - COPY_RAMP_SIZES(&(outputs[i].table_sums[0].u8), outputs + i); - if (!gamma_ramps_unmarshal(outputs[i].table_sums, outputs[i].saved_ramps.u8.red, outputs[i].ramps_size)) - return -1; - } - - return 0; -} - |