@node API
@chapter API
@menu
* Adjustment methods:: Selecting adjustment method.
* Monitors:: Selecting monitors.
* Adjustment method capabilities:: Identifying capabilities of adjustment methods.
* CRTC information:: Retrieving information about CRTC:s.
* Gamma ramps:: Fetch and manipulating gamma ramps.
* Errors:: Error codes and how to handle errors.
@end menu
To use @command{libgamma} add ``@code{#include <libgamma.h>}''
to and C file or C header file that requires anything
from @command{libgamma}. @file{libgamma.h} is the only
header file from @command{libgamma} which should be
included directly.
Once @file{libgamma.h} is included your program will
have access the @command{libgamma}'s API which includes
functions, data structures, error codes, and adjustment
method identifers.
It is highly recommened to add a check for new error
codes if your program will be using error codes from
@command{libgamma}. This allows you to get a notification
if you program is not up to date with new error codes
in @command{libgamma}. To do this, @file{libgamma.h}
provides the C preprocessor definition @code{LIBGAMMA_ERROR_MIN};
this is the lowest value of that any error code has,
all error codes are negative, a new error code is added
it will have a lower value that the ones added before it.
The first step in adding this check is to figure out
what the value of @code{LIBGAMMA_ERROR_MIN} is on your
system. To do this, use the @command{cpp} program, it
should be included with your C compiler.
@example
cpp <<EOF | tail --lines 1
#include <libgamma.h>
LIBGAMMA_ERROR_MIN
EOF
@end example
The next step is to add some C preprocessor directives
to one of your C files that includes @file{libgamma.h}.
@example
#if LIBGAMMA_ERROR_MIN < -10
# warning New error codes have been added to libgamma.
#endif
@end example
In this example, we assume that output of the first
step was `-10', which it really was not. So if you
use this in your program you should receive a warning
until you update the value.
In a similar manner, you should all a check to detect
when the value of either @code{GAMMA_METHOD_MAX} or
@code{GAMMA_METHOD_COUNT} (the latter will have value
of one higher than the earlier) have increased. This
will allow you to get a warning for when new adjustment
method have been added so you can take appropriate
actions if required. @command{libgamma} does not only
provide display server abstract, it optionally lets you
choose any available method you want despite of what
display server you are used.
You may also want to add checks for update to
@code{LIBGAMMA_CONNECTOR_TYPE_COUNT},
@code{LIBGAMMA_SUBPIXEL_ORDER_COUNT} and
@code{LIBGAMMA_CRTC_INFO_COUNT}.
@node Adjustment methods
@section Adjustment methods
@command{libgamma} is an abstraction layer that
lets you select which display server and protocol
--- together called adjustment method --- it
should use to work with the monitors' gamma
ramps. Supported adjustment method, even if
excluded at compile-time are identfier by numerical
values.
@table @code
%>for method in $(libgamma-method-extract --list --method); do
@item %{method}
%>libgamma-method-extract --method $method | texise
%>done
@end table
You can test whether an adjustment method
is available with the function
@code{libgamma_is_method_available}. It
takes the adjustment method's identifer
as its only argument, and returns an
@code{int}. The returned value is non-zero
if and only if the adjustment exists and
is available.
A more flexible more but advanced function,
that you probably want to use instead, is
@code{libgamma_list_methods}. It lists all
List available adjustment methods by their
order of preference based on the environment,
and can filter its output. This function
takes three arguments:
@table @asis
@item @code{methods} [@code{int*}]
Output array of adjustment method
identifiers. It should be able to hold
@code{LIBGAMMA_METHOD_COUNT} elements.
@item @code{buf_size} [@code{size_t}]
The number of elements that fits in
@code{methods}, it should be
@code{LIBGAMMA_METHOD_COUNT},
This is used to avoid writing outside
the output buffer if this library
adds new adjustment methods without
the users of the library recompiling.
@item @code{operation} [@code{int}]
Describes what adjustment methods to
include. There are five valid values
for this parameter, all other values
invoke undefined behaviour.
@table @code
@item 0
Adjustment methods that the environment
suggests will work, excluding fake
Adjustment methods.
@item 1
Adjustment methods that the environment
suggests will work, including fake
Adjustment methods.
@item 2
All real non-fake adjustment methods.
@item 3
All real adjustment methods.
@item 4
All adjustment methods.
@end table
@end table
@code{libgamma_list_methods} returns an
@code{size_t} with the value of how many
adjustment method that should have been
stored in the parameter @code{methods}
if were @code{buf_size}. This value is
how many value that have been stored
in @code{methods} if @code{buf_size}
is large enough.
@node Monitors
@section Monitors
@menu
* Site:: Display sites.
* Partition:: Display partitions.
* CRTC:: Display outputs.
@end menu
@command{libgamma} have a three level hierarchy for addressing
monitors. These levels are:
@table @asis
@item Sites
%>libgamma-method-extract --doc --site-t | behead 2 | texise
@item Partitions
%>libgamma-method-extract --doc --part-t | behead 2 | texise
@item CRTC:s (cathode ray tube controllers) @footnote{Do not be fooled by the legacy name, they are general video controllers.}
%>libgamma-method-extract --doc --crtc-t | behead 2 | texise
@end table
@command{libgamma} keeps tracks of these layers' states,
because of this there are one state data structure per
layer that also identifies the instance of the layer.
@node Site
@subsection Site
The state and identity of the site is track by
the data structure @code{libgamma_site_state_t}
@footnote{@code{struct libgamma_site_state}}.
This structure contains the following variables:
@table @asis
%>for site in $(libgamma-method-extract --list --site-t); do
@item @code{%{site}} [@code{%(libgamma-method-extract --type --site-t $site)}]
%>libgamma-method-extract --site-t $site | texise | sed -e 's/"/``/1' | sed -e 's/"/'\'\''/'
%>done
@end table
To select a site and initialise its state
call the function @code{libgamma_site_initialise}.
It returns zero on success, and and negative
@code{int} on failure. If the return is negative,
it is a @code{libgamma} error code; these are
listed in @ref{Errors}. For input
@code{libgamma_site_initialise} takes three
arguments:
@table @asis
@item @code{this} [@code{libgamma_site_state_t*}]
The site state to initialise.
@item @code{method} [@code{int}]
The adjustment method (display server and protocol),
these are listed in @ref{Adjustment methods}.
@item @code{site} [@code{char*}]
The site identifier, unless it is @code{NULL}
it must a @code{free}:able. Once the state is
destroyed the library will attempt to free it.
There you should not free it yourself, and it
must not be a string constant or allocated on
the stack. Note however that it will not be
@code{free}:d if this function fails.
The name of the default site can be fetched
with the function @code{libgamma_method_default_site}.
It takes the value of @code{method} as its only
argument and returns the default site's name.
The returned value may be @code{NULL}, and
the value should not be @code{free}:d. Because
it should not be @code{free}:d you should
duplicate it with @code{strdup} if it is not
@code{NULL}. This value is @code{NULL} if
the default site cannot be determined or if
the adjustment method only supports one site.
The function @code{libgamma_method_default_site_variable}
works identically is @code{libgamma_method_default_site}
except it returns the name of the environment
variable that is read by @code{libgamma_method_default_site}
to determine the default site for the adjustment
method.
@end table
To release all resources held by a site state,
call the function @code{libgamma_site_destroy},
whose only parameter is the site state to
destroy. It does not return any value, and is
always successful assuming that the site is
valid and properly initialised. If you also
want to free the allocation for the site state
itself call the function @code{libgamma_site_free}
instead. These two functions are identical
with the exception that the latter also
performs a @code{free} call for the state.
@node Partition
@subsection Partition
The state and identity of the partition is track by
the data structure @code{libgamma_partition_state_t}
@footnote{@code{struct libgamma_partition_state}}.
This structure contains the following variables:
@table @asis
%>for part in $(libgamma-method-extract --list --part-t); do
@item @code{%{part}} [@code{%(libgamma-method-extract --type --part-t $part)}]
%>libgamma-method-extract --part-t $part | texise
%>done
@end table
To select a partition and initialise its state
call the function @code{libgamma_partition_initialise}.
It returns zero on success, and and negative
@code{int} on failure. If the return is negative,
it is a @code{libgamma} error code; these are
listed in @ref{Errors}. For input
@code{libgamma_partition_initialise} takes three
arguments:
@table @asis
@item @code{this} [@code{libgamma_partition_state_t*}]
The partition state to initialise.
@item @code{site} [@code{libgamma_site_state_t*}]
The site state for the site that the
partition belongs to.
@item @code{partition} [@code{size_t}]
The the index of the partition within the site.
@end table
To release all resources held by a partition state,
call the function @code{libgamma_partition_destroy},
whose only parameter is the partition state to
destroy. It does not return any value, and is
always successful assuming that the partition is
valid and properly initialised. If you also
want to free the allocation for the partition state
itself call the function @code{libgamma_partition_free}
instead. These two functions are identical
with the exception that the latter also
performs a @code{free} call for the state.
@node CRTC
@subsection CRTC
The state and identity of the partition is track
by the data structure @code{libgamma_crtc_state_t}
@footnote{@code{struct libgamma_crtc_state}}.
This structure contains the following variables:
@table @asis
%>for crtc in $(libgamma-method-extract --list --crtc-t); do
@item @code{%{crtc}} [@code{%(libgamma-method-extract --type --crtc-t crtc)}]
%>libgamma-method-extract --crtc-t $crtc | texise
%>done
@end table
To select a CRTC and initialise its state
call the function @code{libgamma_crtc_initialise}.
It returns zero on success, and and negative
@code{int} on failure. If the return is negative,
it is a @code{libgamma} error code; these are
listed in @ref{Errors}. For input
@code{libgamma_crtc_initialise} takes three
arguments:
@table @asis
@item @code{this} [@code{libgamma_crtc_state_t*}]
The CRTC state to initialise.
@item @code{partition} [@code{libgamma_partition_state_t*}]
The partition state for the
partition that the CRTC belongs to.
@item @code{crtc} [@code{size_t}]
The the index of the CRTC within
the partition. Be aware that adjustment
methods do not necessarily order than
CRTC:s in the same way. For example,
display environment may order the
CRTC:s so that the primary monitors
has the CRTC with index 0; but cannot
be done if there is no concept of
primary monitors, such as the case
of the Linux TTY and the Linux Direct
Rendering Manager adjustment method.
@end table
To release all resources held by a CRTC state,
call the function @code{libgamma_crtc_destroy},
whose only parameter is the CRTC state to
destroy. It does not return any value, and is
always successful assuming that the CRTC is
valid and properly initialised. If you also
want to free the allocation for the CRTC state
itself call the function @code{libgamma_crtc_free}
instead. These two functions are identical
with the exception that the latter also
performs a @code{free} call for the state.
@node Adjustment method capabilities
@section Adjustment method capabilities
Adjustment methods have different
capabilities. Because of this, you
will probably want to know at least
some this the capabilities of the
adjustment method that you are using.
This can be used to filter out
unimportant information for the user.
The function @code{libgamma_method_capabilities},
which does not return anything, can be
used to get an adjustment methods capabilities.
This function takes two arguments. The first
argument is a @code{libgamma_method_capabilities_t*}
that will be filled with this information, and
the second argument is an @code{int} whose
value should be the adjument method's identifier.
@code{libgamma_method_capabilities_t}
@footnote{@code{struct libgamma_method_capabilities}} is
a data structure with the following variables:
@table @asis
%>for cap in $(libgamma-method-extract --list --cap-t); do
@item @code{%{cap}} [@code{%(libgamma-method-extract --type --cap-t $cap)}]
%>libgamma-method-extract --cap-t $cap | texise
%>if [ $cap = crtc_information ]; then
See @ref{CRTC information} for more information.
%>fi
%>done
@end table
@node CRTC information
@section CRTC information
It is possible query information about a CRTC
using the function @code{libgamma_get_crtc_information}.
This function returns an @code{int} whose value
is zero on success and @code{-1} if at least on
of the requested informations about the CRTC
could not successfully be read. This function
takes three arguments:
@table @asis
@item @code{this} [@code{libgamma_crtc_information_t*}]
Instance of a data structure to fill with the
information about the CRTC.
@item @code{crtc} [@code{libgamma_crtc_state_t*}]
The state of the CRTC whose information should be read.
@item @code{fields} [@code{int32_t}]
OR:ed identifiers for the information about
the CRTC that should be read.
@end table
The valid values that can be OR:ed for the
@code{fields} parameters are:
@table @code
%>for info in $(libgamma-method-extract --list --info); do
@item %{info}
%>libgamma-method-extract --info $info | texise
%>done
@end table
@code{libgamma_crtc_information_t}
@footnote{@code{struct libgamma_crtc_information}},
which is the data structure that the read
information is stored in, contains the following
variables:
@table @asis
%>for info in $(libgamma-method-extract --list --info-t); do
@item @code{%{info}} [@code{%(libgamma-method-extract --type --info-t $info)}]
%>libgamma-method-extract --info-t $info | texise
%>done
@end table
The data type for the variable @code{subpixel_order}
is @code{libgamma_subpixel_order_t}
@footnote{@code{enum libgamma_subpixel_order}}.
Its possible values are:
@table @code
%>for order in $(libgamma-method-extract --list --subpixel); do
@item %{order}
%>libgamma-method-extract --subpixel $order | texise
%>done
@end table
The data type for the variable @code{connector_type}
is @code{libgamma_connector_type_t}
@footnote{@code{enum libgamma_connector_type}}.
Its possible values are:
@table @code
%>for type in $(libgamma-method-extract --list --connector); do
@item %{type}
%>libgamma-method-extract --connector $type | texise
%>done
@end table
The variable @code{edid} is in raw format.
To convert it to a human-readable format
you should convert it to hexadecimal
representation. To do this, you can call
either of the functions
@table @code
@item libgamma_behex_edid
@itemx libgamma_behex_edid_lowercase
Converts to lowercase hexadecimal.
@item libgamma_behex_edid_uppercase
Converts to uppercase hexadecimal.
@end table
These functions return the EDID as
a hexadecimal NUL-terminated
non-@code{NULL} string of the data
type @code{char*}, which you should
free when you do not need it anymore.
If enough memory cannot be allocated
@code{NULL} is returned and
@code{errno} is set accordingly.
These functions take two arguments:
@table @asis
@item @code{edid} [@code{const unsigned char*}]
The EDID in raw representation.
@item @code{length} [@code{size_t}]
The length of @code{edid}.
@end table
The values of these arguments should
be the values of the variables
@code{edid} and @code{edid_length},
respectively.
If you want to identify a monitor by
it's EDID@footnote{EDID:s should be
unique and even if the manufacture
for the monitor has not made sure if
this it is very unlikely that it is
not.} it is more effective to convert
the EDID you want to raw format and
compare the raw format rather than
converting all monitors EDID to
hexadecimal representation. To do
this use the function
@code{libgamma_unhex_edid}. This
function takes the EDID in NUL-terminated
non-@code{NULL} hexadecimal
representation as a @code{const char*}
as its only argument. The function
returns the EDID in raw format as an
@code{unsigned char*}. The returned
value will be @code{NULL} if enough
memory for the output cannot be allocated
or if the input is a hexadecimal
representation of a byte array;
@code{errno} will be set accordingly.
To release resources that are held by a
@code{libgamma_crtc_information_t*}
whose variables have been set by
@code{libgamma_get_crtc_information}
call the function @code{libgamma_crtc_information_destroy}
with that @code{libgamma_crtc_information_t}
as its only argument. If you also
want to release the allocation if the
@code{libgamma_crtc_information_t*}
itself call the function
@code{libgamma_crtc_information_free} instead.
@node Gamma ramps
@section Gamma ramps
@command{libgamma} has support for 5
different gamma ramps structures:
16-bit depth, 32-bit depth, 64-bit
depth, single precision floating point,
and double precision floating point.
For best performance, you should
select the one that the adjustment
method uses. If you choose a type
other than what the adjustment
method uses, it will be converted.
@table @asis
@item @code{libgamma_gamma_ramps8_t} (@code{struct libgamma_gamma_ramps8})
8-bit integer (@code{uint8_t}).
Currently no adjustment method.
@item @code{libgamma_gamma_ramps16_t} (@code{struct libgamma_gamma_ramps16})
16-bit integer (@code{uint16_t}).
This is by far the most common.
@item @code{libgamma_gamma_ramps32_t} (@code{struct libgamma_gamma_ramps32})
32-bit integer (@code{uint32_t}).
Currently no adjustment method.
@item @code{libgamma_gamma_ramps64_t} (@code{struct libgamma_gamma_ramps64})
64-bit integer (@code{uint64_t}).
Currently no adjustment method.
@item @code{libgamma_gamma_rampsf_t} (@code{struct libgamma_gamma_rampsf})
Single precision floating point (@code{float}).
Currently this is only used by the
Quartz/CoreGraphics adjustment method.
@item @code{libgamma_gamma_rampsd_t} (@code{struct libgamma_gamma_rampsd})
Double precision floating point (@code{double}).
Currently no adjustment method.
@end table
These structures are very similar.
They have three ramps, one per channels,
each have an array that is a lookup
table with one associated variable that
describes the size of the table. They
only differ in the element type of the
arrays --- @code{red}, @code{green} and
@code{blue} --- whose type is specified
in the table above. @code{red}, @code{green}
and @code{blue} is a pointer of that type.
For example, for @code{libgamma_gamma_ramps16_t}
@code{red}, @code{green} and @code{blue}
are of type @code{uint16_t*} since the
element type is @code{uint16_t}.
@table @asis
@item @code{red_size} [@code{size_t}]
The number of stops in @code{red}.
@item @code{green_size} [@code{size_t}]
The number of stops in @code{green}.
@item @code{blue_size} [@code{size_t}]
The number of stops in @code{blue}.
@item @code{red}
The lookup table for the red channel.
@item @code{green}
The lookup table for the green channel.
@item @code{blue}
The lookup table for the blue channel.
@end table
Because of how the adjustment method's
own API's are designed @code{red},
@code{green} and @code{blue} should
actually one array. To make sure that
this is done the right way and to reduce
you own code @code{libgamma} provides
functions to create and destroy gamma
ramp structures.
@table @asis
@item @code{libgamma_gamma_ramps8_initialise} [@code{int *(libgamma_gamma_ramps8_t*)}]
@itemx @code{libgamma_gamma_ramps16_initialise} [@code{int *(libgamma_gamma_ramps16_t*)}]
@itemx @code{libgamma_gamma_ramps32_initialise} [@code{int *(libgamma_gamma_ramps32_t*)}]
@itemx @code{libgamma_gamma_ramps64_initialise} [@code{int *(libgamma_gamma_ramps64_t*)}]
@itemx @code{libgamma_gamma_rampsf_initialise} [@code{int *(libgamma_gamma_rampsf_t*)}]
@itemx @code{libgamma_gamma_rampsd_initialise} [@code{int *(libgamma_gamma_rampsd_t*)}]
Initialise a gamma ramp in the proper way
that allows all adjustment methods to read
from and write to it without causing
segmentation violation.
The input must have @code{red_size},
@code{green_size} and @code{blue_size}
set to the sizes of the gamma ramps
that should be allocated.
Zero is returned on success. On error
@code{-1} is returned and @code{errno}
is set accordingly. These functions can
only fail on @code{malloc} error.
@item @code{libgamma_gamma_ramps8_destroy} [@code{void *(libgamma_gamma_ramps8_t*)}]
@itemx @code{libgamma_gamma_ramps16_destroy} [@code{void *(libgamma_gamma_ramps16_t*)}]
@itemx @code{libgamma_gamma_ramps32_destroy} [@code{void *(libgamma_gamma_ramps32_t*)}]
@itemx @code{libgamma_gamma_ramps64_destroy} [@code{void *(libgamma_gamma_ramps64_t*)}]
@itemx @code{libgamma_gamma_rampsf_destroy} [@code{void *(libgamma_gamma_rampsf_t*)}]
@itemx @code{libgamma_gamma_rampsd_destroy} [@code{void *(libgamma_gamma_rampsd_t*)}]
Release resources that are held by a gamma
ramp structure that has been allocated by
@code{libgamma_gamma_ramps_initialise} or
otherwise initialises in the proper manner.
@item @code{libgamma_gamma_ramps8_free} [@code{void *(libgamma_gamma_ramps8_t*)}]
@itemx @code{libgamma_gamma_ramps16_free} [@code{void *(libgamma_gamma_ramps16_t*)}]
@itemx @code{libgamma_gamma_ramps32_free} [@code{void *(libgamma_gamma_ramps32_t*)}]
@itemx @code{libgamma_gamma_ramps64_free} [@code{void *(libgamma_gamma_ramps64_t*)}]
@itemx @code{libgamma_gamma_rampsf_free} [@code{void *(libgamma_gamma_rampsf_t*)}]
@itemx @code{libgamma_gamma_rampsd_free} [@code{void *(libgamma_gamma_rampsd_t*)}]
Release resources that are held by a gamma
ramp structure that has been allocated by
@code{libgamma_gamma_ramps*_initialise} or
otherwise initialises in the proper manner,
as well as release the pointer to the
structure.
@end table
To read the current gamma ramps for a
CRTC, you can use the function
@code{libgamma_crtc_get_gamma_ramps16}.
This function returns zero on success,
and a negative @code{int} on failure.
If the function fails, the return
value will be one of the error codes
listed in @ref{Errors}. The function
takes two arguments: the
@code{libgamma_crtc_state_t*}
for the CRTC, and a
@code{libgamma_gamma_rampsd_t*}
that will be filled with the
current gamma ramps, it must
have been initialise by
@code{libgamma_gamma_ramps16_initialise}
or in a compatible manner.
Similarly you can use
@code{libgamma_crtc_set_gamma_ramps16}
to apply gamma ramps to a CRTC.
This function has the same return
value and the same first argument
as @code{libgamma_crtc_get_gamma_ramps16},
but its second argument is a
@code{libgamma_gamma_rampsd_t}
rather than a
@code{libgamma_gamma_rampsd_t*}.
Alternatively, but with some
performance impact, you can use
the function
@code{libgamma_crtc_set_gamma_ramps16_f}.
The difference between
@code{libgamma_crtc_set_gamma_ramps16_f}
and @code{libgamma_crtc_set_gamma_ramps16}
is that the second argument is
substitute for three separate argument
that are used to generate the gamma ramps:
@table @asis
@item @code{red_function} [@code{libgamma_gamma_ramps16_fun*}]
The function that generates the the
gamma ramp for the red channel.
@item @code{green_function} [@code{libgamma_gamma_ramps16_fun*}]
The function that generates the the
gamma ramp for the green channel.
@item @code{blue_function} [@code{libgamma_gamma_ramps16_fun*}]
The function that generates the the
gamma ramp for the blue channel.
@end table
@code{libgamma_gamma_ramps16_fun} is a
@code{typedef} of @code{uint16_t (float encoding)}.
As input, it takes a [0, 1] float of
the encoding value and as output
it should return the output value.
These functions for reading and applying
gamma ramps are for @code{uint16_t} element
type gamma ramps. But it is possible
to use other element types as well:
@table @code
@item uint8_t
Substitute all @code{ramps16} for @code{ramps8}
in the the function names and date type
definition names.
@item uint32_t
Substitute all @code{ramps16} for @code{ramps32}
in the the function names and date type
definition names.
@item uint64_t
Substitute all @code{ramps16} for @code{ramps64}
in the the function names and date type
definition names.
@item float
Substitute all @code{ramps16} for @code{rampsf}
in the the function names and date type
definition names.
@item double
Substitute all @code{ramps16} for @code{rampsd}
in the the function names and date type
definition names.
@end table
@node Errors
@section Errors
Many @command{libgamma} functions will return
@command{libgamma} specific error codes rather
than setting @code{errno} and return @code{-1}.
However @code{errno} may have been set, but
should in such case be ignored unless
@code{LIBGAMMA_ERRNO_SET} has been returned.
Other functions do set @code{errno} and return
@code{-1}. Other functions may store the error
code. In this case @code{LIBGAMMA_ERRNO_SET}
cannot be stored but the value that @code{errno}
had when an error occured can be stored instead
of a @command{libgamma} specific error codes.
@code{errno} values are allows positive whereas
@command{libgamma} specific error codes are
allows negative. On success zero is returned
or stored.
If @code{LIBGAMMA_DEVICE_REQUIRE_GROUP} is returned
the ID of the required group is stored in
@code{libgamma_group_gid} and the name of that
group is stored in @code{libgamma_group_name}.
@code{NULL} is stored if the name of the group
cannto be determined. @file{libgamma.h} give
you access to these variables, they are defined
as @code{gid_t} (@code{short int} for Windows)
and @code{const char*} types respectively.
Additionally, except on Windows, these use thread
local storage, defined with the @code{__thread}
qualifier.
@command{libgamma} defines the following error codes
that its functions may return:
@table @code
%>for err in $(libgamma-error-extract --list | sort); do
@item %{err}
%>libgamma-error-extract $err | texise
%>done
@end table
The function @code{libgamma_name_of_error} can
be used to return the name of an libgamma error.
For example @code{libgamma_name_of_error(LIBGAMMA_ERRNO_SET)}
will return the string ``LIBGAMMA_ERRNO_SET''.
Similarly @code{libgamma_value_of_error("LIBGAMMA_ERRNO_SET")}
will return the value of @code{LIBGAMMA_ERRNO_SET}.
The value returned from @code{libgamma_name_of_error}
shall not be @code{free}:d. @code{NULL} is returned
if the value does nto refer to a @command{libgamma}
error. @code{libgamma_value_of_error} will return zero
if the input is @code{NULL} or string that is not the
name of a @command{libgamma} error.
The function @code{libgamma_perror} can be used to
print an error to stderr in a @code{perror} fashion.
However @code{libgamma_perror} will not translate the
@command{libgamma} errors into human-readable strings,
it will simply print the name of the error.
@code{libgamma_perror} takes two arguments:
a @code{const char*} that work like the parameter for
@code{perror}, and an @code{int} with the error code.
If the error code is the value of @code{LIBGAMMA_ERRNO_SET}
@code{perror} will be used to print the current error
stored in @code{errno}. If the error code is non-negative
(an @code{errno} value), that value will be stored in
@code{errno} and @code{perror} will be used to print it.
Additionally, if the error code is the value of
@code{LIBGAMMA_DEVICE_REQUIRE_GROUP} the required group
will be printed with its numerical value and, if known,
its name.