diff options
| author | Mattias Andrée <maandree@kth.se> | 2016-07-16 19:28:39 +0200 | 
|---|---|---|
| committer | Mattias Andrée <maandree@kth.se> | 2016-07-16 19:28:39 +0200 | 
| commit | 0c0d0ca0da8060484ab5f41a6ee73087755a69e3 (patch) | |
| tree | dd455f5a29edba440f2194a60fc06f0ceed8f397 /src/coopgamma-server | |
| parent | attributes (diff) | |
| download | coopgammad-0c0d0ca0da8060484ab5f41a6ee73087755a69e3.tar.gz coopgammad-0c0d0ca0da8060484ab5f41a6ee73087755a69e3.tar.bz2 coopgammad-0c0d0ca0da8060484ab5f41a6ee73087755a69e3.tar.xz | |
Restructure
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to '')
| -rw-r--r-- | src/coopgamma-server/chaining.c | 257 | ||||
| -rw-r--r-- | src/coopgamma-server/chaining.h | 75 | ||||
| -rw-r--r-- | src/coopgamma-server/server.c | 335 | ||||
| -rw-r--r-- | src/coopgamma-server/server.h | 93 | 
4 files changed, 760 insertions, 0 deletions
| diff --git a/src/coopgamma-server/chaining.c b/src/coopgamma-server/chaining.c new file mode 100644 index 0000000..b2739c2 --- /dev/null +++ b/src/coopgamma-server/chaining.c @@ -0,0 +1,257 @@ +/** + * 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 "chaining.h" + +#include <libclut.h> + +#include <stdio.h> +#include <stdlib.h> + + + +/** + * The name of the process + */ +extern char* restrict argv0; + + + +/** + * 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` + */ +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", +	      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 + */ +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; +      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++; +   +  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; +   +  out->table_filters[i] = *filter; +   +  return (ssize_t)i; +} + + +/** + * Make identity mapping ramps + *  + * @param   ramps   Output parameter for the ramps + * @param   output  The output for which the ramps shall be configured + * @return          Zero on success, -1 on error + */ +int make_plain_ramps(union gamma_ramps* restrict ramps, struct output* restrict output) +{ +  COPY_RAMP_SIZES(&(ramps->u8), output); +  switch (output->depth) +    { +    case 8: +      if (libgamma_gamma_ramps8_initialise(&(ramps->u8))) +	return -1; +      libclut_start_over(&(ramps->u8), UINT8_MAX, uint8_t, 1, 1, 1); +      break; +    case 16: +      if (libgamma_gamma_ramps16_initialise(&(ramps->u16))) +	return -1; +      libclut_start_over(&(ramps->u16), UINT16_MAX, uint16_t, 1, 1, 1); +      break; +    case 32: +      if (libgamma_gamma_ramps32_initialise(&(ramps->u32))) +	return -1; +      libclut_start_over(&(ramps->u32), UINT32_MAX, uint32_t, 1, 1, 1); +      break; +    case 64: +      if (libgamma_gamma_ramps64_initialise(&(ramps->u64))) +	return -1; +      libclut_start_over(&(ramps->u64), UINT64_MAX, uint64_t, 1, 1, 1); +      break; +    case -1: +      if (libgamma_gamma_rampsf_initialise(&(ramps->f))) +	return -1; +      libclut_start_over(&(ramps->f), 1.0f, float, 1, 1, 1); +      break; +    case -2: +      if (libgamma_gamma_rampsd_initialise(&(ramps->d))) +	return -1; +      libclut_start_over(&(ramps->d), (double)1, double, 1, 1, 1); +      break; +    default: +      abort(); +    } +  return 0; +} + diff --git a/src/coopgamma-server/chaining.h b/src/coopgamma-server/chaining.h new file mode 100644 index 0000000..cd31e5a --- /dev/null +++ b/src/coopgamma-server/chaining.h @@ -0,0 +1,75 @@ +/** + * 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/>. + */ +#ifndef COOPGAMMA_SERVER_CHAINING +#define COOPGAMMA_SERVER_CHAINING + + +#include "../types/output.h" + + + +#ifndef GCC_ONLY +# if defined(__GNUC__) && !defined(__clang__) +#  define GCC_ONLY(...)  __VA_ARGS__ +# else +#  define GCC_ONLY(...)  /* nothing */ +# endif +#endif + + + +/** + * 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` + */ +GCC_ONLY(__attribute__((nonnull))) +void apply_filter(union gamma_ramps* restrict dest, void* restrict application, +		  int depth, union gamma_ramps* restrict base); + + +/** + * Add a filter to an output + *  + * @param   output  The output + * @param   filter  The filter + * @return          The index given to the filter, -1 on error + */ +GCC_ONLY(__attribute__((nonnull))) +ssize_t add_filter(struct output* restrict output, struct filter* restrict filter); + +/** + * Make identity mapping ramps + *  + * @param   ramps   Output parameter for the ramps + * @param   output  The output for which the ramps shall be configured + * @return          Zero on success, -1 on error + */ +GCC_ONLY(__attribute__((nonnull))) +int make_plain_ramps(union gamma_ramps* restrict ramps, struct output* restrict output); + + +#endif + diff --git a/src/coopgamma-server/server.c b/src/coopgamma-server/server.c new file mode 100644 index 0000000..8d56119 --- /dev/null +++ b/src/coopgamma-server/server.c @@ -0,0 +1,335 @@ +/** + * 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 "server.h" +#include "chaining.h" +#include "../state.h" +#include "../communication.h" +#include "../util.h" +#include "../gamma-server/server.h" + +#include <libclut.h> + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + + + +/** + * 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++) +	{ +	  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; +	    } +	  output->table_filters[j] = output->table_filters[k]; +	  output->table_sums[j]    = output->table_sums[k]; +	} +      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, 0, +	       "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) +	memcpy(buf + n, output->table_sums[end].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; +  filter.class = NULL; +  filter.ramps = NULL; +  if (flush_filters(output, (size_t)r)) +    goto fail; +   +  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; +} + diff --git a/src/coopgamma-server/server.h b/src/coopgamma-server/server.h new file mode 100644 index 0000000..971f7df --- /dev/null +++ b/src/coopgamma-server/server.h @@ -0,0 +1,93 @@ +/** + * 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/>. + */ +#ifndef COOPGAMMA_SERVER_SERVER_H +#define COOPGAMMA_SERVER_SERVER_H + + +#include "../types/output.h" + +#include <stddef.h> + + + +#ifndef GCC_ONLY +# if defined(__GNUC__) && !defined(__clang__) +#  define GCC_ONLY(...)  __VA_ARGS__ +# else +#  define GCC_ONLY(...)  /* nothing */ +# endif +#endif + + + +/** + * Handle a closed connection + *  + * @param   client  The file descriptor for the client + * @return          Zero on success, -1 on error + */ +int connection_closed(int client); + +/** + * 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 + */ +GCC_ONLY(__attribute__((nonnull(2)))) +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); + +/** + * 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 + */ +GCC_ONLY(__attribute__((nonnull(2)))) +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); + + +/** + * 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 + */ +GCC_ONLY(__attribute__((nonnull))) +int flush_filters(struct output* restrict output, size_t first_updated); + + +#endif + | 
