\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 Economy
@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
@subtitle Automatically adjust the colour temperature
@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}.
* Configuration API::               How to write configuration files.
* 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 too 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.

@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
(unlessed 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 @var{RGB}. Assuming
no values in the curves are larger than 1 (100 %)
the curves are bent upwards if @var{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 @var{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 from the equator to the
north. It is negative if you are on the
southern hemisphere. @env{LON} is the
longitude, floating point measured in degrees
from Greenwich to the east. 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 Configuration API
@chapter Configuration API

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}
(has no parameters) this clipping is done
independently of the value of @code{clip_result}.
When applied these values are automatically
translated to appropriate integer values:
[0, @code{o_size} - 1].

Blueshift provides a set of functions to
manipulate these curves:

@table @code
@item rgb_contrast(rgb)
Adjusts the contrast to @code{rgb}.

@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.

@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.

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

@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.

@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.

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

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

@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(rgb)
Inverts the all values on the colour curves
if @code{rgb} is @code{True}.

@item negative(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 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 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 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))}.
@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 most (not required
the very first time) reset the curves by invoking
@code{start_over} (no parameters.) Otherwise the
adjustments will accumulate.

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 linear [0, 1] 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
@end table

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

To apply a colour curve to the display
server, invoke the @code{randr} function;
@code{print_curves} can be used to print
the curves to stdout instead (for debugging).
These functions apply the curves to all
monitors, put you can also use select monitors
by specifying each monitor in as separate
arguments. The monitors are indexed from zero.

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.

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

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.

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.

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.


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

@bye