/** * libcoopgamma -- Library for interfacing with cooperative gamma servers * Copyright (C) 2016 Mattias Andrée (maandree@kth.se) * * This library 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 library 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 library. If not, see . */ #ifndef LIBCOOPGAMMA_H #define LIBCOOPGAMMA_H #include #include #include #if defined(__clang__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wdocumentation" #endif #if defined(__GNUC__) && !defined(__clang__) # define LIBCOOPGAMMA_GCC_ONLY(...) __VA_ARGS__ #else # define LIBCOOPGAMMA_GCC_ONLY(...) /* ignore */ #endif /** * Unmarshal was successful * * This value will always be zero */ #define LIBCOOPGAMMA_SUCCESS 0 /** * Unmarshal failed: the marshalled data was created * with a older version of libcoopgamma that does not * marshall the data in a compatible way * * This value will always be positive */ #define LIBCOOPGAMMA_INCOMPATIBLE_DOWNGRADE 1 /** * Unmarshal failed: the marshalled data was created with * a newer version libcoopgamma that does not marshall * the data in a compatible way * * This value will always be positive */ #define LIBCOOPGAMMA_INCOMPATIBLE_UPGRADE 2 /** * Unmarshal failed because of an error, `errno` has been set * * This value will always be -1 and will be the * only negative value in this category of constants */ #define LIBCOOPGAMMA_ERRNO_SET -1 /** * Number used to identify implementation * version of `libcoopgamma_support_t`, if it * is ever modified, this number is increased */ #define LIBCOOPGAMMA_SUPPORT_VERSION 0 /** * Number used to identify implementation * version of `libcoopgamma_depth_t`, if it * is ever modified, this number is increased */ #define LIBCOOPGAMMA_DEPTH_VERSION 0 /** * Number used to identify implementation * version of `libcoopgamma_lifespan_t`, if it * is ever modified, this number is increased */ #define LIBCOOPGAMMA_LIFESPAN_VERSION 0 /** * Number used to identify implementation * version of `libcoopgamma_ramps*_t`, if they * are ever modified, this number is increased */ #define LIBCOOPGAMMA_RAMPS_VERSION 0 /** * Number used to identify implementation * version of `libcoopgamma_filter_t`, if it * is ever modified, this number is increased */ #define LIBCOOPGAMMA_FILTER_VERSION 0 /** * Number used to identify implementation * version of `libcoopgamma_ctrc_info_t`, if it * is ever modified, this number is increased */ #define LIBCOOPGAMMA_CRTC_INFO_VERSION 0 /** * Number used to identify implementation * version of `libcoopgamma_filter_query_t`, if it * is ever modified, this number is increased */ #define LIBCOOPGAMMA_FILTER_QUERY_VERSION 0 /** * Number used to identify implementation * version of `libcoopgamma_queried_filter_t`, if it * is ever modified, this number is increased */ #define LIBCOOPGAMMA_QUERIED_FILTER_VERSION 0 /** * Number used to identify implementation * version of `libcoopgamma_filter_table_t`, if it * is ever modified, this number is increased */ #define LIBCOOPGAMMA_FILTER_TABLE_VERSION 0 /** * Number used to identify implementation * version of `libcoopgamma_error_t`, if it * is ever modified, this number is increased */ #define LIBCOOPGAMMA_ERROR_VERSION 0 /** * Number used to identify implementation * version of `libcoopgamma_context_t`, if it * is ever modified, this number is increased */ #define LIBCOOPGAMMA_CONTEXT_VERSION 0 /** * Number used to identify implementation * version of `libcoopgamma_async_context_t`, if it * is ever modified, this number is increased */ #define LIBCOOPGAMMA_ASYNC_CONTEXT_VERSION 0 /** * Values used to indicate the support * for gamma adjustments */ typedef enum libcoopgamma_support { /** * Gamma adjustments are not supported * * This value will always be 0 */ LIBCOOPGAMMA_NO = 0, /** * Don't know whether gamma * adjustments are supported * * This value will always be 1 */ LIBCOOPGAMMA_MAYBE = 1, /** * Gamma adjustments are supported * * This value will always be 2 */ LIBCOOPGAMMA_YES = 2 } libcoopgamma_support_t; /** * Values used to tell which datatype * is used for the gamma ramp stops * * The values will always be the number * of bits for integral types, and * negative for floating-point types */ typedef enum libcoopgamma_depth { /** * `uint8_t` */ LIBCOOPGAMMA_UINT8 = 8, /** * `uint16_t` */ LIBCOOPGAMMA_UINT16 = 16, /** * `uint32_t` */ LIBCOOPGAMMA_UINT32 = 32, /** * `uint64_t` */ LIBCOOPGAMMA_UINT64 = 64, /** * `float` */ LIBCOOPGAMMA_FLOAT = -1, /** * `double` */ LIBCOOPGAMMA_DOUBLE = -2 } libcoopgamma_depth_t; /** * Values used to tell when a filter * should be removed */ typedef enum libcoopgamma_lifespan { /** * Remove the filter now * * This value will always be 0 */ LIBCOOPGAMMA_REMOVE = 0, /** * Remove the filter when disconnecting * from the coopgamma server */ LIBCOOPGAMMA_UNTIL_DEATH = 1, /** * Only remove the filter when it * is explicitly requested */ LIBCOOPGAMMA_UNTIL_REMOVAL = 2 } libcoopgamma_lifespan_t; /** * Define a gamma ramp structure * * @param suffix:identifier The end of the name of the `struct` * @param type:scalar-type The datatype of the stops */ #define LIBCOOPGAMMA_RAMPS__(suffix, type) \ typedef struct libcoopgamma_ramps##suffix \ { \ /** * The number of stops in the red ramp */ \ size_t red_size; \ \ /** * The number of stops in the green ramp */ \ size_t green_size; \ \ /** * The number of stops in the blue ramp */ \ size_t blue_size; \ \ /** * The red ramp */ \ type* red; \ \ /** * The green ramp */ \ type* green; \ \ /** * The blue ramp */ \ type* blue; \ \ } libcoopgamma_ramps##suffix##_t /** * `typedef struct libcoopgamma_ramps8 libcoopgamma_ramps8_t` * * Gamma ramp structure with `uint8_t` stops */ LIBCOOPGAMMA_RAMPS__(8, uint8_t); /** * `typedef struct libcoopgamma_ramps16 libcoopgamma_ramps16_t` * * Gamma ramp structure with `uint16_t` stops */ LIBCOOPGAMMA_RAMPS__(16, uint16_t); /** * `typedef struct libcoopgamma_ramps32 libcoopgamma_ramps32_t` * * Gamma ramp structure with `uint32_t` stops */ LIBCOOPGAMMA_RAMPS__(32, uint32_t); /** * `typedef struct libcoopgamma_ramps64 libcoopgamma_ramps64_t` * * Gamma ramp structure with `uint64_t` stops */ LIBCOOPGAMMA_RAMPS__(64, uint64_t); /** * `typedef struct libcoopgamma_rampsf libcoopgamma_rampsf_t` * * Gamma ramp structure with `float` stops */ LIBCOOPGAMMA_RAMPS__(f, float); /** * `typedef struct libcoopgamma_rampsd libcoopgamma_rampsd_t` * * Gamma ramp structure with `double` stops */ LIBCOOPGAMMA_RAMPS__(d, double); /** * Union with all ramp types. */ typedef union libcoopgamma_ramps { /** * 8-bit version */ libcoopgamma_ramps8_t u8; /** * 16-bit version */ libcoopgamma_ramps16_t u16; /** * 32-bit version */ libcoopgamma_ramps32_t u32; /** * 64-bit version */ libcoopgamma_ramps64_t u64; /** * Single precision floating-point version */ libcoopgamma_rampsf_t f; /** * Double precision floating-point version */ libcoopgamma_rampsd_t d; } libcoopgamma_ramps_t; /** * Data set to the coopgamma server to apply, * update, or remove a filter. */ typedef struct libcoopgamma_filter { /** * The priority of the filter, higher priority * is applied first. The gamma correction should * have priority 0. */ int64_t priority; /** * The CRTC for which this filter shall be applied */ char* crtc; /** * Identifier for the filter * * The syntax must be "${PACKAGE_NAME}::${COMMAND_NAME}::${RULE}" */ char* class; /** * When shall the filter be removed? * * If this member's value is `LIBCOOPGAMMA_REMOVE`, * only `.crtc` and `.class` need also be defined */ libcoopgamma_lifespan_t lifespan; /** * The data type and bit-depth of the ramp stops */ libcoopgamma_depth_t depth; /** * The gamma ramp adjustments of the filter */ libcoopgamma_ramps_t ramps; } libcoopgamma_filter_t; /** * Gamma ramp meta information for a CRTC */ typedef struct libcoopgamma_crtc_info { /** * Is cooperative gamma server running? */ int cooperative; /** * The data type and bit-depth of the ramp stops */ libcoopgamma_depth_t depth; /** * Is gamma adjustments supported on the CRTC? * If not, `.depth`, `.red_size`, `.green_size`, * and `.blue_size` are undefined */ libcoopgamma_support_t supported; #if INT_MAX != LONG_MAX int padding__; #endif /** * The number of stops in the red ramp */ size_t red_size; /** * The number of stops in the green ramp */ size_t green_size; /** * The number of stops in the blue ramp */ size_t blue_size; } libcoopgamma_crtc_info_t; /** * Data sent to the coopgamma server * when requestng the current filter * table */ typedef struct libcoopgamma_filter_query { /** * Do no return filters with higher * priority than this value */ int64_t high_priority; /** * Do no return filters with lower * priority than this value */ int64_t low_priority; /** * The CRTC for which the the current * filters shall returned */ char* crtc; /** * Whether to coalesce all filters * into one gamma ramp triplet */ int coalesce; #if INT_MAX != LONG_MAX int padding__; #endif } libcoopgamma_filter_query_t; /** * Stripped down version of `libcoopgamma_filter` * which only contains the information returned * in response to "Command: get-gamma" */ typedef struct libcoopgamma_queried_filter { /** * The filter's priority */ int64_t priority; /** * The filter's class */ char* class; /** * The gamma ramp adjustments of the filter */ libcoopgamma_ramps_t ramps; } libcoopgamma_queried_filter_t; /** * Response type for "Command: get-gamma": a * list of applied filters and meta-information * that was necessary for decoding the response */ typedef struct libcoopgamma_filter_table { /** * The number of stops in the red ramp */ size_t red_size; /** * The number of stops in the green ramp */ size_t green_size; /** * The number of stops in the blue ramp */ size_t blue_size; /** * The number of filters */ size_t filter_count; /** * The filters, should be ordered by priority * in descending order, lest there is something * wrong with the coopgamma server * * If filter coalition was requested, there will * be exactly one filter (`.filter_count == 1`) * and `.filters->class == NULL` and * `.filters->priority` is undefined. */ libcoopgamma_queried_filter_t* filters; /** * The data type and bit-depth of the ramp stops */ libcoopgamma_depth_t depth; #if INT_MAX != LONG_MAX int padding__; #endif } libcoopgamma_filter_table_t; /** * Error message from coopgamma server */ typedef struct libcoopgamma_error { /** * Error code * * If `.custom` is false, 0 indicates * success, otherwise, 0 indicates that * no error code has been assigned */ uint64_t number; /** * Is this a custom error? */ int custom; /** * Did the error occur on the server-side? */ int server_side; /** * Error message, can be `NULL` if * `.custom` is false */ char* description; } libcoopgamma_error_t; /** * Library state * * Use of this structure is not thread-safe, * create one instance per thread that uses * this structure */ typedef struct libcoopgamma_context { /** * The error of the last failed function call * * This member is undefined after successful function call */ libcoopgamma_error_t error; /** * File descriptor for the socket */ int fd; /* The members below are internal. */ /** * Whether `libcoopgamma_synchronise` have * read the empty end-of-headers line */ int have_all_headers; /** * Whether `libcoopgamma_synchronise` is reading * a corrupt but recoverable message */ int bad_message; #if INT_MAX != LONG_MAX int padding__; #endif /** * Message ID of the next message */ uint32_t message_id; /** * The ID of outbound message to which the inbound * message being read by `libcoopgamma_synchronise` * is a response */ uint32_t in_response_to; /** * Buffer with the outbound message */ char* outbound; /** * The write head for `outbound` */ size_t outbound_head; /** * The read head for `outbound` */ size_t outbound_tail; /** * The allocation size of `outbound` */ size_t outbound_size; /** * Buffer with the inbound message */ char* inbound; /** * The write head for `inbound` */ size_t inbound_head; /** * The read head for `inbound` */ size_t inbound_tail; /** * The allocation size of `inbound` */ size_t inbound_size; /** * The value of 'Length' header in * the inbound message */ size_t length; /** * The beginning of the current line that * is being read by `libcoopgamma_synchronise` */ size_t curline; } libcoopgamma_context_t; /** * Information necessary to identify and * parse a response from the server */ typedef struct libcoopgamma_async_context { /* All members are internal. */ /** * The value of the 'In response to' header * in the waited message */ uint32_t message_id; /** * Whether to coalesce all filters * into one gamma ramp triplet */ int coalesce; } libcoopgamma_async_context_t; /** * Initialise a `libcoopgamma_ramps8_t`, `libcoopgamma_ramps16_t`, `libcoopgamma_ramps32_t`, * `libcoopgamma_ramps64_t`, `libcoopgamma_rampsf_t`, or `libcoopgamma_rampsd_t` * * `this->red_size`, `this->green_size`, and `this->blue_size` must already be set * * @param this The record to initialise * @return Zero on success, -1 on error */ #define libcoopgamma_ramps_initialise(this) \ (libcoopgamma_ramps_initialise_((this), sizeof(*((this)->red)))) /** * Marshal a `libcoopgamma_ramps8_t`, `libcoopgamma_ramps16_t`, `libcoopgamma_ramps32_t`, * `libcoopgamma_ramps64_t`, `libcoopgamma_rampsf_t`, or `libcoopgamma_rampsd_t` into a buffer * * @param this The record to marshal * @param buf The output buffer, `NULL` to only measure * how large this buffer has to be * @return The number of marshalled bytes, or if `buf == NULL`, * how many bytes would be marshalled if `buf != NULL` */ #define libcoopgamma_ramps_marshal(this, buf) \ (libcoopgamma_ramps_marshal_((this), (buf), sizeof(*((this)->red)))) /** * Unmarshal a `libcoopgamma_ramps8_t`, `libcoopgamma_ramps16_t`, `libcoopgamma_ramps32_t`, * `libcoopgamma_ramps64_t`, `libcoopgamma_rampsf_t`, or `libcoopgamma_rampsd_t` from a buffer * * @param this The output parameter for unmarshalled record * @param buf The buffer with the marshalled record * @param n Output parameter for the number of unmarshalled bytes, undefined on failure * @return `LIBCOOPGAMMA_SUCCESS` (0), `LIBCOOPGAMMA_INCOMPATIBLE_DOWNGRADE`, * `LIBCOOPGAMMA_INCOMPATIBLE_UPGRADE`, or `LIBCOOPGAMMA_ERRNO_SET` */ #define libcoopgamma_ramps_unmarshal(this, buf, n) \ (libcoopgamma_ramps_unmarshal_((this), (buf), (n), sizeof(*((this)->red)))) /** * Initialise a `libcoopgamma_ramps8_t`, `libcoopgamma_ramps16_t`, `libcoopgamma_ramps32_t`, * `libcoopgamma_ramps64_t`, `libcoopgamma_rampsf_t`, or `libcoopgamma_rampsd_t` * * `this->red_size`, `this->green_size`, and `this->blue_size` must already be set * * @param this The record to initialise * @param width The `sizeof(*(this->red))` * @return Zero on success, -1 on error */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) int libcoopgamma_ramps_initialise_(void* restrict, size_t); /** * Release all resources allocated to a `libcoopgamma_ramps8_t`, `libcoopgamma_ramps16_t`, * `libcoopgamma_ramps32_t`, `libcoopgamma_ramps64_t`, `libcoopgamma_rampsf_t`, * `libcoopgamma_rampsd_t`, or `libcoopgamma_ramps_t`, the allocation of the record * itself is not freed * * Always call this function after failed call to `libcoopgamma_ramps_initialise` * or failed call to `libcoopgamma_ramps_unmarshal` * * @param this The record to destroy */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) void libcoopgamma_ramps_destroy(void* restrict); /** * Marshal a `libcoopgamma_ramps8_t`, `libcoopgamma_ramps16_t`, `libcoopgamma_ramps32_t`, * `libcoopgamma_ramps64_t`, `libcoopgamma_rampsf_t`, or `libcoopgamma_rampsd_t` into a buffer * * @param this The record to marshal * @param buf The output buffer, `NULL` to only measure * how large this buffer has to be * @param width The `sizeof(*(this->red))` * @return The number of marshalled bytes, or if `buf == NULL`, * how many bytes would be marshalled if `buf != NULL` */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__(1), __leaf__))) size_t libcoopgamma_ramps_marshal_(const void* restrict, void* restrict, size_t); /** * Unmarshal a `libcoopgamma_ramps8_t`, `libcoopgamma_ramps16_t`, `libcoopgamma_ramps32_t`, * `libcoopgamma_ramps64_t`, `libcoopgamma_rampsf_t`, or `libcoopgamma_rampsd_t` from a buffer * * @param this The output parameter for unmarshalled record * @param buf The buffer with the marshalled record * @param n Output parameter for the number of unmarshalled bytes, undefined on failure * @param width The `sizeof(*(this->red))` * @return `LIBCOOPGAMMA_SUCCESS` (0), `LIBCOOPGAMMA_INCOMPATIBLE_DOWNGRADE`, * `LIBCOOPGAMMA_INCOMPATIBLE_UPGRADE`, or `LIBCOOPGAMMA_ERRNO_SET` */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) int libcoopgamma_ramps_unmarshal_(void* restrict, const void* restrict, size_t* restrict, size_t); /** * Initialise a `libcoopgamma_filter_t` * * @param this The record to initialise * @return Zero on success, -1 on error */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) int libcoopgamma_filter_initialise(libcoopgamma_filter_t* restrict); /** * Release all resources allocated to a `libcoopgamma_filter_t`, * the allocation of the record itself is not freed * * Always call this function after failed call to `libcoopgamma_filter_initialise` * or failed call to `libcoopgamma_filter_unmarshal` * * @param this The record to destroy */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) void libcoopgamma_filter_destroy(libcoopgamma_filter_t* restrict); /** * Marshal a `libcoopgamma_filter_t` into a buffer * * @param this The record to marshal * @param buf The output buffer, `NULL` to only measure * how large this buffer has to be * @return The number of marshalled bytes, or if `buf == NULL`, * how many bytes would be marshalled if `buf != NULL` */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__(1)))) size_t libcoopgamma_filter_marshal(const libcoopgamma_filter_t* restrict, void* restrict); /** * Unmarshal a `libcoopgamma_filter_t` from a buffer * * @param this The output parameter for unmarshalled record * @param buf The buffer with the marshalled record * @param n Output parameter for the number of unmarshalled bytes, undefined on failure * @return `LIBCOOPGAMMA_SUCCESS` (0), `LIBCOOPGAMMA_INCOMPATIBLE_DOWNGRADE`, * `LIBCOOPGAMMA_INCOMPATIBLE_UPGRADE`, or `LIBCOOPGAMMA_ERRNO_SET` */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__))) int libcoopgamma_filter_unmarshal(libcoopgamma_filter_t* restrict, const void* restrict, size_t* restrict); /** * Initialise a `libcoopgamma_crtc_info_t` * * @param this The record to initialise * @return Zero on success, -1 on error */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) int libcoopgamma_crtc_info_initialise(libcoopgamma_crtc_info_t* restrict); /** * Release all resources allocated to a `libcoopgamma_crtc_info_t`, * the allocation of the record itself is not freed * * Always call this function after failed call to `libcoopgamma_crtc_info_initialise` * or failed call to `libcoopgamma_crtc_info_unmarshal` * * @param this The record to destroy */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) void libcoopgamma_crtc_info_destroy(libcoopgamma_crtc_info_t* restrict); /** * Marshal a `libcoopgamma_crtc_info_t` into a buffer * * @param this The record to marshal * @param buf The output buffer, `NULL` to only measure * how large this buffer has to be * @return The number of marshalled bytes, or if `buf == NULL`, * how many bytes would be marshalled if `buf != NULL` */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__(1), __leaf__))) size_t libcoopgamma_crtc_info_marshal(const libcoopgamma_crtc_info_t* restrict, void* restrict); /** * Unmarshal a `libcoopgamma_crtc_info_t` from a buffer * * @param this The output parameter for unmarshalled record * @param buf The buffer with the marshalled record * @param n Output parameter for the number of unmarshalled bytes, undefined on failure * @return `LIBCOOPGAMMA_SUCCESS` (0), `LIBCOOPGAMMA_INCOMPATIBLE_DOWNGRADE`, * `LIBCOOPGAMMA_INCOMPATIBLE_UPGRADE`, or `LIBCOOPGAMMA_ERRNO_SET` */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) int libcoopgamma_crtc_info_unmarshal(libcoopgamma_crtc_info_t* restrict, const void* restrict, size_t* restrict); /** * Initialise a `libcoopgamma_filter_query_t` * * @param this The record to initialise * @return Zero on success, -1 on error */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) int libcoopgamma_filter_query_initialise(libcoopgamma_filter_query_t* restrict); /** * Release all resources allocated to a `libcoopgamma_filter_query_t`, * the allocation of the record itself is not freed * * Always call this function after failed call to `libcoopgamma_filter_query_initialise` * or failed call to `libcoopgamma_filter_query_unmarshal` * * @param this The record to destroy */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) void libcoopgamma_filter_query_destroy(libcoopgamma_filter_query_t* restrict); /** * Marshal a `libcoopgamma_filter_query_t` into a buffer * * @param this The record to marshal * @param buf The output buffer, `NULL` to only measure * how large this buffer has to be * @return The number of marshalled bytes, or if `buf == NULL`, * how many bytes would be marshalled if `buf != NULL` */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__(1), __leaf__))) size_t libcoopgamma_filter_query_marshal(const libcoopgamma_filter_query_t* restrict, void* restrict); /** * Unmarshal a `libcoopgamma_filter_query_t` from a buffer * * @param this The output parameter for unmarshalled record * @param buf The buffer with the marshalled record * @param n Output parameter for the number of unmarshalled bytes, undefined on failure * @return `LIBCOOPGAMMA_SUCCESS` (0), `LIBCOOPGAMMA_INCOMPATIBLE_DOWNGRADE`, * `LIBCOOPGAMMA_INCOMPATIBLE_UPGRADE`, or `LIBCOOPGAMMA_ERRNO_SET` */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) int libcoopgamma_filter_query_unmarshal(libcoopgamma_filter_query_t* restrict, const void* restrict, size_t* restrict); /** * Initialise a `libcoopgamma_queried_filter_t` * * @param this The record to initialise * @return Zero on success, -1 on error */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) int libcoopgamma_queried_filter_initialise(libcoopgamma_queried_filter_t* restrict); /** * Release all resources allocated to a `libcoopgamma_queried_filter_t`, * the allocation of the record itself is not freed * * Always call this function after failed call to `libcoopgamma_queried_filter_initialise` * or failed call to `libcoopgamma_queried_filter_unmarshal` * * @param this The record to destroy */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__))) void libcoopgamma_queried_filter_destroy(libcoopgamma_queried_filter_t* restrict); /** * Marshal a `libcoopgamma_queried_filter_t` into a buffer * * @param this The record to marshal * @param buf The output buffer, `NULL` to only measure * how large this buffer has to be * @param depth The type used of ramp stops * @return The number of marshalled bytes, or if `buf == NULL`, * how many bytes would be marshalled if `buf != NULL` */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__(1)))) size_t libcoopgamma_queried_filter_marshal(const libcoopgamma_queried_filter_t* restrict, void* restrict, libcoopgamma_depth_t); /** * Unmarshal a `libcoopgamma_queried_filter_t` from a buffer * * @param this The output parameter for unmarshalled record * @param buf The buffer with the marshalled record * @param n Output parameter for the number of unmarshalled bytes, undefined on failure * @param depth The type used of ramp stops * @return `LIBCOOPGAMMA_SUCCESS` (0), `LIBCOOPGAMMA_INCOMPATIBLE_DOWNGRADE`, * `LIBCOOPGAMMA_INCOMPATIBLE_UPGRADE`, or `LIBCOOPGAMMA_ERRNO_SET` */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__))) int libcoopgamma_queried_filter_unmarshal(libcoopgamma_queried_filter_t* restrict, const void* restrict, size_t* restrict, libcoopgamma_depth_t); /** * Initialise a `libcoopgamma_filter_table_t` * * @param this The record to initialise * @return Zero on success, -1 on error */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) int libcoopgamma_filter_table_initialise(libcoopgamma_filter_table_t* restrict); /** * Release all resources allocated to a `libcoopgamma_filter_table_t`, * the allocation of the record itself is not freed * * Always call this function after failed call to `libcoopgamma_filter_table_initialise` * or failed call to `libcoopgamma_filter_table_unmarshal` * * @param this The record to destroy */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__))) void libcoopgamma_filter_table_destroy(libcoopgamma_filter_table_t* restrict); /** * Marshal a `libcoopgamma_filter_table_t` into a buffer * * @param this The record to marshal * @param buf The output buffer, `NULL` to only measure * how large this buffer has to be * @return The number of marshalled bytes, or if `buf == NULL`, * how many bytes would be marshalled if `buf != NULL` */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__(1)))) size_t libcoopgamma_filter_table_marshal(const libcoopgamma_filter_table_t* restrict, void* restrict); /** * Unmarshal a `libcoopgamma_filter_table_t` from a buffer * * @param this The output parameter for unmarshalled record * @param buf The buffer with the marshalled record * @param n Output parameter for the number of unmarshalled bytes, undefined on failure * @return `LIBCOOPGAMMA_SUCCESS` (0), `LIBCOOPGAMMA_INCOMPATIBLE_DOWNGRADE`, * `LIBCOOPGAMMA_INCOMPATIBLE_UPGRADE`, or `LIBCOOPGAMMA_ERRNO_SET` */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__))) int libcoopgamma_filter_table_unmarshal(libcoopgamma_filter_table_t* restrict, const void* restrict, size_t* restrict); /** * Initialise a `libcoopgamma_error_t` * * @param this The record to initialise * @return Zero on success, -1 on error */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) int libcoopgamma_error_initialise(libcoopgamma_error_t* restrict); /** * Release all resources allocated to a `libcoopgamma_error_t`, * the allocation of the record itself is not freed * * Always call this function after failed call to `libcoopgamma_error_initialise` * or failed call to `libcoopgamma_error_unmarshal` * * @param this The record to destroy */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) void libcoopgamma_error_destroy(libcoopgamma_error_t* restrict); /** * Marshal a `libcoopgamma_error_t` into a buffer * * @param this The record to marshal * @param buf The output buffer, `NULL` to only measure * how large this buffer has to be * @return The number of marshalled bytes, or if `buf == NULL`, * how many bytes would be marshalled if `buf != NULL` */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__(1), __leaf__))) size_t libcoopgamma_error_marshal(const libcoopgamma_error_t* restrict, void* restrict); /** * Unmarshal a `libcoopgamma_error_t` from a buffer * * @param this The output parameter for unmarshalled record * @param buf The buffer with the marshalled record * @param n Output parameter for the number of unmarshalled bytes, undefined on failure * @return `LIBCOOPGAMMA_SUCCESS` (0), `LIBCOOPGAMMA_INCOMPATIBLE_DOWNGRADE`, * `LIBCOOPGAMMA_INCOMPATIBLE_UPGRADE`, or `LIBCOOPGAMMA_ERRNO_SET` */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) int libcoopgamma_error_unmarshal(libcoopgamma_error_t* restrict, const void* restrict, size_t* restrict); /** * Initialise a `libcoopgamma_context_t` * * @param this The record to initialise * @return Zero on success, -1 on error */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) int libcoopgamma_context_initialise(libcoopgamma_context_t* restrict); /** * Release all resources allocated to a `libcoopgamma_context_t`, * the allocation of the record itself is not freed * * Always call this function after failed call to `libcoopgamma_context_initialise` * or failed call to `libcoopgamma_context_unmarshal` * * @param this The record to destroy * @param disconnect Disconnect from the server? */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__))) void libcoopgamma_context_destroy(libcoopgamma_context_t* restrict, int); /** * Marshal a `libcoopgamma_context_t` into a buffer * * @param this The record to marshal * @param buf The output buffer, `NULL` to only measure * how large this buffer has to be * @return The number of marshalled bytes, or if `buf == NULL`, * how many bytes would be marshalled if `buf != NULL` */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__(1)))) size_t libcoopgamma_context_marshal(const libcoopgamma_context_t* restrict, void* restrict); /** * Unmarshal a `libcoopgamma_context_t` from a buffer * * @param this The output parameter for unmarshalled record * @param buf The buffer with the marshalled record * @param n Output parameter for the number of unmarshalled bytes, undefined on failure * @return `LIBCOOPGAMMA_SUCCESS` (0), `LIBCOOPGAMMA_INCOMPATIBLE_DOWNGRADE`, * `LIBCOOPGAMMA_INCOMPATIBLE_UPGRADE`, or `LIBCOOPGAMMA_ERRNO_SET` */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__))) int libcoopgamma_context_unmarshal(libcoopgamma_context_t* restrict, const void* restrict, size_t* restrict); /** * Initialise a `libcoopgamma_async_context_t` * * @param this The record to initialise * @return Zero on success, -1 on error */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) int libcoopgamma_async_context_initialise(libcoopgamma_async_context_t* restrict); /** * Release all resources allocated to a `libcoopgamma_async_context_t`, * the allocation of the record itself is not freed * * Always call this function after failed call to `libcoopgamma_async_context_initialise` * or failed call to `libcoopgamma_async_context_unmarshal` * * @param this The record to destroy */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) void libcoopgamma_async_context_destroy(libcoopgamma_async_context_t* restrict); /** * Marshal a `libcoopgamma_async_context_t` into a buffer * * @param this The record to marshal * @param buf The output buffer, `NULL` to only measure * how large this buffer has to be * @return The number of marshalled bytes, or if `buf == NULL`, * how many bytes would be marshalled if `buf != NULL` */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__(1), __leaf__))) size_t libcoopgamma_async_context_marshal(const libcoopgamma_async_context_t* restrict, void* restrict); /** * Unmarshal a `libcoopgamma_async_context_t` from a buffer * * @param this The output parameter for unmarshalled record * @param buf The buffer with the marshalled record * @param n Output parameter for the number of unmarshalled bytes, undefined on failure * @return `LIBCOOPGAMMA_SUCCESS` (0), `LIBCOOPGAMMA_INCOMPATIBLE_DOWNGRADE`, * `LIBCOOPGAMMA_INCOMPATIBLE_UPGRADE`, or `LIBCOOPGAMMA_ERRNO_SET` */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) int libcoopgamma_async_context_unmarshal(libcoopgamma_async_context_t* restrict, const void* restrict, size_t* restrict); /** * List all recognised adjustment method * * SIGCHLD must not be ignored or blocked * * @return A `NULL`-terminated list of names. You should only free * the outer pointer, inner pointers are subpointers of the * outer pointer and cannot be freed. `NULL` on error. */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__malloc__))) char** libcoopgamma_get_methods(void); /** * Get the adjustment method and site * * SIGCHLD must not be ignored or blocked * * @param method The adjustment method, `NULL` for automatic * @param site The site, `NULL` for automatic * @param methodp Output pointer for the selected adjustment method, * which cannot be `NULL`. It is safe to call * this function with this parameter set to `NULL`. * @param sitep Output pointer for the selected site, which will * be `NULL` the method only supports one site or if * `site == NULL` and no site can be selected * automatically. It is safe to call this function * with this parameter set to `NULL`. * @return Zero on success, -1 on error */ int libcoopgamma_get_method_and_site(const char* restrict, const char* restrict, char** restrict, char** restrict); /** * Get the PID file of the coopgamma server * * SIGCHLD must not be ignored or blocked * * @param method The adjustment method, `NULL` for automatic * @param site The site, `NULL` for automatic * @return The pathname of the server's PID file, `NULL` on error * or if there server does not use PID files. The later * case is detected by checking that `errno` is set to 0. */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__malloc__))) char* libcoopgamma_get_pid_file(const char* restrict, const char* restrict); /** * Get the socket file of the coopgamma server * * SIGCHLD must not be ignored or blocked * * @param method The adjustment method, `NULL` for automatic * @param site The site, `NULL` for automatic * @return The pathname of the server's socket, `NULL` on error * or if there server does have its own socket. The later * case is detected by checking that `errno` is set to 0, * and is the case when communicating with a server in a * multi-server display server like mds. */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__malloc__))) char* libcoopgamma_get_socket_file(const char* restrict, const char* restrict); /** * Connect to a coopgamma server, and start it if necessary * * Use `libcoopgamma_context_destroy` to disconnect * * SIGCHLD must not be ignored or blocked * * @param method The adjustment method, `NULL` for automatic * @param site The site, `NULL` for automatic * @param ctx The state of the library, must be initialised * @return Zero on success, -1 on error. On error, `errno` is set * to 0 if the server could not be initialised. */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__(3)))) int libcoopgamma_connect(const char* restrict, const char* restrict, libcoopgamma_context_t* restrict); /** * By default communication is blocking, this function * can be used to switch between blocking and nonblocking * * After setting the communication to nonblocking, * `libcoopgamma_flush`, `libcoopgamma_synchronise` and * and request-sending functions can fail with EAGAIN and * EWOULDBLOCK. It is safe to continue with `libcoopgamma_flush` * (for `libcoopgamma_flush` it selfand equest-sending functions) * or `libcoopgamma_synchronise` just like EINTR failure. * * @param ctx The state of the library, must be connected * @param nonblocking Nonblocking mode? * @return Zero on success, -1 on error */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) int libcoopgamma_set_nonblocking(libcoopgamma_context_t* restrict, int); /** * Send all pending outbound data * * If this function or another function that sends a request * to the server fails with EINTR, call this function to * complete the transfer. The `async` parameter will always * be in a properly configured state if a function fails * with EINTR. * * @param ctx The state of the library, must be connected * @return Zero on success, -1 on error */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) int libcoopgamma_flush(libcoopgamma_context_t* restrict); /** * Wait for the next message to be received * * @param ctx The state of the library, must be connected * @param pending Information for each pending request * @param n The number of elements in `pending` * @param selected The index of the element in `pending` which corresponds * to the first inbound message, note that this only means * that the message is not for any of the other request, * if the message is corrupt any of the listed requests can * be selected even if it is not for any of the requests. * Functions that parse the message will detect such corruption. * @return Zero on success, -1 on error, -2 if the message is ignored * which happens if corresponding `libcoopgamma_async_context_t` * is not listed. If `-1` is returned, `errno` will be set, * if it is set to `ENOTRECOVERABLE` you have receive a corrupt * message and the context has been tainted beyond recover. */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__, __leaf__))) int libcoopgamma_synchronise(libcoopgamma_context_t* restrict, libcoopgamma_async_context_t* restrict, size_t, size_t* restrict); /** * List all available CRTC:s, send request part * * Cannot be used before connecting to the server * * @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 */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__))) int libcoopgamma_get_crtcs_send(libcoopgamma_context_t* restrict, libcoopgamma_async_context_t* restrict); /** * List all available CRTC:s, receive response part * * @param ctx The state of the library, must be connected * @param async Information about the request * @return A `NULL`-terminated list of names. You should only free * the outer pointer, inner pointers are subpointers of the * outer pointer and cannot be freed. `NULL` on error, in * which case `ctx->error` (rather than `errno`) is read * for information about the error. */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__malloc__, __nonnull__))) char** libcoopgamma_get_crtcs_recv(libcoopgamma_context_t* restrict, libcoopgamma_async_context_t* restrict); /** * List all available CRTC:s, synchronous version * * This is a synchronous request function, as such, * you have to ensure that communication is blocking * (default), and that there are not asynchronous * requests waiting, it also means that EINTR:s are * silently ignored and there no wait to cancel the * operation without disconnection from the server * * @param ctx The state of the library, must be connected * @return A `NULL`-terminated list of names. You should only free * the outer pointer, inner pointers are subpointers of the * outer pointer and cannot be freed. `NULL` on error, in * which case `ctx->error` (rather than `errno`) is read * for information about the error. */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__malloc__, __nonnull__))) char** libcoopgamma_get_crtcs_sync(libcoopgamma_context_t* restrict); /** * Retrieve information about a CRTC:s gamma ramps, send request part * * Cannot be used before connecting to the server * * @param crtc The name of the CRTC * @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 */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__))) int libcoopgamma_get_gamma_info_send(const char* restrict, libcoopgamma_context_t* restrict, libcoopgamma_async_context_t* restrict); /** * 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 */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__))) int libcoopgamma_get_gamma_info_recv(libcoopgamma_crtc_info_t* restrict, libcoopgamma_context_t* restrict, libcoopgamma_async_context_t* restrict); /** * Retrieve information about a CRTC:s gamma ramps, synchronous version * * This is a synchronous request function, as such, * you have to ensure that communication is blocking * (default), and that there are not asynchronous * requests waiting, it also means that EINTR:s are * silently ignored and there no wait to cancel the * operation without disconnection from the server * * @param crtc The name of the CRTC * @param info Output parameter for the information, must be initialised * @param ctx The state of the library, must be connected * @return Zero on success, -1 on error, in which case `ctx->error` * (rather than `errno`) is read for information about the error */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__))) int libcoopgamma_get_gamma_info_sync(const char* restrict, libcoopgamma_crtc_info_t* restrict, libcoopgamma_context_t* restrict); /** * Retrieve the current gamma ramp adjustments, send request part * * Cannot be used before connecting to the server * * @param query The query to send * @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 */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__))) int libcoopgamma_get_gamma_send(libcoopgamma_filter_query_t* restrict, libcoopgamma_context_t* restrict, libcoopgamma_async_context_t* restrict); /** * Retrieve the current gamma ramp adjustments, receive response part * * @param table Output for the response, 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 */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__))) int libcoopgamma_get_gamma_recv(libcoopgamma_filter_table_t* restrict, libcoopgamma_context_t* restrict, libcoopgamma_async_context_t* restrict); /** * Retrieve the current gamma ramp adjustments, synchronous version * * This is a synchronous request function, as such, * you have to ensure that communication is blocking * (default), and that there are not asynchronous * requests waiting, it also means that EINTR:s are * silently ignored and there no wait to cancel the * operation without disconnection from the server * * @param query The query to send * @param table Output for the response, must be initialised * @param ctx The state of the library, must be connected * @return Zero on success, -1 on error, in which case `ctx->error` * (rather than `errno`) is read for information about the error */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__))) int libcoopgamma_get_gamma_sync(libcoopgamma_filter_query_t* restrict, libcoopgamma_filter_table_t* restrict, libcoopgamma_context_t* restrict); /** * 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 depth The datatype for the stops in the gamma ramps, 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 */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__))) int libcoopgamma_set_gamma_send(libcoopgamma_filter_t* restrict, libcoopgamma_depth_t, libcoopgamma_context_t* restrict, libcoopgamma_async_context_t* restrict); /** * Apply, update, or remove a gamma ramp adjustment, receive response part * * @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 */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__))) int libcoopgamma_set_gamma_recv(libcoopgamma_context_t* restrict, libcoopgamma_async_context_t* restrict); /** * Apply, update, or remove a gamma ramp adjustment, synchronous version * * This is a synchronous request function, as such, * you have to ensure that communication is blocking * (default), and that there are not asynchronous * requests waiting, it also means that EINTR:s are * silently ignored and there no wait to cancel the * operation without disconnection from the server * * @param filter The filter to apply, update, or remove, gamma ramp meta-data must match the CRTC's * @param depth The datatype for the stops in the gamma ramps, must match the CRTC's * @param ctx The state of the library, must be connected * @return Zero on success, -1 on error, in which case `ctx->error` * (rather than `errno`) is read for information about the error */ LIBCOOPGAMMA_GCC_ONLY(__attribute__((__nonnull__))) int libcoopgamma_set_gamma_sync(libcoopgamma_filter_t* restrict, libcoopgamma_depth_t, libcoopgamma_context_t* restrict); #if defined(__clang__) # pragma GCC diagnostic pop #endif #undef LIBCOOPGAMMA_GCC_ONLY #endif