aboutsummaryrefslogblamecommitdiffstats
path: root/src/libcoopgamma.h
blob: fb3b9c4d685495b96ab97ccec0d109246821b1f1 (plain) (tree)





















                                                                         
                   




                   




                                                 





                                                 

 
   
                           

                                 






                                                     

                                     






                                                         

                                     




                                                             


                                                    












































                                               
                                         



































                                                    






                                                   


   


                                      

                                 

                                        

                                
     
                      


                             


                                
     
                         


                                    

                                
     
                      
  


                         


                                     



                                       
   

                               


              
                         



               
                           



               
                           



               
                           



            
                          



             
                          
  


                       



                                    

                                  

                          

                                
     
                          




                                         
                               




                                   
                                
  


                          





                                                                 


                                                 


                                                 
                                                 



                                                 
                                                 



                                                 
                                                 



                                                 
                                                 



                                                 
                                                 



                                                 
                                                 
                                                 
                                





                                                             
                                 





                                                               
                                   





                                                               
                                   





                                                               
                                   





                                                             
                               





                                                             
                                

 
   





































                                              


                                             

                                  
     



                                                  
                   



                                                    
             





                                                                   
              






                                                     
                                   

     




                                                  

                                             
                             
  


                        


                                         

                                     
     
                                         
     
                  



                                                  
                             

     










                                                  

                                        
                  



                                          
                    



                                         
                   
  


                           




                                    

                                        
     











                                     


                                       
             




                                    
               
  


                       
  


                              




                                                 

                                          


                          
                   



                       
              



                                             
                             
  


                                




                                               

                                        
     

                                        
                  



                                          
                    



                                         
                   



                          
                      










                                                  
                                         
  








                                                  


                              


                                      

                                 
     
               


                                         
                                    
     
                  



                            
             

     




                                            


                                    
                    
  


                       

                



                                            



                                   






                                                            



                                   

                                       
     

                                            
     










                                                  
  




                                   
     






                                                     






































                                      





                                    





                                                


                         





                                         

                                 





                                             





                                    


                               
 



                                                                                            

                                                                                  



                                              
                                                                  











                                                                                              
                                                                      




                                                                                              
                                                              





                                                                                             
                                                                             





                                                                                            

                                                                                  
                                           
                                             

                                               
                                                             
                                                           


                                                                                           


                                                                                   



                                                                                 
                                      
   
                                                             












                                                                                              
                                                                
                                                                                 




                                                                                              
                                                               





                                                                                              
                                                             
                                                                                                  







                                              
                                                             








                                                                                  
                                      
   
                                                             










                                                                      
                                                      




                                                                                          
                                                              




                                                                                             
                                                   
                                                                                                           







                                              
                                                             








                                                                                     
                                      
   
                                                             










                                                                        
                                                                




                                                                                                
                                                              




                                                                                             
                                                             

                                                                             







                                              
                                                             








                                                                                        
                                      
   
                                                             










                                                                              
                                                                




                                                                                                      
                                                              




                                                                                             
                                                             

                                                                                







                                               
                                                             








                                                                                          
                                      
   
                                                   




                                                                                  





                                                                       
   
                                                      

                                                                                                         



                                                            
                                                               




                                                                                              
   
                                                   

                                                                                                        







                                              
                                                             








                                                                                        
                                      
   
                                                   










                                                                              
                                                      




                                                                                                      
                                                              




                                                                                             
                                                   

                                                                                







                                              
                                                             








                                                                                 
                                      
   
                                                             










                                                                      
                                                                




                                                                                        
                                                              




                                                                                             
                                                             
                                                                                                         







                                              
                                                             








                                                                                   

                                                  
   
                                                   










                                                                         
                                                      




                                                                                            
                                                              




                                                                                             
                                                   
                                                                                                             

 
   




                                              
                                                             










                                                                                         
                                                             










                                                                                
                                                                




                                                                                                        
                                                              




                                                                                             
                                                             




                                                                                                      

                                        

                                         



                                                                    
                                                  




                                      

                                         

















                                                                                

                                         





                                                                           
                                                  




                                                                            

                                         







                                                                           
                                                  







                                                                               

                                         





                                                                          
                                                      


                                                                                                       


                                                         






                                                                 



                                                                    
                                                             


                                                                        







                                                            
                                                            

                                             
                                                             


                                                         












                                                                                   


                                                                                  
   
                                                             




                                                                                                      
                                               


                                                 



                                                                   
   
                                                   
                                                                                                          

   
                                                   
   







                                                                           
                                                               


                                                                                                             















                                                                         
                                                               



                                                                     
                                                                     
   







                                                                   
                                                   
                                                                                            









                                                                                
   
                                                   

                                                                                                          

   














                                                                                
                                                   




                                                                                              
                                                                 
   
                                                 
   
                                    




                                                                   
                                                   





                                                                                                        

                                                               
                                                

                                                                                
   
                                                   

                                                                                                        

   














                                                                                
                                                   




                                                                                                             


                                                                      
   

                                                                                                      
                                                               



                                                                    
                                                   


                                                                                                          



                                                                          
                                                

                                                                                
   
                                                   
                                                                                                          
 















                                                                                                      
                                                   


                                                                                      
 
 



                           

                            

 

      
/**
 * 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 <http://www.gnu.org/licenses/>.
 */
#ifndef LIBCOOPGAMMA_H
#define LIBCOOPGAMMA_H



#include <limits.h>
#include <stddef.h>
#include <stdint.h>



#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