aboutsummaryrefslogtreecommitdiffstats
path: root/src/servers/coopgamma.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/servers/coopgamma.c')
-rw-r--r--src/servers/coopgamma.c558
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;
-}
-