\input texinfo   @c -*-texinfo-*-

@c %**start of header
@setfilename blueshift.info
@settitle blueshift
@afourpaper
@documentencoding UTF-8
@documentlanguage en
@finalout
@c %**end of header


@dircategory Ergonomy
@direntry
* blueshift: (blueshift).            Automatically adjust the colour temperature
@end direntry


@copying
Copyright @copyright{} 2014 Mattias Andrée

@quotation
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with no
Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
Texts. A copy of the license is included in the section entitled
``GNU Free Documentation License''.
@end quotation
@end copying

@ifnottex
@node Top
@top blueshift -- Automatically adjust the colour temperature
@insertcopying
@end ifnottex

@titlepage
@title blueshift
@c @subtitle Automatically adjust the colour temperature
@subtitle The grand unified dynamic colour adjustment framework
@author by Mattias Andrée (maandree)

@page
@vskip 0pt plus 1filll
@insertcopying
@end titlepage

@contents



@menu
* Overview::                        Brief overview of @command{blueshift}.
* Invoking::                        Invocation of @command{blueshift}.
* Signals::                         Signals handled by @command{blueshift}.
* Configuration API::               How to write configuration files.
* Related software::                Software related to @command{blueshift}.
* Terminology::                     Related terminology.
* GNU Free Documentation License::  Copying and sharing this manual.
@end menu



@node Overview
@chapter Overview

Inspired by Redshift, Blueshift adjusts the colour
temperature of your monitor according to brightness
outside to reduce eye strain and make it easier to
fall asleep when going to bed. It can also be used
to increase the colour temperature and make the
monitor bluer, this helps you focus on your work.

Blueshift is not user friendly and it is not
meant to be. Blueshift does offer limited
use of command line options to apply settings,
but it is really meant for you to have configuration
files (written in Python 3) where all the policies
are implemented, Blueshift is only meant to provide
the mechanism for modifying the colour curves.
Blueshift neither provides any means of automatically
getting your geographical position; the intention is
that you should implement that in the policy yourself
using library which can do that. Additionally
Blueshift provides not safe guards from making your
screen unreadable or otherwise miscoloured; and
Blueshift will never, officially, add support
specifically for any proprietary operating system.
Blueshift is fully extensible so it is possible to
make extensions that make it usable under unsupported
systems, the base code is written in Python 3 without
calls to any system dependent functions.
If Blueshift does not work for you for any of these
reasons, you should take a look at Redshift.



@node Invoking
@chapter Invoking

Blueshift uses argparser to read options from the
commnad line. It inherits a few properaties from this:
abbreviations are supported, you only need to type the
beginning of the long options so that the rest can
be filled in unambiguously by the program; @option{--}
can be used, as usual, to make all following options
being parsed as just arguments; and @option{++} works
like @option{--}, except it only allied to the next
option. Any argument that is not parsed as an option
for Blueshift is passed onto the configuration script.

Blueshift recognises the following options:

@table @option
@item -c
@itemx --configurations FILE
Select configuration script. This defaults to the
first file of the following the exists:
@itemize @bullet
@item @file{$XDG_CONFIG_HOME/blueshift/blueshiftrc}
@item @file{$HOME/.config/blueshift/blueshiftrc}
@item @file{$HOME/.blueshiftrc}
@item @file{/etc/blueshiftrc}
@end itemize
Blueshift does not check the user home, rather it
checks @env{HOME} which should be the user home, unless
you change it yourself.

You update the configuration file you can send a
SIGUSR1 signal to reload it.

@item -p @c the long name of option is inspired from openntpd
@itemx --panic-gate
@itemx --panicgate
Applies the settings directly instead of transitioning
into the initial settings. There is not option for doing
this when the program exists. But you press @kbd{Control+c}
twice, or send SIGTERM twice, to skip transition into
default settings.

@item -h
@itemx -?
@itemx --help
Prints help information.

@item -C
@itemx --copying
@itemx --copyright
Prints copyright information.

@item -W
@itemx --warranty
Prints non-warranty information,
included in the copyright information.

@item -v
@itemx --version
Prints the name of the program and the
installed version of the program
@end table

Blueshift also supports a few options
for ad-hoc settings. These are ignored
(unless fetched by the configuration file)
if @option{-c} (@option{--configurations})
is used.

@table @option
@item -g
@itemx --gamma RGB
Apply gamma correction to the colour curves.
All values in the three colour curves are raised
to the power of 1 divided by @code{RGB}. Assuming
no values in the curves are larger than 1 (100 %)
the curves are bent upwards if @code{RGB} is larger
than 1.

@item -g
@itemx --gamma R:G:B
This works as @option{--gamma RGB}, except the
gamma is applied separately for the three colour
curves. If we want to apply the 0,9 gamma to the
red colour component, and 1,1 and 1,2 for the
green and blue colour components, respectively use
@option{-g 0.9:1.1:1.2} or @option{-gamma 0.9:1.1:1.2}.

@item -b
@itemx --brightness RGB
This multiplies all values in the colour curves
with @env{RGB}, effectively making the display
@env{RGB} times as bright. Values larger than 1,
will be clipped to 1. This is indented to be used
to make the screen slightly darker during the night.

@item -b
@itemx --brightness R:G:B
This option is to @option{--brightness RGB} as
@option{--gamma R:G:B} is to @option{--gamma RGB}.

@item +b
@itemx ++brightness Y
This option works as @option{--brightness RGB},
except the CIE xyY colour spaces is used instead
of sRGB and will probably make the colour curves
look better.

@item -t
@itemx --temperature TEMP
Changes the colour tempurature to @code{TEMP}
Kelvin. The standard colour tempurature is
6500 K@footnote{Or actually 6504 K using revised
constants in Plank's law}. If not specified,
the colour temperature will be 3700 K during
high night and 6500 K during the high day.

@item -l
@itemx --location LAT:LON
Specify your geographical coordinates. This
is used to determine how dark it is outside.
@env{LAT} is the latitude, floating point
measured in degrees celestial northwards from
the equator. It is negative if you are on the
southern hemisphere. @env{LON} is the
longitude, floating point measured in degrees
eastwards from Greenwich. Negative if you
are on the west side of the Earth.

@item -r
@itemx --reset
Transition from the specified settings to
normal, clean, settings.

@item -o
@itemx --output
@itemx --crtc CRTC
Select CRTC to apply changes to. This is
comma separated list, and multiple options
may be used. It is best to start one
instance per monitor with colour calibration.
@end table

@option{-g}, @option{-b}, @option{+b}, and
@option{-t} can be use twice, each, to use
different settings during the night and during
the day. While this is possible for gamma,
it is not recommended. The purpose of gamma
is to adjust the same error that are present
in minors and make all colours look correct
in relation to each other.



@node Signals
@chapter Signals

@command{blueshift}, by default in continuous
mode, implements special support for three
signals:

@table @asis
@item SIGTERM
Fades out the settings and exits the first
time SIGTERM is received. If SIGTERM is
received again, Blueshift immediately
resets effects and exits.

@kbd{Control+c} is treated as SIGTERM.

@item SIGTSTP
@itemx SIGCONT
Blueshift does implement special handling
of the termporary stop signal (SIGTSTP),
or continue signal (SIGCONT). So if you send
SIGTSTP to Blueshift it pause until you send
SIGCONT.

With usual TTY settings, the terminal sends
SIGTSTP when @kbd{Control+z} is processed.
Shells can send SIGCONT if you type either
of @code{%}, @code{fg}, @code{%blueshift} or
@code{fg blueshift}. @code{bg} or
@code{bg blueshift} can be used to continue
in the background instead of in the foreground.

@item SIGUSR1
Reloads the configuration script.

@item SIGUSR2
Disables or enables Blueshift.

@end table



@node Configuration API
@chapter Configuration API

@menu
* Configuration variables::             Configuration variables.
* Colour curve manipulators::           Configuration functions colour adjustments.
* Custom colour curve manipulators::    Creating custom colour adjustment functions.
* Preexisting adjustments::             Using preexisting adjustment, in use and ICC.
* Applying colour curves::              Appying colour adjustments to the video drivers.
* Hardware detection::                  Detecting connected monitors.
* Backlight::                           Adjusting monitor backlight.
* Continuous mode::                     Creating continuous mode configurations.
* Solar time::                          Solar functions, such as elevation calcuation.
@end menu


@node Configuration variables
@section Configuration variables

Blueshift has three colour curves:

@table @code
@item r_curve
The curve for the red colour component.
@item g_curve
The curve for the green colour component.
@item b_curve
The curve for the blue colour component.
@end table

These are @code{i_size} sized floating point
lists, where 0 is the darkest colour and 1
is the brightest colour. Values outside this
range are clipped unless @code{clip_result}
is set to @code{False}. By calling @code{clip}
this clipping is done independently of the value
of @code{clip_result}. @code{clip} optionally
takes one or three arguments, if one, nothing
will happen if it is @code{False}, if three,
nothing will happen for the red, green and
blue colour curves if the first, second and
third arguments, respectively, is @code{False}.
When applied these values are automatically
translated to appropriate integer values:
[0, @code{o_size} - 1].

Additionally if the variable @code{panicgate}
is @code{True}, there is no fading when the program
starts. And @code{conf_opts} is a list of command line
arguments passed onto the configuration script; and
@code{conf_storage} is a dictionary can be used to
store information is required to survive a
configuration reload, such as replaced functions.

If you want to use the settings intended for ad-hoc
mode, set @code{uses_adhoc_opts} to @code{True}. This
lets you use @code{parser}, which is an instance of
@code{ArgParser} (from the argparser library) which
@code{parser} and @code{support_alternatives} already
invoked, without a warning being printed. If you do
not do this, @code{parser} will be @code{None} at the
time @code{periodically} is first invoked by Blueshift.


@node Colour curve manipulators
@section Colour curve manipulators

Blueshift provides a set of functions to
manipulate these curves:

@table @code
@item rgb_contrast(rgb)
Adjusts the contrast to @code{rgb}. This
function assumes the black is 0, and white
is 1, so you should apply this before brightness.

Note: This does not correspond to the contrast
on monitors control panels used to calibrate
the white point.

@item rgb_contrast(r, g, b)
Adjusts the contrast to @code{r}, @code{g}
and @code{b} on the red, green and blue curves,
respectively. This function assumes the black is
0, and white is 1, so you should apply this
before brightness.

Note: This does not correspond to the contrast
on monitors control panels used to calibrate
the white point.

@item cie_contrast(y)
Adjusts the contrast to @code{y}.
The function calculate the values by using
the CIE xyY colour space instead of the sRGB
colour space. This function assumes the black
is 0, and white is 1, so you should apply
this before brightness.

Note: This does not correspond to the contrast
on monitors control panels used to calibrate
the white point.

@item rgb_brightness(rgb)
Adjusts the brightness to @code{rgb}.
Note: This does not correspond to the contrast
on monitors control panels used to calibrate
the white point.

Note: This does not correspond to the brightness
on monitors control panels used to calibrate
the black point point, rather it corresponds
to the contrast on monitors control panels
used to calibrate white point.

@item rgb_brightness(r, g, b)
Adjusts the brightness to @code{r}, @code{g}
and @code{b} on the red, green and blue curves,
respectively.

Note: This does not correspond to the brightness
on monitors control panels used to calibrate
the black point point, rather it corresponds
to the contrast on monitors control panels
used to calibrate white point.

@item cie_brightness(y)
Adjusts the brightness to @code{y}.
The function calculate the values by using
the CIE xyY colour space instead of the sRGB
colour space.

Note: This does not correspond to the brightness
on monitors control panels used to calibrate
the black point point, rather it corresponds
to the contrast on monitors control panels
used to calibrate white point.

@item linearise()
Converts the colour curves from sRGB to
linear RGB. sRGB is the default colour space.

@item linearise(rgb)
Converts the colour curves from sRGB to
linear RGB if @code{rgb} is @code{True}.
sRGB is the default colour space.

@item linearise(r, g, b)
Converts the colour curves from sRGB to
linear RGB, but only for the red, green
and blue colour curves if @code{red},
@code{green}, @code{blue} is @code{True},
respectively. sRGB is the default colour
space.

@item standardise()
Converts the colour curves from linear RGB to
sRGB, the default colour space.

@item standardise(rgb)
Converts the colour curves from linear RGB to
sRGB, the default colour space, if @code{rgb}
is @code{True}.

@item standardise(r, g, b)
Converts the colour curves from linear RGB to
sRGB, the default colour space, but only for
the red, green and blue colour curves if
@code{red}, @code{green}, @code{blue} is
@code{True}, respectively.

@item gamma(rgb)
Adjusts the gamma to @code{rgb}.

@item gamma(r, g, b)
Adjusts the gamma to @code{r}, @code{g}
and @code{b} on the red, green and blue curves,
respectively.

@item negative()
Reverse the colour curves on the encoding axis.
This creates a negative image with preserved gamma.

@item negative(rgb)
Reverse the colour curves on the encoding axis
if @code{rgb} is @code{True}.

@item negative(r, g, b)
Reverse the red, green and blue curves on the
encoding axis if @code{r}, @code{g} and @code{b}
are @code{True}, respectively.

@item rgb_invert()
Inverts the all values on the colour curves.
This creates a negative image with inverted gamma.

@item rgb_invert(rgb)
Inverts the all values on the colour curves
if @code{rgb} is @code{True}.

@item rgb_invert(r, g, b)
Inverts the all values on the red, green and
blue curves if @code{r}, @code{g} and @code{b}
are @code{True}, respectively.

@item cie_invert()
Inverts the all values on the colour curves
using the CIE xyY colour space instead of sRGB.

@item cie_invert(y)
Inverts the all values on the colour curves
using the CIE xyY colour space instead of sRGB,
if @code{y} is @code{true}.

@item sigmoid(r, g, b)
An inverted sigmoid curve function is applied
to the values of in red, green and blue curves
if @code{r}, @code{g} and @code{b} are not
@code{None}, respectively. @code{r}, @code{g}
and @code{b} are the curve sigmoid curve
multipliers for the red, green and blue curves,
respectively.

@item rgb_limits(rgb_min, rgb_max)
Changes the black point to @code{rgb_min}, and
the white point to @code{rgb_max}.

@code{rgb_min} corresponds to the brightness
on monitor control panels used to calibrate the
black point. @code{rgb_max} corresponds to the
contrast on monitor control panels used to
calibrate the white point.

@item rgb_limits(r_min, r_max, g_min, g_max, b_min, b_max)
Changes the black point to (@code{r_min},
@code{g_min}, @code{b_min}), and the white
point to (@code{r_max}, @code{g_max}, @code{b_max}).

@item cie_limits(y_min, y_max)
Changes the black point to @code{y_min}, and
the white point to @code{y_max}, using the
CIE xyY colour space instead of sRGB.

@item manipulate(rgb)
Applies the function @code{rgb} : float
@click{} float to colour curves.

@item manipulate(r, g, b)
Applies the functions @code{r}, @code{g} and
@code{b} : float @click{} float to red, green
and blue colour curves, respectively.

@item cie_manipulate(f)
Applies the function @code{f} : float @click{}
float to Y component (illumination) colour curves
converted to CIE xyY.

@item temperature(temperature, algorithm)
Applies the a blackbody colour temperature of
@code{temperature}@footnote{Actually multiplied
by 1,000556328, due to revisions of natural
constants.} Kelvin. Where the white point
for that temperature is calculates by
the function @code{algorithm} : @code{temperature}
@click{} (red, green, blue). When the white
point has been calculates, its components
are used as parameters in a componentwise
brightness adjustment.

There are a few algorithm for calculating the
white point included:
@table @code
@item series_d(temperature)
Can only calculate the white point correctly for
temperatures inside [4000, 7000]. The CIE illuminant
series D is used to calculate the white point.

@item simple_whitepoint(temperature)
Can only calculate the white point accurately for
temperatures inside [1000, 40000]. A mathematical
model of the @code{cmf_10deg} function is used.

@item cmf_2deg(temperature)
Uses a lookup table with linear interpolation to
calculate temperatures inside [1000, 40000].
CIE 1931 2 degree CMF is used.

@item cmf_10deg(temperature)
Uses a lookup table with linear interpolation to
calculate temperatures inside [1000, 40000].
CIE 1964 10 degree CMF is used. This is the
preferred algorithm.

@item redshift(temperature, old_version, linear_interpolation = False)
Uses the lookup table from Redshift with linear
interpolation. If @code{old_version} is @code{True}
the table Redshift<=1.8 is used, which is limited
to [1000, 10000], and is not that accurate. Otherwise
(the default) the table from Redshift>1.8 is used,
which is limited to [1000, 25100], and is accurate.

If @code{linear_interpolation} is @code{False}
(the default) the sRGB colour space is used for
interpolation, otherwise linear RGB is used.
@end table

Some of these algorithms (including @code{cmf_10deg})
are not very good by themself and should be wrapped
with @code{divide_by_maximum} or @code{clip_whitepoint}
((red, green, blue) @click{} (red, green, blue) functions.)
For example, instead of using @code{cmf_10deg}, you
can use @code{lambda t : divide_by_maximum(cmf_10deg(t))}.

@item lower_resolution(x, y)
Emulate low resolution. @code{x} is the number of
colours to emulate that each subpixel can have.
@code{y} does the same thing as @code{x}, except
on the output axis rather than the encoding axis.

@item lower_resolution(rx, ry, gx, gy, bx, by)
This works the same way as @code{lower_resolution(x, y)},
except the subpixels are controlled individually.
@code{rx} and @code{ry} are @code{x} and @code{y}
for the red subpixel, and analogously for @code{gx}
and @code{gy} for green, and @code{bx} and @code{by}
for blue.
@end table

Keep in mind that the order your call the
function matters. For example, adjusting
the gamma before the brightness does not
yeild the same result as in the reverse
order, the latter is the correct way to
apply gamma correction.

Before performing adjusts you must (not required
the very first time) reset the curves by invoking
@code{start_over} (no parameters.) Otherwise the
adjustments will accumulate.


@node Custom colour curve manipulators
@section Custom colour curve manipulators

If you want to write your own functions
@code{curves(r, g, b)} returns a tuple
containing the tuples @code{(r_curve, r)},
@code{(g_curve, g)} and @code{(b_curve, b)}.
To make this easier Blueshift provies a set
of functions used to convert colour space:

@table @code
@item linear_to_standard(r, g, b)
Convert [0, 1] linear RGB to [0, 1] sRGB

@item standard_to_linear(r, g, b)
Convert [0, 1] sRGB to [0, 1] linear RGB

@item ciexyy_to_ciexyz(x, y, Y)
Convert CIE xyY to CIE XYZ

@item ciexyz_to_ciexyy(X, Y, Z)
Convert CIE XYZ to CIE xyY

@item ciexyz_to_linear(X, Y, Z)
Convert CIE XYZ to [0, 1] linear RGB

@item linear_to_ciexyz(r, g, b)
Convert [0, 1] linear RGB to CIE XYZ

@item srgb_to_ciexyy(r, g, b)
Convert [0, 1] sRGB to CIE xyY

@item ciexyy_to_srgb(x, y, Y)
Convert CIE xyY to [0, 1] sRGB

@item ciexyz_to_cielab(x, y, z)
Convert CIE XYZ to CIE L*a*b*

@item cielab_to_xiexyz(l, a, b)
Convert CIE L*a*b* to CIE XYZ
@end table

All these functions return lists with
the three colour components, not tuples.
Input and output is one colour instance.

If you want to calculated the distance (difference)
between two colours, you can use @code{delta_e}. It
has two parameters, each is red–green–blue-tuple of
an sRGB colour. The just notice difference is circa
2,3.


@node Preexisting adjustments
@section Preexisting adjustments

If you have an ICC profile for calibration (applied last)
or want to use one for as a video filter (applied first),
the function @code{load_icc} can be used to load an ICC
profile file. @code{load_icc} takes one argument, the
pathname of the ICC profile file; the function returns
a fuction that can be invoked to apply the profile.

Alternatively, you can use either of the functions:

@table @code
@item parse_icc(data)
Parse raw (series of bytes) ICC profile data into a function
that applies the profile when invoked.

@item get_current_icc_raw()
Load the raw data for the currently applied ICC profiles,
stored on the X server. This function returns a list of
3-tuples, each tuple contains the index of a screen,
the index of a monitor and the raw data (series of bytes)
of the ICC profile for indicated monitor on the indicated
screen. Monitors without profiles are not listed.

@item get_current_icc()
This function works like @code{get_current_icc_raw}, except
rather than returning raw profile data it returns functions
that apply the profiles when invoked.

@end table

If you want to apply your adjustments on top of the
current colour adjustments, you can use the functions
@code{randr_get} or @code{vidmode_get}. @code{randr_get}
and @code{vidmode_get} have optional two parameters,
@code{crtc} and @code{screen}, which are the CRTC of
the monitor to read from, and the screen to which the
monitor belongs, respectively. The functions return
a parameterless function that applies adjustsments
that were applied at the time of invokation of
@code{randr_get} or @code{vidmode_get} to the current
working curves.


@node Applying colour curves
@section Applying colour curves

To apply a colour curve to the display
server, invoke the @code{randr} function, or
@code{vidmode}@footnote{@code{vidmode} has
the same API as @code{randr}, but it only
supports using the zeroth CRTC};
@code{print_curves} can be used to print
the curves to stdout instead (for debugging).
These functions apply the curves to all
monitors in the default screen (screen 0),
put you can also use select monitors by
specifying each monitor in as separate
arguments. The monitors are indexed from
zero. The screen by can be selected by
adding the argument @code{screen = X},
where @code{X} is the index of the screen.
@code{print_curves} has a third optional
parameters: @code{compact}, if it is set
to @code{True}, the curves will be printed
with run-length encoding.

If you want to write your own curve flushing
fucntion @code{translate_to_integers} can be
used, it returned the colour curves converted
from floating point lists to integer lists in
a tuple of three (red, green and blue.) Replace
the parameterless function @code{close_c_bindings}
to make it free all used resource, this is
invoked when Blueshift exits.

When Blueshift exists, it invoked the
parameterless function @code{reset} which
you should replace. By default it resets
the colour curves and flushes it to all
monitors. To restrict which monitors it
applies the changes to replace
@code{monitor_controller} with a parameterless
function that sends the colour curves to
the desired monitors to the display server.
This is only done if Blueshift runs in
continuous mode.


@node Hardware detection
@section Hardware detection

To support multiple monitors in a dynamic way,
the function @code{list_screens} can be used.
@code{list_screens} is parameterless and returns
the an instance of the class @code{Screens}.
Instances of @code{Screens} have one varible:
@code{screens}, a list of instances of the class
@code{Screen}. The index of each screens is their
index in @code{screens}.

Instances of the class @code{Screen} have two
varibles: @code{crtc_count}, the number of CRT
controllers used within the screen, and
@code{outputs}, a list of all output ports as
instances of the class @code{Output}. Instances
of @code{Output} have six variables:

@table @code
@item name
The name of the output port.

@item connected
Whether the output is known to be connected
to a monitor.

@item widthmm
The physical width of the monitor, measured
in millimetres. @code{None} if unknown or if
not connected.

@item heightmm
The physical height of the monitor, measured
in millimetres. @code{None} if unknown or if
not connected.

@item crtc
The CRT controller index. @code{None} if not
connected.

@item screen
The screen index. @code{None} if not used.

@item edid
The extended display identification data of
the monitor in lower case hexadecimal representations.
@code{None} if not used or not found. If the monitor
is used it is probably found because it is needed
for plug and play support of the monitor.
@end table

@code{Screens} and @code{Screen} provide a set
of functions for finding the output, and traversal
the CRTC and screen, a monitor is connected to:

@table @code
@item find_by_crtc(index)
Matches outputs by CRTC index. If @code{index}
is @code{None}, it will find unused outputs.

@item find_by_name(name)
Matches outputs by output name.

@item find_by_size(widthmm, heightmm)
Matches outputs by physical size of the monitor.
@code{widthmm} and @code{heightmm} are the
monitor's physical width and heigth, respectively,
measured in millimetres. IF @code{widthmm} and
@code{heightmm} are @code{None} it will find
unused outputs and outputs whether the monitor's
size is unknown.

@item find_by_connected(status)
Matches outputs that are known to be in used
(if @code{status} is @code{True}) or outputs
that are either unused or not known whether
they are used or not (if @code{status} is
@code{False}.)

@item find_by_edid(name)
Matches outputs by monitor extended display
identification data.
@end table

These functions returns a list of matching
@code{Output}:s. The list is empty if non are
found.


@node Backlight
@section Backlight

@command{blueshift} offers support for adjusting
the backlight on monitors through Linux's sysfs.
When available this preferable to adjusting the
brightness. It does however have two drawbacks:
it interferes with manual adjustments and depending
on the backlight controller you may have very
few backlight levels available.

To list the available backlight controllers, run the
function @code{list_backlights}, has ho parameters,
it returns a list of controller names.

To use a backlight controller, invoke the contructor
of the class @code{Backlight}. It takes one manditory
argument, the backlight controller either by name or
path, and two optional arguments: @code{adjbacklight}
and @code{minimum}. @code{adjbacklight} is booleanic,
if @code{True} the command @command{adjbacklight} from
the package with the same name will be used to set the
backlight, rather than @command{blueshift} setting it
by itself; this lets you adjust the backlight without
root permissions and without the administrator justing
the permission of @file{/sys/class/backlight/*/brightness}
files. @code{minimum} is an integer and is zero by default,
which is the lowest logical value to have. @code{minimum}
raises the minimum value from zero to avaoid the backlight
from getting stuck at zero when reached, as happens on
some controllers.

Instances of the class @code{Backlight} have one
variable: @code{maximum}. @code{maximum} is an integer
and is the highest inclusive brightness level. Instances
also have two properties: @code{actual} and
@code{brightness}. @code{actual} is read-only and gets
the current actual backlight level. @code{brightness}
can both be read and write and gets or sets the current
backlight level. Both are integer properties.


@node Continuous mode
@section Continuous mode

In continuous mode, there are some interesting
variables you can adjust at any time:

@table @code
@item wait_period
The number of seconds to wait before updating
the colour curves again. This is a floating
point variable.

@item fadein_time
he number of seconds used to fade in on start,
@code{None} for no fading. This is a floating
point variable.

@item fadeout_time
The number of seconds used to fade out on exit,
@code{None} for no fading. This is a floating
point variable.

@item fadein_steps
The number of steps in the fade in phase, if any.

@item fadeout_steps
The number of steps in the fade out phase, if any.

@item running
Set to @code{False} to exit the program. This is
normally done when @kbd{Control+c} is pressed or
a SIGTERM signal has been received.

@item panic
This variable only have effect if @code{running}
is @code{False}. If this variable is set to
@code{True}, the program will immediately
run @code{reset} and exit. This is normally done
the second time @kbd{Control+c} is pressed or
the second time a SIGTERM signal has been received.
(Or if both has happend.)
@end table

The parameterless function @code{continuous_run},
may replace if you want to do something very special,
is invoked to run the continuous mode, it the program
shall run in continuous mode. Which is determined by
whether the function @code{periodically} is defined.
Updates to @code{continuous_run} are ignored when
SIGUSR1 signals are received.

You can also replace the function @code{signal_SIGTERM}.
@code{continuous_run} sets up the program to run it
when the program receive a SIGTERM signal.
@code{continuous_run} also invokes it when @kbd{Control+c}
is pressed. @code{signal_SIGTERM} has two parameters,
the second can be ignored as it is normally @code{None};
the first parameter is the signal that is received
(an integer), and zero if @kbd{Control+c} has been
pressed.

Similarly @code{signal_SIGUSR1} and @code{signal_SIGUSR2}
are invoked when the programs received a SIGUSR1 signal or
a SIGUSR2 signal, respectively. SIGUSR1 reloads the
configurations and SIGUSR2 enables or disables Blueshift.

To run in continuous mode, you must implement the
function @code{periodically}. It takes 8 positional
arguments:

@table @code
@item year
The year.
@item month
The month, 1 = January, 12 = December.
@item day
The day, minimum value is 1, probable maximum value is 31.
Theoretically, but most probably not, a change in the
calender system could happen and the month's could length
could be increased. This has happend once, giving us
1712-(02)Feb-30.
@item hour
The hour, minimum value is 0, maximum value is 23.
@item minute
The minute, minimum value is 0, maximum value is 59.
@item second
The second, minimum value is 0, probable maximum value is 60.
We can get 60, or even higher (but that has never happend yet)
due to leapseconds. A minutes length could also be shortend,
but that has never happend yet either.
@item weekday
The weekday, 1 = Monday, 7 = Sunday.
@item fade
Normally, @code{periodically} is invoked with @code{fade}
set to @code{None}. This is note the case when the program
starts or exits. When @code{fade} is not @code{None},
@code{wait_period} is not honoured.

Blueshift can use @code{periodically} to fade into a state
when it start or exits. @code{fade} can either be negative,
zero or positive or @code{None}, but the magnitude of value
cannot exceed 1. When Blueshift starts, the function will
be invoked multiple with the time parameters of the time it
is invoked and each time @code{fade} will increase towards
1, starting at 0, when the value is 1, the settings should
be applied to 100 %. After this this function will be invoked
once again with @code{fade} being @code{None}. When Blueshift
exits the same behaviour is used except, @code{fade} decrease
towards @math{-1} but start slightly below 0, when @math{-1}
is reached all settings should be normal. Then Blueshift will
@emph{not} invoke this function with @code{fade} being
@code{None}, instead it will by itself revert all settings,
by calling @code{reset} and quit.
@end table

Python does not specify that the exceptions can
happen, but do not could on them not. Python's
documentation could be work, or the API could
change.

If you want higher time precision --- the time
parameters are integers --- you are welcome to
use Python's time API. @code{periodically} will
never be invoked with fake time. Just do not mix
as you could theoretically get on two different
seconds, minutes, hours, or even days, months or
years, the delay between Blueshift's timestamp
and yours could overlap an increase in the second.


@node Solar time
@section Solar time

Blueshift includes a simple way to get the Sun's
position. The function @code{sun(latitude, longitude)}
returns the visibility of the Sun as an [0, 1] floating
point. It has three optional, additional, parameters:

@table @code
@item t = None
The time in Julian Centuries.

@item low = -6.0
The Suns elevation at the limit to high night, that
is, the highest possible position (measured in degrees)
of the Sun before it becomes visible.

@item high = 3.0
The Suns elevation at the limit to high day, that is,
the lowest possible position (measured in degrees) of
the before it starts becoming less visible (twilight.)
@end table

To convert a time to Julian Centuries, you can use
the function @code{epoch_to_julian_centuries}. It takes
one argument, the POSIX time, that is, the number of
seconds that have elapsed since 1970-(01)Jan-01 00:00:00
UTC, not counting leap seconds.

A set of functions that are used to calculate the Sun's
are provided:

@table @code
@item julian_day_to_epoch(t)
Converts a Julian Day timestamp to a POSIX time timestamp.

@item epoch_to_julian_day(t)
Converts a POSIX time timestamp to a Julian Day timestamp.

@item julian_day_to_julian_centuries(t)
Converts a Julian Day timestamp to a Julian Centuries timestamp.

@item julian_centuries_to_julian_day(t)
Converts a Julian Centuries timestamp to a Julian Day timestamp.

@item epoch_to_julian_centuries(t)
Converts a POSIX time timestamp to a Julian Centuries timestamp.

@item julian_centuries_to_epoch(t)
Converts a Julian Centuries timestamp to a POSIX time timestamp.

@item epoch()
Returns the current time in POSIX time.

@item julian_day()
Returns the current time in Julian Day time.

@item julian_centuries()
Returns the current time in Julian Centuries time (100 Julian days since J2000.)

@item radians(deg)
Converts from degrees to radians.

@item degrees(rad)
Converts from radians to degrees.

@item sun_geometric_mean_longitude(t)
Calculates the Sun's geometric mean longitude, in radians.

@item sun_geometric_mean_anomaly(t)
Calculates the Sun's geometric mean anomaly, in radians.

@item earth_orbit_eccentricity(t)
Calculates the Earth's orbit eccentricity.

@item sun_equation_of_centre(t)
Calculates the Sun's equation of the centre, the difference
between the true anomaly and the mean anomaly, in radians.

@item sun_real_longitude(t)
Calculates the Sun's real longitudinal position, in radians.

@item sun_apparent_longitude(t)
Calculates the Sun's apparent longitudinal position, in radians.

@item mean_ecliptic_obliquity(t)
Calculates the mean ecliptic obliquity, in radians,
of the Sun's apparent motion without variation correction.

@item corrected_mean_ecliptic_obliquity(t)
Calculates the mean ecliptic obliquity, in radians,
of the Sun's apparent motion with variation correction.

@item solar_declination(t)
Calculates the Sun's declination, in radians.

@item equation_of_time(t)
Calculates the equation of time, the discrepancy between
apparent and mean solar time, in degrees.

@item hour_angle_from_elevation(latitude, declination, elevation)
Calculates the solar hour angle from the Sun's elevation.

@item elevation_from_hour_angle(latitude, declination, hour_angle)
Calculates the Sun's elevation from the solar hour angle.

@item time_of_solar_noon(t, longitude)
Calculates the time of the closest solar noon.

@item time_of_solar_elevation(t, noon, latitude, longitude, elevation)
Calculates the time the Sun has the apparent elevation
@code{elevation}, in degrees, at the geographical position
(@code{latitude}, @code{longitude}). @code{noon} is the
time the closest the solar noon.

@item solar_elevation_from_time(t, latitude, longitude)
Calculates the Suns elevation, in degrees, as apparent from the
geographical position (@code{latitude}, @code{longitude}).

@item solar_elevation(latitude, longitude, t = None)
Calculates the same thing as @code{solar_elevation_from_time},
except the time is optional and defaults to the current time.
@end table

For all functions beneath @code{degrees}, @code{t} is the
time in Julian Centuries. All parameters are floating point
and may not be @code{None}, except for in @code{solar_elevation},
as specified.

Blueshift provides constants with important elevations of
the Sun during twilight.

@table @code
@item SOLAR_ELEVATION_SUNSET_SUNRISE
The Sun's elevation at sunset and sunrise,
measured in degrees.

@item SOLAR_ELEVATION_CIVIL_DUSK_DAWN
The Sun's elevation at civil dusk and civil dawn,
measured in degrees.

@item SOLAR_ELEVATION_NAUTICAL_DUSK_DAWN
The Sun's elevation at nautical dusk and nautical
dawn, measured in degrees.

@item SOLAR_ELEVATION_ASTRONOMICAL_DUSK_DAWN
The Sun's elevation at astronomical dusk and
astronomical dawn, measured in degrees.

@item SOLAR_ELEVATION_RANGE_TWILIGHT
The Sun's lowest and highest elevation during all
periods of twilight, measured in degrees.

@item SOLAR_ELEVATION_RANGE_CIVIL_TWILIGHT
The Sun's lowest and highest elevation during
civil twilight, measured in degrees.

@item SOLAR_ELEVATION_RANGE_NAUTICAL_TWILIGHT
The Sun's lowest and highest elevation during
nautical twilight, measured in degrees.

@item SOLAR_ELEVATION_RANGE_ASTRONOMICAL_TWILIGHT
The Sun's lowest and highest elevation during
astronomical twilight, measured in degrees.
@end table



@node Related software
@chapter Related software

@command{blueshift} by itself have a wide range of
feature, but it can be extended further by additional
software:

@table @command
@item blueshift-tray
A wrapper for Blueshift that makes it easy to
temporarily activate and deactivate Blueshift
by placing it in the X system tray.

@item blueshift-curse
@command{blueshift-curse} is an extension for
Blueshift that can be used by configuration scripts
to make it possible for other applications, included
an ncurses interface that comes with it, to do
modifications to the configurations.
@command{blueshift-curse} uses domain sockets for
interprocess communication.
@end table

If you want to extend the capabilities of Blueshift
for your configuration scripts their are some library
packages that can be of particular interest:

@table @command
@item python3-xlib
X library for Python based on the Xlib library.

@item xpyb
(Not ported to Python 3)@*
X library for Python based on the XCB library.

@item xpybutil
(Not ported to Python 3)@*
A Python rendition of xcb-util including EWMH, ICCCM, key binding, Xinerama, &c.

@item ooxcb
(Not ported to Python 3)@*
An object-oriented X library for Python based on xpyb.

@item pygtk
(Not ported to Python 3)@*
GTK+ 2 bindings for Python.

@item python-gobject
GTK+ 3 bindings for Python.

@item python2-geoclue
(Not ported to Python 3)@*
GeoClue library for Python, can be used to get your geographical position.
GeoClue uses D-Bus, and can use multiple position providers:
@itemize @bullet{}
@item GPS:
Position information from a Global Positioning System receiver via @command{gpsd} and @command{gypsy}.
@item GSM:
Position information from cellular network connection.
@item Plazes:
Position information from the Plazes Wi-Fi location service.
@item Hostip:
Position information based on IP address.
@item Manual:
User-provided position information.
@end itemize

@item python-dbus
Python bindings for D-Bus.

@item python-networkmanager
Python interface to NetworkManager.
@end table



@node Terminology
@chapter Terminology

Terminology related to Blueshift:

@table @asis
@item Ad-hoc mode
@itemx One time mode
Running Blueshift without a configuration script.

@item Configuration mode
Running Blueshift with a configuration script.

@item Configuration script
Blueshift provides a mechanism for adjusting
colours on the monitors. Configuration scripts,
invoked by Blueshift, implements the policy
for doing so.

@item Continuous mode
Running Blueshift such at it applies adjustments
but than continues to run and applies now
(time dependent) adjustments every now and then
until the user terminates Blueshift.

@item One shot mode
Running Blueshift such at it applies adjustments
and than exits.

 @item Panicgate
Applying adjustments immediately without
transitioning. This terminology is borrowed
from OpenNTPD.

@item High day
@itemx Day
@itemx Daytime
The time during the day when the Sun elevated to
be 100 % visible. The time between sunrise and
sunset; when it is full daylight.

@item High night
@itemx Night
@itemx Nighttime
The time during the day when the Sun elevated to
be 0 % visible. The time between dusk and dawn;
when it is complete darkness.
@end table



@node GNU Free Documentation License
@appendix GNU Free Documentation License
@include fdl.texinfo

@bye