diff --git a/src/colorramp.c b/src/colorramp.c index fda75f2f..72038945 100644 --- a/src/colorramp.c +++ b/src/colorramp.c @@ -23,305 +23,350 @@ #include "redshift.h" +#define TEMPERATURE_NORM 6500 +#define TEMPERATURE_ZERO 700 +// Approximation of the `redshift` table from +// https://github.com/jonls/redshift/blob/04760afe31bff5b26cf18fe51606e7bdeac15504/src/colorramp.c#L30-L273 +// without limits: +// GAMMA = K0 + K1 * ln(T - T0) +// Red range (T0 = TEMPERATURE_ZERO) +// Green color +#define GAMMA_K0GR -1.47751309139817 +#define GAMMA_K1GR 0.28590164772055 +// Blue color +#define GAMMA_K0BR -4.38321650114872 +#define GAMMA_K1BR 0.6212158769447 +// Blue range (T0 = TEMPERATURE_NORM - TEMPERATURE_ZERO) +// Red color +#define GAMMA_K0RB 1.75390204039018 +#define GAMMA_K1RB -0.1150805671482 +// Green color +#define GAMMA_K0GB 1.49221604915144 +#define GAMMA_K1GB -0.07513509588921 + + /* Whitepoint values for temperatures at 100K intervals. These will be interpolated for the actual temperature. This table was provided by Ingo Thies, 2013. See - the file README-colorramp for more information. */ + the file README-colorramp for more information. + 1000K - 25100K */ +/* static const float blackbody_color[] = { - 1.00000000, 0.18172716, 0.00000000, /* 1000K */ - 1.00000000, 0.25503671, 0.00000000, /* 1100K */ - 1.00000000, 0.30942099, 0.00000000, /* 1200K */ - 1.00000000, 0.35357379, 0.00000000, /* ... */ - 1.00000000, 0.39091524, 0.00000000, - 1.00000000, 0.42322816, 0.00000000, - 1.00000000, 0.45159884, 0.00000000, - 1.00000000, 0.47675916, 0.00000000, - 1.00000000, 0.49923747, 0.00000000, - 1.00000000, 0.51943421, 0.00000000, - 1.00000000, 0.54360078, 0.08679949, - 1.00000000, 0.56618736, 0.14065513, - 1.00000000, 0.58734976, 0.18362641, - 1.00000000, 0.60724493, 0.22137978, - 1.00000000, 0.62600248, 0.25591950, - 1.00000000, 0.64373109, 0.28819679, - 1.00000000, 0.66052319, 0.31873863, - 1.00000000, 0.67645822, 0.34786758, - 1.00000000, 0.69160518, 0.37579588, - 1.00000000, 0.70602449, 0.40267128, - 1.00000000, 0.71976951, 0.42860152, - 1.00000000, 0.73288760, 0.45366838, - 1.00000000, 0.74542112, 0.47793608, - 1.00000000, 0.75740814, 0.50145662, - 1.00000000, 0.76888303, 0.52427322, - 1.00000000, 0.77987699, 0.54642268, - 1.00000000, 0.79041843, 0.56793692, - 1.00000000, 0.80053332, 0.58884417, - 1.00000000, 0.81024551, 0.60916971, - 1.00000000, 0.81957693, 0.62893653, - 1.00000000, 0.82854786, 0.64816570, - 1.00000000, 0.83717703, 0.66687674, - 1.00000000, 0.84548188, 0.68508786, - 1.00000000, 0.85347859, 0.70281616, - 1.00000000, 0.86118227, 0.72007777, - 1.00000000, 0.86860704, 0.73688797, - 1.00000000, 0.87576611, 0.75326132, - 1.00000000, 0.88267187, 0.76921169, - 1.00000000, 0.88933596, 0.78475236, - 1.00000000, 0.89576933, 0.79989606, - 1.00000000, 0.90198230, 0.81465502, - 1.00000000, 0.90963069, 0.82838210, - 1.00000000, 0.91710889, 0.84190889, - 1.00000000, 0.92441842, 0.85523742, - 1.00000000, 0.93156127, 0.86836903, - 1.00000000, 0.93853986, 0.88130458, - 1.00000000, 0.94535695, 0.89404470, - 1.00000000, 0.95201559, 0.90658983, - 1.00000000, 0.95851906, 0.91894041, - 1.00000000, 0.96487079, 0.93109690, - 1.00000000, 0.97107439, 0.94305985, - 1.00000000, 0.97713351, 0.95482993, - 1.00000000, 0.98305189, 0.96640795, - 1.00000000, 0.98883326, 0.97779486, - 1.00000000, 0.99448139, 0.98899179, - 1.00000000, 1.00000000, 1.00000000, /* 6500K */ - 0.98947904, 0.99348723, 1.00000000, - 0.97940448, 0.98722715, 1.00000000, - 0.96975025, 0.98120637, 1.00000000, - 0.96049223, 0.97541240, 1.00000000, - 0.95160805, 0.96983355, 1.00000000, - 0.94303638, 0.96443333, 1.00000000, - 0.93480451, 0.95923080, 1.00000000, - 0.92689056, 0.95421394, 1.00000000, - 0.91927697, 0.94937330, 1.00000000, - 0.91194747, 0.94470005, 1.00000000, - 0.90488690, 0.94018594, 1.00000000, - 0.89808115, 0.93582323, 1.00000000, - 0.89151710, 0.93160469, 1.00000000, - 0.88518247, 0.92752354, 1.00000000, - 0.87906581, 0.92357340, 1.00000000, - 0.87315640, 0.91974827, 1.00000000, - 0.86744421, 0.91604254, 1.00000000, - 0.86191983, 0.91245088, 1.00000000, - 0.85657444, 0.90896831, 1.00000000, - 0.85139976, 0.90559011, 1.00000000, - 0.84638799, 0.90231183, 1.00000000, - 0.84153180, 0.89912926, 1.00000000, - 0.83682430, 0.89603843, 1.00000000, - 0.83225897, 0.89303558, 1.00000000, - 0.82782969, 0.89011714, 1.00000000, - 0.82353066, 0.88727974, 1.00000000, - 0.81935641, 0.88452017, 1.00000000, - 0.81530175, 0.88183541, 1.00000000, - 0.81136180, 0.87922257, 1.00000000, - 0.80753191, 0.87667891, 1.00000000, - 0.80380769, 0.87420182, 1.00000000, - 0.80018497, 0.87178882, 1.00000000, - 0.79665980, 0.86943756, 1.00000000, - 0.79322843, 0.86714579, 1.00000000, - 0.78988728, 0.86491137, 1.00000000, /* 10000K */ - 0.78663296, 0.86273225, 1.00000000, - 0.78346225, 0.86060650, 1.00000000, - 0.78037207, 0.85853224, 1.00000000, - 0.77735950, 0.85650771, 1.00000000, - 0.77442176, 0.85453121, 1.00000000, - 0.77155617, 0.85260112, 1.00000000, - 0.76876022, 0.85071588, 1.00000000, - 0.76603147, 0.84887402, 1.00000000, - 0.76336762, 0.84707411, 1.00000000, - 0.76076645, 0.84531479, 1.00000000, - 0.75822586, 0.84359476, 1.00000000, - 0.75574383, 0.84191277, 1.00000000, - 0.75331843, 0.84026762, 1.00000000, - 0.75094780, 0.83865816, 1.00000000, - 0.74863017, 0.83708329, 1.00000000, - 0.74636386, 0.83554194, 1.00000000, - 0.74414722, 0.83403311, 1.00000000, - 0.74197871, 0.83255582, 1.00000000, - 0.73985682, 0.83110912, 1.00000000, - 0.73778012, 0.82969211, 1.00000000, - 0.73574723, 0.82830393, 1.00000000, - 0.73375683, 0.82694373, 1.00000000, - 0.73180765, 0.82561071, 1.00000000, - 0.72989845, 0.82430410, 1.00000000, - 0.72802807, 0.82302316, 1.00000000, - 0.72619537, 0.82176715, 1.00000000, - 0.72439927, 0.82053539, 1.00000000, - 0.72263872, 0.81932722, 1.00000000, - 0.72091270, 0.81814197, 1.00000000, - 0.71922025, 0.81697905, 1.00000000, - 0.71756043, 0.81583783, 1.00000000, - 0.71593234, 0.81471775, 1.00000000, - 0.71433510, 0.81361825, 1.00000000, - 0.71276788, 0.81253878, 1.00000000, - 0.71122987, 0.81147883, 1.00000000, - 0.70972029, 0.81043789, 1.00000000, - 0.70823838, 0.80941546, 1.00000000, - 0.70678342, 0.80841109, 1.00000000, - 0.70535469, 0.80742432, 1.00000000, - 0.70395153, 0.80645469, 1.00000000, - 0.70257327, 0.80550180, 1.00000000, - 0.70121928, 0.80456522, 1.00000000, - 0.69988894, 0.80364455, 1.00000000, - 0.69858167, 0.80273941, 1.00000000, - 0.69729688, 0.80184943, 1.00000000, - 0.69603402, 0.80097423, 1.00000000, - 0.69479255, 0.80011347, 1.00000000, - 0.69357196, 0.79926681, 1.00000000, - 0.69237173, 0.79843391, 1.00000000, - 0.69119138, 0.79761446, 1.00000000, /* 15000K */ - 0.69003044, 0.79680814, 1.00000000, - 0.68888844, 0.79601466, 1.00000000, - 0.68776494, 0.79523371, 1.00000000, - 0.68665951, 0.79446502, 1.00000000, - 0.68557173, 0.79370830, 1.00000000, - 0.68450119, 0.79296330, 1.00000000, - 0.68344751, 0.79222975, 1.00000000, - 0.68241029, 0.79150740, 1.00000000, - 0.68138918, 0.79079600, 1.00000000, - 0.68038380, 0.79009531, 1.00000000, - 0.67939381, 0.78940511, 1.00000000, - 0.67841888, 0.78872517, 1.00000000, - 0.67745866, 0.78805526, 1.00000000, - 0.67651284, 0.78739518, 1.00000000, - 0.67558112, 0.78674472, 1.00000000, - 0.67466317, 0.78610368, 1.00000000, - 0.67375872, 0.78547186, 1.00000000, - 0.67286748, 0.78484907, 1.00000000, - 0.67198916, 0.78423512, 1.00000000, - 0.67112350, 0.78362984, 1.00000000, - 0.67027024, 0.78303305, 1.00000000, - 0.66942911, 0.78244457, 1.00000000, - 0.66859988, 0.78186425, 1.00000000, - 0.66778228, 0.78129191, 1.00000000, - 0.66697610, 0.78072740, 1.00000000, - 0.66618110, 0.78017057, 1.00000000, - 0.66539706, 0.77962127, 1.00000000, - 0.66462376, 0.77907934, 1.00000000, - 0.66386098, 0.77854465, 1.00000000, - 0.66310852, 0.77801705, 1.00000000, - 0.66236618, 0.77749642, 1.00000000, - 0.66163375, 0.77698261, 1.00000000, - 0.66091106, 0.77647551, 1.00000000, - 0.66019791, 0.77597498, 1.00000000, - 0.65949412, 0.77548090, 1.00000000, - 0.65879952, 0.77499315, 1.00000000, - 0.65811392, 0.77451161, 1.00000000, - 0.65743716, 0.77403618, 1.00000000, - 0.65676908, 0.77356673, 1.00000000, - 0.65610952, 0.77310316, 1.00000000, - 0.65545831, 0.77264537, 1.00000000, - 0.65481530, 0.77219324, 1.00000000, - 0.65418036, 0.77174669, 1.00000000, - 0.65355332, 0.77130560, 1.00000000, - 0.65293404, 0.77086988, 1.00000000, - 0.65232240, 0.77043944, 1.00000000, - 0.65171824, 0.77001419, 1.00000000, - 0.65112144, 0.76959404, 1.00000000, - 0.65053187, 0.76917889, 1.00000000, - 0.64994941, 0.76876866, 1.00000000, /* 20000K */ - 0.64937392, 0.76836326, 1.00000000, - 0.64880528, 0.76796263, 1.00000000, - 0.64824339, 0.76756666, 1.00000000, - 0.64768812, 0.76717529, 1.00000000, - 0.64713935, 0.76678844, 1.00000000, - 0.64659699, 0.76640603, 1.00000000, - 0.64606092, 0.76602798, 1.00000000, - 0.64553103, 0.76565424, 1.00000000, - 0.64500722, 0.76528472, 1.00000000, - 0.64448939, 0.76491935, 1.00000000, - 0.64397745, 0.76455808, 1.00000000, - 0.64347129, 0.76420082, 1.00000000, - 0.64297081, 0.76384753, 1.00000000, - 0.64247594, 0.76349813, 1.00000000, - 0.64198657, 0.76315256, 1.00000000, - 0.64150261, 0.76281076, 1.00000000, - 0.64102399, 0.76247267, 1.00000000, - 0.64055061, 0.76213824, 1.00000000, - 0.64008239, 0.76180740, 1.00000000, - 0.63961926, 0.76148010, 1.00000000, - 0.63916112, 0.76115628, 1.00000000, - 0.63870790, 0.76083590, 1.00000000, - 0.63825953, 0.76051890, 1.00000000, - 0.63781592, 0.76020522, 1.00000000, - 0.63737701, 0.75989482, 1.00000000, - 0.63694273, 0.75958764, 1.00000000, - 0.63651299, 0.75928365, 1.00000000, - 0.63608774, 0.75898278, 1.00000000, - 0.63566691, 0.75868499, 1.00000000, - 0.63525042, 0.75839025, 1.00000000, - 0.63483822, 0.75809849, 1.00000000, - 0.63443023, 0.75780969, 1.00000000, - 0.63402641, 0.75752379, 1.00000000, - 0.63362667, 0.75724075, 1.00000000, - 0.63323097, 0.75696053, 1.00000000, - 0.63283925, 0.75668310, 1.00000000, - 0.63245144, 0.75640840, 1.00000000, - 0.63206749, 0.75613641, 1.00000000, - 0.63168735, 0.75586707, 1.00000000, - 0.63131096, 0.75560036, 1.00000000, - 0.63093826, 0.75533624, 1.00000000, - 0.63056920, 0.75507467, 1.00000000, - 0.63020374, 0.75481562, 1.00000000, - 0.62984181, 0.75455904, 1.00000000, - 0.62948337, 0.75430491, 1.00000000, - 0.62912838, 0.75405319, 1.00000000, - 0.62877678, 0.75380385, 1.00000000, - 0.62842852, 0.75355685, 1.00000000, - 0.62808356, 0.75331217, 1.00000000, - 0.62774186, 0.75306977, 1.00000000, /* 25000K */ - 0.62740336, 0.75282962, 1.00000000 /* 25100K */ + 1.00000000, 0.18172716, 0.00000000, + 1.00000000, 0.25503671, 0.00000000, + 1.00000000, 0.30942099, 0.00000000, + 1.00000000, 0.35357379, 0.00000000, + 1.00000000, 0.39091524, 0.00000000, + 1.00000000, 0.42322816, 0.00000000, + 1.00000000, 0.45159884, 0.00000000, + 1.00000000, 0.47675916, 0.00000000, + 1.00000000, 0.49923747, 0.00000000, + 1.00000000, 0.51943421, 0.00000000, + 1.00000000, 0.54360078, 0.08679949, + 1.00000000, 0.56618736, 0.14065513, + 1.00000000, 0.58734976, 0.18362641, + 1.00000000, 0.60724493, 0.22137978, + 1.00000000, 0.62600248, 0.25591950, + 1.00000000, 0.64373109, 0.28819679, + 1.00000000, 0.66052319, 0.31873863, + 1.00000000, 0.67645822, 0.34786758, + 1.00000000, 0.69160518, 0.37579588, + 1.00000000, 0.70602449, 0.40267128, + 1.00000000, 0.71976951, 0.42860152, + 1.00000000, 0.73288760, 0.45366838, + 1.00000000, 0.74542112, 0.47793608, + 1.00000000, 0.75740814, 0.50145662, + 1.00000000, 0.76888303, 0.52427322, + 1.00000000, 0.77987699, 0.54642268, + 1.00000000, 0.79041843, 0.56793692, + 1.00000000, 0.80053332, 0.58884417, + 1.00000000, 0.81024551, 0.60916971, + 1.00000000, 0.81957693, 0.62893653, + 1.00000000, 0.82854786, 0.64816570, + 1.00000000, 0.83717703, 0.66687674, + 1.00000000, 0.84548188, 0.68508786, + 1.00000000, 0.85347859, 0.70281616, + 1.00000000, 0.86118227, 0.72007777, + 1.00000000, 0.86860704, 0.73688797, + 1.00000000, 0.87576611, 0.75326132, + 1.00000000, 0.88267187, 0.76921169, + 1.00000000, 0.88933596, 0.78475236, + 1.00000000, 0.89576933, 0.79989606, + 1.00000000, 0.90198230, 0.81465502, + 1.00000000, 0.90963069, 0.82838210, + 1.00000000, 0.91710889, 0.84190889, + 1.00000000, 0.92441842, 0.85523742, + 1.00000000, 0.93156127, 0.86836903, + 1.00000000, 0.93853986, 0.88130458, + 1.00000000, 0.94535695, 0.89404470, + 1.00000000, 0.95201559, 0.90658983, + 1.00000000, 0.95851906, 0.91894041, + 1.00000000, 0.96487079, 0.93109690, + 1.00000000, 0.97107439, 0.94305985, + 1.00000000, 0.97713351, 0.95482993, + 1.00000000, 0.98305189, 0.96640795, + 1.00000000, 0.98883326, 0.97779486, + 1.00000000, 0.99448139, 0.98899179, + 1.00000000, 1.00000000, 1.00000000, + 0.98947904, 0.99348723, 1.00000000, + 0.97940448, 0.98722715, 1.00000000, + 0.96975025, 0.98120637, 1.00000000, + 0.96049223, 0.97541240, 1.00000000, + 0.95160805, 0.96983355, 1.00000000, + 0.94303638, 0.96443333, 1.00000000, + 0.93480451, 0.95923080, 1.00000000, + 0.92689056, 0.95421394, 1.00000000, + 0.91927697, 0.94937330, 1.00000000, + 0.91194747, 0.94470005, 1.00000000, + 0.90488690, 0.94018594, 1.00000000, + 0.89808115, 0.93582323, 1.00000000, + 0.89151710, 0.93160469, 1.00000000, + 0.88518247, 0.92752354, 1.00000000, + 0.87906581, 0.92357340, 1.00000000, + 0.87315640, 0.91974827, 1.00000000, + 0.86744421, 0.91604254, 1.00000000, + 0.86191983, 0.91245088, 1.00000000, + 0.85657444, 0.90896831, 1.00000000, + 0.85139976, 0.90559011, 1.00000000, + 0.84638799, 0.90231183, 1.00000000, + 0.84153180, 0.89912926, 1.00000000, + 0.83682430, 0.89603843, 1.00000000, + 0.83225897, 0.89303558, 1.00000000, + 0.82782969, 0.89011714, 1.00000000, + 0.82353066, 0.88727974, 1.00000000, + 0.81935641, 0.88452017, 1.00000000, + 0.81530175, 0.88183541, 1.00000000, + 0.81136180, 0.87922257, 1.00000000, + 0.80753191, 0.87667891, 1.00000000, + 0.80380769, 0.87420182, 1.00000000, + 0.80018497, 0.87178882, 1.00000000, + 0.79665980, 0.86943756, 1.00000000, + 0.79322843, 0.86714579, 1.00000000, + 0.78988728, 0.86491137, 1.00000000, + 0.78663296, 0.86273225, 1.00000000, + 0.78346225, 0.86060650, 1.00000000, + 0.78037207, 0.85853224, 1.00000000, + 0.77735950, 0.85650771, 1.00000000, + 0.77442176, 0.85453121, 1.00000000, + 0.77155617, 0.85260112, 1.00000000, + 0.76876022, 0.85071588, 1.00000000, + 0.76603147, 0.84887402, 1.00000000, + 0.76336762, 0.84707411, 1.00000000, + 0.76076645, 0.84531479, 1.00000000, + 0.75822586, 0.84359476, 1.00000000, + 0.75574383, 0.84191277, 1.00000000, + 0.75331843, 0.84026762, 1.00000000, + 0.75094780, 0.83865816, 1.00000000, + 0.74863017, 0.83708329, 1.00000000, + 0.74636386, 0.83554194, 1.00000000, + 0.74414722, 0.83403311, 1.00000000, + 0.74197871, 0.83255582, 1.00000000, + 0.73985682, 0.83110912, 1.00000000, + 0.73778012, 0.82969211, 1.00000000, + 0.73574723, 0.82830393, 1.00000000, + 0.73375683, 0.82694373, 1.00000000, + 0.73180765, 0.82561071, 1.00000000, + 0.72989845, 0.82430410, 1.00000000, + 0.72802807, 0.82302316, 1.00000000, + 0.72619537, 0.82176715, 1.00000000, + 0.72439927, 0.82053539, 1.00000000, + 0.72263872, 0.81932722, 1.00000000, + 0.72091270, 0.81814197, 1.00000000, + 0.71922025, 0.81697905, 1.00000000, + 0.71756043, 0.81583783, 1.00000000, + 0.71593234, 0.81471775, 1.00000000, + 0.71433510, 0.81361825, 1.00000000, + 0.71276788, 0.81253878, 1.00000000, + 0.71122987, 0.81147883, 1.00000000, + 0.70972029, 0.81043789, 1.00000000, + 0.70823838, 0.80941546, 1.00000000, + 0.70678342, 0.80841109, 1.00000000, + 0.70535469, 0.80742432, 1.00000000, + 0.70395153, 0.80645469, 1.00000000, + 0.70257327, 0.80550180, 1.00000000, + 0.70121928, 0.80456522, 1.00000000, + 0.69988894, 0.80364455, 1.00000000, + 0.69858167, 0.80273941, 1.00000000, + 0.69729688, 0.80184943, 1.00000000, + 0.69603402, 0.80097423, 1.00000000, + 0.69479255, 0.80011347, 1.00000000, + 0.69357196, 0.79926681, 1.00000000, + 0.69237173, 0.79843391, 1.00000000, + 0.69119138, 0.79761446, 1.00000000, + 0.69003044, 0.79680814, 1.00000000, + 0.68888844, 0.79601466, 1.00000000, + 0.68776494, 0.79523371, 1.00000000, + 0.68665951, 0.79446502, 1.00000000, + 0.68557173, 0.79370830, 1.00000000, + 0.68450119, 0.79296330, 1.00000000, + 0.68344751, 0.79222975, 1.00000000, + 0.68241029, 0.79150740, 1.00000000, + 0.68138918, 0.79079600, 1.00000000, + 0.68038380, 0.79009531, 1.00000000, + 0.67939381, 0.78940511, 1.00000000, + 0.67841888, 0.78872517, 1.00000000, + 0.67745866, 0.78805526, 1.00000000, + 0.67651284, 0.78739518, 1.00000000, + 0.67558112, 0.78674472, 1.00000000, + 0.67466317, 0.78610368, 1.00000000, + 0.67375872, 0.78547186, 1.00000000, + 0.67286748, 0.78484907, 1.00000000, + 0.67198916, 0.78423512, 1.00000000, + 0.67112350, 0.78362984, 1.00000000, + 0.67027024, 0.78303305, 1.00000000, + 0.66942911, 0.78244457, 1.00000000, + 0.66859988, 0.78186425, 1.00000000, + 0.66778228, 0.78129191, 1.00000000, + 0.66697610, 0.78072740, 1.00000000, + 0.66618110, 0.78017057, 1.00000000, + 0.66539706, 0.77962127, 1.00000000, + 0.66462376, 0.77907934, 1.00000000, + 0.66386098, 0.77854465, 1.00000000, + 0.66310852, 0.77801705, 1.00000000, + 0.66236618, 0.77749642, 1.00000000, + 0.66163375, 0.77698261, 1.00000000, + 0.66091106, 0.77647551, 1.00000000, + 0.66019791, 0.77597498, 1.00000000, + 0.65949412, 0.77548090, 1.00000000, + 0.65879952, 0.77499315, 1.00000000, + 0.65811392, 0.77451161, 1.00000000, + 0.65743716, 0.77403618, 1.00000000, + 0.65676908, 0.77356673, 1.00000000, + 0.65610952, 0.77310316, 1.00000000, + 0.65545831, 0.77264537, 1.00000000, + 0.65481530, 0.77219324, 1.00000000, + 0.65418036, 0.77174669, 1.00000000, + 0.65355332, 0.77130560, 1.00000000, + 0.65293404, 0.77086988, 1.00000000, + 0.65232240, 0.77043944, 1.00000000, + 0.65171824, 0.77001419, 1.00000000, + 0.65112144, 0.76959404, 1.00000000, + 0.65053187, 0.76917889, 1.00000000, + 0.64994941, 0.76876866, 1.00000000, + 0.64937392, 0.76836326, 1.00000000, + 0.64880528, 0.76796263, 1.00000000, + 0.64824339, 0.76756666, 1.00000000, + 0.64768812, 0.76717529, 1.00000000, + 0.64713935, 0.76678844, 1.00000000, + 0.64659699, 0.76640603, 1.00000000, + 0.64606092, 0.76602798, 1.00000000, + 0.64553103, 0.76565424, 1.00000000, + 0.64500722, 0.76528472, 1.00000000, + 0.64448939, 0.76491935, 1.00000000, + 0.64397745, 0.76455808, 1.00000000, + 0.64347129, 0.76420082, 1.00000000, + 0.64297081, 0.76384753, 1.00000000, + 0.64247594, 0.76349813, 1.00000000, + 0.64198657, 0.76315256, 1.00000000, + 0.64150261, 0.76281076, 1.00000000, + 0.64102399, 0.76247267, 1.00000000, + 0.64055061, 0.76213824, 1.00000000, + 0.64008239, 0.76180740, 1.00000000, + 0.63961926, 0.76148010, 1.00000000, + 0.63916112, 0.76115628, 1.00000000, + 0.63870790, 0.76083590, 1.00000000, + 0.63825953, 0.76051890, 1.00000000, + 0.63781592, 0.76020522, 1.00000000, + 0.63737701, 0.75989482, 1.00000000, + 0.63694273, 0.75958764, 1.00000000, + 0.63651299, 0.75928365, 1.00000000, + 0.63608774, 0.75898278, 1.00000000, + 0.63566691, 0.75868499, 1.00000000, + 0.63525042, 0.75839025, 1.00000000, + 0.63483822, 0.75809849, 1.00000000, + 0.63443023, 0.75780969, 1.00000000, + 0.63402641, 0.75752379, 1.00000000, + 0.63362667, 0.75724075, 1.00000000, + 0.63323097, 0.75696053, 1.00000000, + 0.63283925, 0.75668310, 1.00000000, + 0.63245144, 0.75640840, 1.00000000, + 0.63206749, 0.75613641, 1.00000000, + 0.63168735, 0.75586707, 1.00000000, + 0.63131096, 0.75560036, 1.00000000, + 0.63093826, 0.75533624, 1.00000000, + 0.63056920, 0.75507467, 1.00000000, + 0.63020374, 0.75481562, 1.00000000, + 0.62984181, 0.75455904, 1.00000000, + 0.62948337, 0.75430491, 1.00000000, + 0.62912838, 0.75405319, 1.00000000, + 0.62877678, 0.75380385, 1.00000000, + 0.62842852, 0.75355685, 1.00000000, + 0.62808356, 0.75331217, 1.00000000, + 0.62774186, 0.75306977, 1.00000000, + 0.62740336, 0.75282962, 1.00000000 }; - +*/ +static float floattrim(float x, float a, float b) +{ + float buff[3] = {a, x, b}; + return buff[ (int)(x > a) + (int)(x > b) ]; +} static void -interpolate_color(float a, const float *c1, const float *c2, float *c) +interpolate_color(float temperature, float *c) { - c[0] = (1.0-a)*c1[0] + a*c2[0]; - c[1] = (1.0-a)*c1[1] + a*c2[1]; - c[2] = (1.0-a)*c1[2] + a*c2[2]; + float g; + if (temperature < TEMPERATURE_NORM) + { + c[0] = 1.0f; + if (temperature > TEMPERATURE_ZERO) + { + g = log(temperature - TEMPERATURE_ZERO); + c[1] = floattrim(GAMMA_K0GR + GAMMA_K1GR * g, 0.0f, 1.0f); + c[2] = floattrim(GAMMA_K0BR + GAMMA_K1BR * g, 0.0f, 1.0f); + } + else + { + c[1] = 0.0f; + c[2] = 0.0f; + } + } + else + { + g = log(temperature - (TEMPERATURE_NORM - TEMPERATURE_ZERO)); + c[0] = floattrim(GAMMA_K0RB + GAMMA_K1RB * g, 0.0f, 1.0f); + c[1] = floattrim(GAMMA_K0GB + GAMMA_K1GB * g, 0.0f, 1.0f); + c[2] = 1.0f; + } } /* Helper macro used in the fill functions */ #define F(Y, C) pow((Y) * setting->brightness * \ - white_point[C], 1.0/setting->gamma[C]) + white_point[C], 1.0/setting->gamma[C]) void colorramp_fill(uint16_t *gamma_r, uint16_t *gamma_g, uint16_t *gamma_b, - int size, const color_setting_t *setting) + int size, const color_setting_t *setting) { - /* Approximate white point */ - float white_point[3]; - float alpha = (setting->temperature % 100) / 100.0; - int temp_index = ((setting->temperature - 1000) / 100)*3; - interpolate_color(alpha, &blackbody_color[temp_index], - &blackbody_color[temp_index+3], white_point); + /* Approximate white point */ + float white_point[3]; + float temp = (setting->temperature); + interpolate_color(temp, white_point); - for (int i = 0; i < size; i++) { - gamma_r[i] = F((double)gamma_r[i]/(UINT16_MAX+1), 0) * - (UINT16_MAX+1); - gamma_g[i] = F((double)gamma_g[i]/(UINT16_MAX+1), 1) * - (UINT16_MAX+1); - gamma_b[i] = F((double)gamma_b[i]/(UINT16_MAX+1), 2) * - (UINT16_MAX+1); - } + for (int i = 0; i < size; i++) { + gamma_r[i] = F((double)gamma_r[i]/(UINT16_MAX+1), 0) * + (UINT16_MAX+1); + gamma_g[i] = F((double)gamma_g[i]/(UINT16_MAX+1), 1) * + (UINT16_MAX+1); + gamma_b[i] = F((double)gamma_b[i]/(UINT16_MAX+1), 2) * + (UINT16_MAX+1); + } } void colorramp_fill_float(float *gamma_r, float *gamma_g, float *gamma_b, - int size, const color_setting_t *setting) + int size, const color_setting_t *setting) { - /* Approximate white point */ - float white_point[3]; - float alpha = (setting->temperature % 100) / 100.0; - int temp_index = ((setting->temperature - 1000) / 100)*3; - interpolate_color(alpha, &blackbody_color[temp_index], - &blackbody_color[temp_index+3], white_point); + /* Approximate white point */ + float white_point[3]; + float temp = (setting->temperature); + interpolate_color(temp, white_point); - for (int i = 0; i < size; i++) { - gamma_r[i] = F((double)gamma_r[i], 0); - gamma_g[i] = F((double)gamma_g[i], 1); - gamma_b[i] = F((double)gamma_b[i], 2); - } + for (int i = 0; i < size; i++) { + gamma_r[i] = F((double)gamma_r[i], 0); + gamma_g[i] = F((double)gamma_g[i], 1); + gamma_b[i] = F((double)gamma_b[i], 2); + } } #undef F diff --git a/src/redshift.c b/src/redshift.c index d2ba577c..09b188ed 100644 --- a/src/redshift.c +++ b/src/redshift.c @@ -38,9 +38,9 @@ #else #define POLLIN 0 struct pollfd { - int fd; - short events; - short revents; + int fd; + short events; + short revents; }; int poll(struct pollfd *fds, int nfds, int timeout) { abort(); return -1; } #endif @@ -115,8 +115,8 @@ int poll(struct pollfd *fds, int nfds, int timeout) { abort(); return -1; } #define MAX_LAT 90.0 #define MIN_LON -180.0 #define MAX_LON 180.0 -#define MIN_TEMP 1000 -#define MAX_TEMP 25000 +#define MIN_TEMP 900 +#define MAX_TEMP 50000 #define MIN_BRIGHTNESS 0.1 #define MAX_BRIGHTNESS 1.0 #define MIN_GAMMA 0.1 @@ -132,11 +132,11 @@ int poll(struct pollfd *fds, int nfds, int timeout) { abort(); return -1; } /* Names of periods of day */ static const char *period_names[] = { - /* TRANSLATORS: Name printed when period of day is unknown */ - N_("None"), - N_("Daytime"), - N_("Night"), - N_("Transition") + /* TRANSLATORS: Name printed when period of day is unknown */ + N_("None"), + N_("Daytime"), + N_("Night"), + N_("Transition") }; @@ -144,348 +144,348 @@ static const char *period_names[] = { static period_t get_period_from_time(const transition_scheme_t *transition, int time_offset) { - if (time_offset < transition->dawn.start || - time_offset >= transition->dusk.end) { - return PERIOD_NIGHT; - } else if (time_offset >= transition->dawn.end && - time_offset < transition->dusk.start) { - return PERIOD_DAYTIME; - } else { - return PERIOD_TRANSITION; - } + if (time_offset < transition->dawn.start || + time_offset >= transition->dusk.end) { + return PERIOD_NIGHT; + } else if (time_offset >= transition->dawn.end && + time_offset < transition->dusk.start) { + return PERIOD_DAYTIME; + } else { + return PERIOD_TRANSITION; + } } /* Determine which period we are currently in based on solar elevation. */ static period_t get_period_from_elevation( - const transition_scheme_t *transition, double elevation) + const transition_scheme_t *transition, double elevation) { - if (elevation < transition->low) { - return PERIOD_NIGHT; - } else if (elevation < transition->high) { - return PERIOD_TRANSITION; - } else { - return PERIOD_DAYTIME; - } + if (elevation < transition->low) { + return PERIOD_NIGHT; + } else if (elevation < transition->high) { + return PERIOD_TRANSITION; + } else { + return PERIOD_DAYTIME; + } } /* Determine how far through the transition we are based on time offset. */ static double get_transition_progress_from_time( - const transition_scheme_t *transition, int time_offset) + const transition_scheme_t *transition, int time_offset) { - if (time_offset < transition->dawn.start || - time_offset >= transition->dusk.end) { - return 0.0; - } else if (time_offset < transition->dawn.end) { - return (transition->dawn.start - time_offset) / - (double)(transition->dawn.start - - transition->dawn.end); - } else if (time_offset > transition->dusk.start) { - return (transition->dusk.end - time_offset) / - (double)(transition->dusk.end - - transition->dusk.start); - } else { - return 1.0; - } + if (time_offset < transition->dawn.start || + time_offset >= transition->dusk.end) { + return 0.0; + } else if (time_offset < transition->dawn.end) { + return (transition->dawn.start - time_offset) / + (double)(transition->dawn.start - + transition->dawn.end); + } else if (time_offset > transition->dusk.start) { + return (transition->dusk.end - time_offset) / + (double)(transition->dusk.end - + transition->dusk.start); + } else { + return 1.0; + } } /* Determine how far through the transition we are based on elevation. */ static double get_transition_progress_from_elevation( - const transition_scheme_t *transition, double elevation) + const transition_scheme_t *transition, double elevation) { - if (elevation < transition->low) { - return 0.0; - } else if (elevation < transition->high) { - return (transition->low - elevation) / - (transition->low - transition->high); - } else { - return 1.0; - } + if (elevation < transition->low) { + return 0.0; + } else if (elevation < transition->high) { + return (transition->low - elevation) / + (transition->low - transition->high); + } else { + return 1.0; + } } /* Return number of seconds since midnight from timestamp. */ static int get_seconds_since_midnight(double timestamp) { - time_t t = (time_t)timestamp; - struct tm tm; + time_t t = (time_t)timestamp; + struct tm tm; #ifdef _WIN32 - localtime_s(&tm, &t); + localtime_s(&tm, &t); #else - localtime_r(&t, &tm); + localtime_r(&t, &tm); #endif - return tm.tm_sec + tm.tm_min * 60 + tm.tm_hour * 3600; + return tm.tm_sec + tm.tm_min * 60 + tm.tm_hour * 3600; } /* Print verbose description of the given period. */ static void print_period(period_t period, double transition) { - switch (period) { - case PERIOD_NONE: - case PERIOD_NIGHT: - case PERIOD_DAYTIME: - printf(_("Period: %s\n"), gettext(period_names[period])); - break; - case PERIOD_TRANSITION: - printf(_("Period: %s (%.2f%% day)\n"), - gettext(period_names[period]), - transition*100); - break; - } + switch (period) { + case PERIOD_NONE: + case PERIOD_NIGHT: + case PERIOD_DAYTIME: + printf(_("Period: %s\n"), gettext(period_names[period])); + break; + case PERIOD_TRANSITION: + printf(_("Period: %s (%.2f%% day)\n"), + gettext(period_names[period]), + transition*100); + break; + } } /* Print location */ static void print_location(const location_t *location) { - /* TRANSLATORS: Abbreviation for `north' */ - const char *north = _("N"); - /* TRANSLATORS: Abbreviation for `south' */ - const char *south = _("S"); - /* TRANSLATORS: Abbreviation for `east' */ - const char *east = _("E"); - /* TRANSLATORS: Abbreviation for `west' */ - const char *west = _("W"); - - /* TRANSLATORS: Append degree symbols after %f if possible. - The string following each number is an abreviation for - north, source, east or west (N, S, E, W). */ - printf(_("Location: %.2f %s, %.2f %s\n"), - fabs(location->lat), location->lat >= 0.f ? north : south, - fabs(location->lon), location->lon >= 0.f ? east : west); + /* TRANSLATORS: Abbreviation for `north' */ + const char *north = _("N"); + /* TRANSLATORS: Abbreviation for `south' */ + const char *south = _("S"); + /* TRANSLATORS: Abbreviation for `east' */ + const char *east = _("E"); + /* TRANSLATORS: Abbreviation for `west' */ + const char *west = _("W"); + + /* TRANSLATORS: Append degree symbols after %f if possible. + The string following each number is an abreviation for + north, source, east or west (N, S, E, W). */ + printf(_("Location: %.2f %s, %.2f %s\n"), + fabs(location->lat), location->lat >= 0.f ? north : south, + fabs(location->lon), location->lon >= 0.f ? east : west); } /* Interpolate color setting structs given alpha. */ static void interpolate_color_settings( - const color_setting_t *first, - const color_setting_t *second, - double alpha, - color_setting_t *result) + const color_setting_t *first, + const color_setting_t *second, + double alpha, + color_setting_t *result) { - alpha = CLAMP(0.0, alpha, 1.0); - - result->temperature = (1.0-alpha)*first->temperature + - alpha*second->temperature; - result->brightness = (1.0-alpha)*first->brightness + - alpha*second->brightness; - for (int i = 0; i < 3; i++) { - result->gamma[i] = (1.0-alpha)*first->gamma[i] + - alpha*second->gamma[i]; - } + alpha = CLAMP(0.0, alpha, 1.0); + + result->temperature = (1.0-alpha)*first->temperature + + alpha*second->temperature; + result->brightness = (1.0-alpha)*first->brightness + + alpha*second->brightness; + for (int i = 0; i < 3; i++) { + result->gamma[i] = (1.0-alpha)*first->gamma[i] + + alpha*second->gamma[i]; + } } /* Interpolate color setting structs transition scheme. */ static void interpolate_transition_scheme( - const transition_scheme_t *transition, - double alpha, - color_setting_t *result) + const transition_scheme_t *transition, + double alpha, + color_setting_t *result) { - const color_setting_t *day = &transition->day; - const color_setting_t *night = &transition->night; + const color_setting_t *day = &transition->day; + const color_setting_t *night = &transition->night; - alpha = CLAMP(0.0, alpha, 1.0); - interpolate_color_settings(night, day, alpha, result); + alpha = CLAMP(0.0, alpha, 1.0); + interpolate_color_settings(night, day, alpha, result); } /* Return 1 if color settings have major differences, otherwise 0. Used to determine if a fade should be applied in continual mode. */ static int color_setting_diff_is_major( - const color_setting_t *first, - const color_setting_t *second) + const color_setting_t *first, + const color_setting_t *second) { - return (abs(first->temperature - second->temperature) > 25 || - fabsf(first->brightness - second->brightness) > 0.1 || - fabsf(first->gamma[0] - second->gamma[0]) > 0.1 || - fabsf(first->gamma[1] - second->gamma[1]) > 0.1 || - fabsf(first->gamma[2] - second->gamma[2]) > 0.1); + return (abs(first->temperature - second->temperature) > 25 || + fabsf(first->brightness - second->brightness) > 0.1 || + fabsf(first->gamma[0] - second->gamma[0]) > 0.1 || + fabsf(first->gamma[1] - second->gamma[1]) > 0.1 || + fabsf(first->gamma[2] - second->gamma[2]) > 0.1); } /* Reset color setting to default values. */ static void color_setting_reset(color_setting_t *color) { - color->temperature = NEUTRAL_TEMP; - color->gamma[0] = 1.0; - color->gamma[1] = 1.0; - color->gamma[2] = 1.0; - color->brightness = 1.0; + color->temperature = NEUTRAL_TEMP; + color->gamma[0] = 1.0; + color->gamma[1] = 1.0; + color->gamma[2] = 1.0; + color->brightness = 1.0; } static int provider_try_start(const location_provider_t *provider, - location_state_t **state, config_ini_state_t *config, - char *args) + location_state_t **state, config_ini_state_t *config, + char *args) { - int r; - - r = provider->init(state); - if (r < 0) { - fprintf(stderr, _("Initialization of %s failed.\n"), - provider->name); - return -1; - } - - /* Set provider options from config file. */ - config_ini_section_t *section = - config_ini_get_section(config, provider->name); - if (section != NULL) { - config_ini_setting_t *setting = section->settings; - while (setting != NULL) { - r = provider->set_option(*state, setting->name, - setting->value); - if (r < 0) { - provider->free(*state); - fprintf(stderr, _("Failed to set %s" - " option.\n"), - provider->name); - /* TRANSLATORS: `help' must not be - translated. */ - fprintf(stderr, _("Try `-l %s:help' for more" - " information.\n"), - provider->name); - return -1; - } - setting = setting->next; - } - } - - /* Set provider options from command line. */ - const char *manual_keys[] = { "lat", "lon" }; - int i = 0; - while (args != NULL) { - char *next_arg = strchr(args, ':'); - if (next_arg != NULL) *(next_arg++) = '\0'; - - const char *key = args; - char *value = strchr(args, '='); - if (value == NULL) { - /* The options for the "manual" method can be set - without keys on the command line for convencience - and for backwards compatability. We add the proper - keys here before calling set_option(). */ - if (strcmp(provider->name, "manual") == 0 && - i < sizeof(manual_keys)/sizeof(manual_keys[0])) { - key = manual_keys[i]; - value = args; - } else { - fprintf(stderr, _("Failed to parse option `%s'.\n"), - args); - return -1; - } - } else { - *(value++) = '\0'; - } - - r = provider->set_option(*state, key, value); - if (r < 0) { - provider->free(*state); - fprintf(stderr, _("Failed to set %s option.\n"), - provider->name); - /* TRANSLATORS: `help' must not be translated. */ - fprintf(stderr, _("Try `-l %s:help' for more" - " information.\n"), provider->name); - return -1; - } - - args = next_arg; - i += 1; - } - - /* Start provider. */ - r = provider->start(*state); - if (r < 0) { - provider->free(*state); - fprintf(stderr, _("Failed to start provider %s.\n"), - provider->name); - return -1; - } - - return 0; + int r; + + r = provider->init(state); + if (r < 0) { + fprintf(stderr, _("Initialization of %s failed.\n"), + provider->name); + return -1; + } + + /* Set provider options from config file. */ + config_ini_section_t *section = + config_ini_get_section(config, provider->name); + if (section != NULL) { + config_ini_setting_t *setting = section->settings; + while (setting != NULL) { + r = provider->set_option(*state, setting->name, + setting->value); + if (r < 0) { + provider->free(*state); + fprintf(stderr, _("Failed to set %s" + " option.\n"), + provider->name); + /* TRANSLATORS: `help' must not be + translated. */ + fprintf(stderr, _("Try `-l %s:help' for more" + " information.\n"), + provider->name); + return -1; + } + setting = setting->next; + } + } + + /* Set provider options from command line. */ + const char *manual_keys[] = { "lat", "lon" }; + int i = 0; + while (args != NULL) { + char *next_arg = strchr(args, ':'); + if (next_arg != NULL) *(next_arg++) = '\0'; + + const char *key = args; + char *value = strchr(args, '='); + if (value == NULL) { + /* The options for the "manual" method can be set + without keys on the command line for convencience + and for backwards compatability. We add the proper + keys here before calling set_option(). */ + if (strcmp(provider->name, "manual") == 0 && + i < sizeof(manual_keys)/sizeof(manual_keys[0])) { + key = manual_keys[i]; + value = args; + } else { + fprintf(stderr, _("Failed to parse option `%s'.\n"), + args); + return -1; + } + } else { + *(value++) = '\0'; + } + + r = provider->set_option(*state, key, value); + if (r < 0) { + provider->free(*state); + fprintf(stderr, _("Failed to set %s option.\n"), + provider->name); + /* TRANSLATORS: `help' must not be translated. */ + fprintf(stderr, _("Try `-l %s:help' for more" + " information.\n"), provider->name); + return -1; + } + + args = next_arg; + i += 1; + } + + /* Start provider. */ + r = provider->start(*state); + if (r < 0) { + provider->free(*state); + fprintf(stderr, _("Failed to start provider %s.\n"), + provider->name); + return -1; + } + + return 0; } static int method_try_start(const gamma_method_t *method, - gamma_state_t **state, config_ini_state_t *config, char *args) + gamma_state_t **state, config_ini_state_t *config, char *args) { - int r; - - r = method->init(state); - if (r < 0) { - fprintf(stderr, _("Initialization of %s failed.\n"), - method->name); - return -1; - } - - /* Set method options from config file. */ - config_ini_section_t *section = - config_ini_get_section(config, method->name); - if (section != NULL) { - config_ini_setting_t *setting = section->settings; - while (setting != NULL) { - r = method->set_option( - *state, setting->name, setting->value); - if (r < 0) { - method->free(*state); - fprintf(stderr, _("Failed to set %s" - " option.\n"), - method->name); - /* TRANSLATORS: `help' must not be - translated. */ - fprintf(stderr, _("Try `-m %s:help' for more" - " information.\n"), - method->name); - return -1; - } - setting = setting->next; - } - } - - /* Set method options from command line. */ - while (args != NULL) { - char *next_arg = strchr(args, ':'); - if (next_arg != NULL) *(next_arg++) = '\0'; - - const char *key = args; - char *value = strchr(args, '='); - if (value == NULL) { - fprintf(stderr, _("Failed to parse option `%s'.\n"), - args); - return -1; - } else { - *(value++) = '\0'; - } - - r = method->set_option(*state, key, value); - if (r < 0) { - method->free(*state); - fprintf(stderr, _("Failed to set %s option.\n"), - method->name); - /* TRANSLATORS: `help' must not be translated. */ - fprintf(stderr, _("Try -m %s:help' for more" - " information.\n"), method->name); - return -1; - } - - args = next_arg; - } - - /* Start method. */ - r = method->start(*state); - if (r < 0) { - method->free(*state); - fprintf(stderr, _("Failed to start adjustment method %s.\n"), - method->name); - return -1; - } - - return 0; + int r; + + r = method->init(state); + if (r < 0) { + fprintf(stderr, _("Initialization of %s failed.\n"), + method->name); + return -1; + } + + /* Set method options from config file. */ + config_ini_section_t *section = + config_ini_get_section(config, method->name); + if (section != NULL) { + config_ini_setting_t *setting = section->settings; + while (setting != NULL) { + r = method->set_option( + *state, setting->name, setting->value); + if (r < 0) { + method->free(*state); + fprintf(stderr, _("Failed to set %s" + " option.\n"), + method->name); + /* TRANSLATORS: `help' must not be + translated. */ + fprintf(stderr, _("Try `-m %s:help' for more" + " information.\n"), + method->name); + return -1; + } + setting = setting->next; + } + } + + /* Set method options from command line. */ + while (args != NULL) { + char *next_arg = strchr(args, ':'); + if (next_arg != NULL) *(next_arg++) = '\0'; + + const char *key = args; + char *value = strchr(args, '='); + if (value == NULL) { + fprintf(stderr, _("Failed to parse option `%s'.\n"), + args); + return -1; + } else { + *(value++) = '\0'; + } + + r = method->set_option(*state, key, value); + if (r < 0) { + method->free(*state); + fprintf(stderr, _("Failed to set %s option.\n"), + method->name); + /* TRANSLATORS: `help' must not be translated. */ + fprintf(stderr, _("Try -m %s:help' for more" + " information.\n"), method->name); + return -1; + } + + args = next_arg; + } + + /* Start method. */ + r = method->start(*state); + if (r < 0) { + method->free(*state); + fprintf(stderr, _("Failed to start adjustment method %s.\n"), + method->name); + return -1; + } + + return 0; } @@ -493,12 +493,12 @@ method_try_start(const gamma_method_t *method, static int gamma_is_valid(const float gamma[3]) { - return !(gamma[0] < MIN_GAMMA || - gamma[0] > MAX_GAMMA || - gamma[1] < MIN_GAMMA || - gamma[1] > MAX_GAMMA || - gamma[2] < MIN_GAMMA || - gamma[2] > MAX_GAMMA); + return !(gamma[0] < MIN_GAMMA || + gamma[0] > MAX_GAMMA || + gamma[1] < MIN_GAMMA || + gamma[1] > MAX_GAMMA || + gamma[2] < MIN_GAMMA || + gamma[2] > MAX_GAMMA); } /* Check whether location is valid. @@ -507,25 +507,25 @@ gamma_is_valid(const float gamma[3]) static int location_is_valid(const location_t *location) { - /* Latitude */ - if (location->lat < MIN_LAT || location->lat > MAX_LAT) { - /* TRANSLATORS: Append degree symbols if possible. */ - fprintf(stderr, - _("Latitude must be between %.1f and %.1f.\n"), - MIN_LAT, MAX_LAT); - return 0; - } - - /* Longitude */ - if (location->lon < MIN_LON || location->lon > MAX_LON) { - /* TRANSLATORS: Append degree symbols if possible. */ - fprintf(stderr, - _("Longitude must be between" - " %.1f and %.1f.\n"), MIN_LON, MAX_LON); - return 0; - } - - return 1; + /* Latitude */ + if (location->lat < MIN_LAT || location->lat > MAX_LAT) { + /* TRANSLATORS: Append degree symbols if possible. */ + fprintf(stderr, + _("Latitude must be between %.1f and %.1f.\n"), + MIN_LAT, MAX_LAT); + return 0; + } + + /* Longitude */ + if (location->lon < MIN_LON || location->lon > MAX_LON) { + /* TRANSLATORS: Append degree symbols if possible. */ + fprintf(stderr, + _("Longitude must be between" + " %.1f and %.1f.\n"), MIN_LON, MAX_LON); + return 0; + } + + return 1; } /* Wait for location to become available from provider. @@ -534,56 +534,56 @@ location_is_valid(const location_t *location) 0 if timeout was reached, 1 if location became available. */ static int provider_get_location( - const location_provider_t *provider, location_state_t *state, - int timeout, location_t *loc) + const location_provider_t *provider, location_state_t *state, + int timeout, location_t *loc) { - int available = 0; - struct pollfd pollfds[1]; - while (!available) { - int loc_fd = provider->get_fd(state); - if (loc_fd >= 0) { - /* Provider is dynamic. */ - /* TODO: This should use a monotonic time source. */ - double now; - int r = systemtime_get_time(&now); - if (r < 0) { - fputs(_("Unable to read system time.\n"), - stderr); - return -1; - } - - /* Poll on file descriptor until ready. */ - pollfds[0].fd = loc_fd; - pollfds[0].events = POLLIN; - r = poll(pollfds, 1, timeout); - if (r < 0) { - perror("poll"); - return -1; - } else if (r == 0) { - return 0; - } - - double later; - r = systemtime_get_time(&later); - if (r < 0) { - fputs(_("Unable to read system time.\n"), - stderr); - return -1; - } - - /* Adjust timeout by elapsed time */ - if (timeout >= 0) { - timeout -= (later - now) * 1000; - timeout = timeout < 0 ? 0 : timeout; - } - } - - - int r = provider->handle(state, loc, &available); - if (r < 0) return -1; - } - - return 1; + int available = 0; + struct pollfd pollfds[1]; + while (!available) { + int loc_fd = provider->get_fd(state); + if (loc_fd >= 0) { + /* Provider is dynamic. */ + /* TODO: This should use a monotonic time source. */ + double now; + int r = systemtime_get_time(&now); + if (r < 0) { + fputs(_("Unable to read system time.\n"), + stderr); + return -1; + } + + /* Poll on file descriptor until ready. */ + pollfds[0].fd = loc_fd; + pollfds[0].events = POLLIN; + r = poll(pollfds, 1, timeout); + if (r < 0) { + perror("poll"); + return -1; + } else if (r == 0) { + return 0; + } + + double later; + r = systemtime_get_time(&later); + if (r < 0) { + fputs(_("Unable to read system time.\n"), + stderr); + return -1; + } + + /* Adjust timeout by elapsed time */ + if (timeout >= 0) { + timeout -= (later - now) * 1000; + timeout = timeout < 0 ? 0 : timeout; + } + } + + + int r = provider->handle(state, loc, &available); + if (r < 0) return -1; + } + + return 1; } /* Easing function for fade. @@ -591,10 +591,10 @@ provider_get_location( static double ease_fade(double t) { - if (t <= 0) return 0; - if (t >= 1) return 1; - return 1.0042954579734844 * exp( - -6.4041738958415664 * exp(-7.2908241330981340 * t)); + if (t <= 0) return 0; + if (t >= 1) return 1; + return 1.0042954579734844 * exp( + -6.4041738958415664 * exp(-7.2908241330981340 * t)); } @@ -604,725 +604,725 @@ ease_fade(double t) color temperature. */ static int run_continual_mode(const location_provider_t *provider, - location_state_t *location_state, - const transition_scheme_t *scheme, - const gamma_method_t *method, - gamma_state_t *method_state, - int use_fade, int preserve_gamma, int verbose) + location_state_t *location_state, + const transition_scheme_t *scheme, + const gamma_method_t *method, + gamma_state_t *method_state, + int use_fade, int preserve_gamma, int verbose) { - int r; - - /* Short fade parameters */ - int fade_length = 0; - int fade_time = 0; - color_setting_t fade_start_interp; - - r = signals_install_handlers(); - if (r < 0) { - return r; - } - - /* Save previous parameters so we can avoid printing status updates if - the values did not change. */ - period_t prev_period = PERIOD_NONE; - - /* Previous target color setting and current actual color setting. - Actual color setting takes into account the current color fade. */ - color_setting_t prev_target_interp; - color_setting_reset(&prev_target_interp); - - color_setting_t interp; - color_setting_reset(&interp); - - location_t loc = { NAN, NAN }; - int need_location = !scheme->use_time; - if (need_location) { - fputs(_("Waiting for initial location" - " to become available...\n"), stderr); - - /* Get initial location from provider */ - r = provider_get_location(provider, location_state, -1, &loc); - if (r < 0) { - fputs(_("Unable to get location" - " from provider.\n"), stderr); - return -1; - } - - if (!location_is_valid(&loc)) { - fputs(_("Invalid location returned from provider.\n"), - stderr); - return -1; - } - - print_location(&loc); - } - - if (verbose) { - printf(_("Color temperature: %uK\n"), interp.temperature); - printf(_("Brightness: %.2f\n"), interp.brightness); - } - - /* Continuously adjust color temperature */ - int done = 0; - int prev_disabled = 1; - int disabled = 0; - int location_available = 1; - while (1) { - /* Check to see if disable signal was caught */ - if (disable && !done) { - disabled = !disabled; - disable = 0; - } - - /* Check to see if exit signal was caught */ - if (exiting) { - if (done) { - /* On second signal stop the ongoing fade. */ - break; - } else { - done = 1; - disabled = 1; - } - exiting = 0; - } - - /* Print status change */ - if (verbose && disabled != prev_disabled) { - printf(_("Status: %s\n"), disabled ? - _("Disabled") : _("Enabled")); - } - - prev_disabled = disabled; - - /* Read timestamp */ - double now; - r = systemtime_get_time(&now); - if (r < 0) { - fputs(_("Unable to read system time.\n"), stderr); - return -1; - } - - period_t period; - double transition_prog; - if (scheme->use_time) { - int time_offset = get_seconds_since_midnight(now); - - period = get_period_from_time(scheme, time_offset); - transition_prog = get_transition_progress_from_time( - scheme, time_offset); - } else { - /* Current angular elevation of the sun */ - double elevation = solar_elevation( - now, loc.lat, loc.lon); - - period = get_period_from_elevation(scheme, elevation); - transition_prog = - get_transition_progress_from_elevation( - scheme, elevation); - } - - /* Use transition progress to get target color - temperature. */ - color_setting_t target_interp; - interpolate_transition_scheme( - scheme, transition_prog, &target_interp); - - if (disabled) { - period = PERIOD_NONE; - color_setting_reset(&target_interp); - } - - if (done) { - period = PERIOD_NONE; - } - - /* Print period if it changed during this update, - or if we are in the transition period. In transition we - print the progress, so we always print it in - that case. */ - if (verbose && (period != prev_period || - period == PERIOD_TRANSITION)) { - print_period(period, transition_prog); - } - - /* Activate hooks if period changed */ - if (period != prev_period) { - hooks_signal_period_change(prev_period, period); - } - - /* Start fade if the parameter differences are too big to apply - instantly. */ - if (use_fade) { - if ((fade_length == 0 && - color_setting_diff_is_major( - &interp, - &target_interp)) || - (fade_length != 0 && - color_setting_diff_is_major( - &target_interp, - &prev_target_interp))) { - fade_length = FADE_LENGTH; - fade_time = 0; - fade_start_interp = interp; - } - } - - /* Handle ongoing fade */ - if (fade_length != 0) { - fade_time += 1; - double frac = fade_time / (double)fade_length; - double alpha = CLAMP(0.0, ease_fade(frac), 1.0); - - interpolate_color_settings( - &fade_start_interp, &target_interp, alpha, - &interp); - - if (fade_time > fade_length) { - fade_time = 0; - fade_length = 0; - } - } else { - interp = target_interp; - } - - /* Break loop when done and final fade is over */ - if (done && fade_length == 0) break; - - if (verbose) { - if (prev_target_interp.temperature != - target_interp.temperature) { - printf(_("Color temperature: %uK\n"), - target_interp.temperature); - } - if (prev_target_interp.brightness != - target_interp.brightness) { - printf(_("Brightness: %.2f\n"), - target_interp.brightness); - } - } - - /* Adjust temperature */ - r = method->set_temperature( - method_state, &interp, preserve_gamma); - if (r < 0) { - fputs(_("Temperature adjustment failed.\n"), - stderr); - return -1; - } - - /* Save period and target color setting as previous */ - prev_period = period; - prev_target_interp = target_interp; - - /* Sleep length depends on whether a fade is ongoing. */ - int delay = SLEEP_DURATION; - if (fade_length != 0) { - delay = SLEEP_DURATION_SHORT; - } - - /* Update location. */ - int loc_fd = -1; - if (need_location) { - loc_fd = provider->get_fd(location_state); - } - - if (loc_fd >= 0) { - /* Provider is dynamic. */ - struct pollfd pollfds[1]; - pollfds[0].fd = loc_fd; - pollfds[0].events = POLLIN; - int r = poll(pollfds, 1, delay); - if (r < 0) { - if (errno == EINTR) continue; - perror("poll"); - fputs(_("Unable to get location" - " from provider.\n"), stderr); - return -1; - } else if (r == 0) { - continue; - } - - /* Get new location and availability - information. */ - location_t new_loc; - int new_available; - r = provider->handle( - location_state, &new_loc, - &new_available); - if (r < 0) { - fputs(_("Unable to get location" - " from provider.\n"), stderr); - return -1; - } - - if (!new_available && - new_available != location_available) { - fputs(_("Location is temporarily" - " unavailable; Using previous" - " location until it becomes" - " available...\n"), stderr); - } - - if (new_available && - (new_loc.lat != loc.lat || - new_loc.lon != loc.lon || - new_available != location_available)) { - loc = new_loc; - print_location(&loc); - } - - location_available = new_available; - - if (!location_is_valid(&loc)) { - fputs(_("Invalid location returned" - " from provider.\n"), stderr); - return -1; - } - } else { - systemtime_msleep(delay); - } - } - - /* Restore saved gamma ramps */ - method->restore(method_state); - - return 0; + int r; + + /* Short fade parameters */ + int fade_length = 0; + int fade_time = 0; + color_setting_t fade_start_interp; + + r = signals_install_handlers(); + if (r < 0) { + return r; + } + + /* Save previous parameters so we can avoid printing status updates if + the values did not change. */ + period_t prev_period = PERIOD_NONE; + + /* Previous target color setting and current actual color setting. + Actual color setting takes into account the current color fade. */ + color_setting_t prev_target_interp; + color_setting_reset(&prev_target_interp); + + color_setting_t interp; + color_setting_reset(&interp); + + location_t loc = { NAN, NAN }; + int need_location = !scheme->use_time; + if (need_location) { + fputs(_("Waiting for initial location" + " to become available...\n"), stderr); + + /* Get initial location from provider */ + r = provider_get_location(provider, location_state, -1, &loc); + if (r < 0) { + fputs(_("Unable to get location" + " from provider.\n"), stderr); + return -1; + } + + if (!location_is_valid(&loc)) { + fputs(_("Invalid location returned from provider.\n"), + stderr); + return -1; + } + + print_location(&loc); + } + + if (verbose) { + printf(_("Color temperature: %uK\n"), interp.temperature); + printf(_("Brightness: %.2f\n"), interp.brightness); + } + + /* Continuously adjust color temperature */ + int done = 0; + int prev_disabled = 1; + int disabled = 0; + int location_available = 1; + while (1) { + /* Check to see if disable signal was caught */ + if (disable && !done) { + disabled = !disabled; + disable = 0; + } + + /* Check to see if exit signal was caught */ + if (exiting) { + if (done) { + /* On second signal stop the ongoing fade. */ + break; + } else { + done = 1; + disabled = 1; + } + exiting = 0; + } + + /* Print status change */ + if (verbose && disabled != prev_disabled) { + printf(_("Status: %s\n"), disabled ? + _("Disabled") : _("Enabled")); + } + + prev_disabled = disabled; + + /* Read timestamp */ + double now; + r = systemtime_get_time(&now); + if (r < 0) { + fputs(_("Unable to read system time.\n"), stderr); + return -1; + } + + period_t period; + double transition_prog; + if (scheme->use_time) { + int time_offset = get_seconds_since_midnight(now); + + period = get_period_from_time(scheme, time_offset); + transition_prog = get_transition_progress_from_time( + scheme, time_offset); + } else { + /* Current angular elevation of the sun */ + double elevation = solar_elevation( + now, loc.lat, loc.lon); + + period = get_period_from_elevation(scheme, elevation); + transition_prog = + get_transition_progress_from_elevation( + scheme, elevation); + } + + /* Use transition progress to get target color + temperature. */ + color_setting_t target_interp; + interpolate_transition_scheme( + scheme, transition_prog, &target_interp); + + if (disabled) { + period = PERIOD_NONE; + color_setting_reset(&target_interp); + } + + if (done) { + period = PERIOD_NONE; + } + + /* Print period if it changed during this update, + or if we are in the transition period. In transition we + print the progress, so we always print it in + that case. */ + if (verbose && (period != prev_period || + period == PERIOD_TRANSITION)) { + print_period(period, transition_prog); + } + + /* Activate hooks if period changed */ + if (period != prev_period) { + hooks_signal_period_change(prev_period, period); + } + + /* Start fade if the parameter differences are too big to apply + instantly. */ + if (use_fade) { + if ((fade_length == 0 && + color_setting_diff_is_major( + &interp, + &target_interp)) || + (fade_length != 0 && + color_setting_diff_is_major( + &target_interp, + &prev_target_interp))) { + fade_length = FADE_LENGTH; + fade_time = 0; + fade_start_interp = interp; + } + } + + /* Handle ongoing fade */ + if (fade_length != 0) { + fade_time += 1; + double frac = fade_time / (double)fade_length; + double alpha = CLAMP(0.0, ease_fade(frac), 1.0); + + interpolate_color_settings( + &fade_start_interp, &target_interp, alpha, + &interp); + + if (fade_time > fade_length) { + fade_time = 0; + fade_length = 0; + } + } else { + interp = target_interp; + } + + /* Break loop when done and final fade is over */ + if (done && fade_length == 0) break; + + if (verbose) { + if (prev_target_interp.temperature != + target_interp.temperature) { + printf(_("Color temperature: %uK\n"), + target_interp.temperature); + } + if (prev_target_interp.brightness != + target_interp.brightness) { + printf(_("Brightness: %.2f\n"), + target_interp.brightness); + } + } + + /* Adjust temperature */ + r = method->set_temperature( + method_state, &interp, preserve_gamma); + if (r < 0) { + fputs(_("Temperature adjustment failed.\n"), + stderr); + return -1; + } + + /* Save period and target color setting as previous */ + prev_period = period; + prev_target_interp = target_interp; + + /* Sleep length depends on whether a fade is ongoing. */ + int delay = SLEEP_DURATION; + if (fade_length != 0) { + delay = SLEEP_DURATION_SHORT; + } + + /* Update location. */ + int loc_fd = -1; + if (need_location) { + loc_fd = provider->get_fd(location_state); + } + + if (loc_fd >= 0) { + /* Provider is dynamic. */ + struct pollfd pollfds[1]; + pollfds[0].fd = loc_fd; + pollfds[0].events = POLLIN; + int r = poll(pollfds, 1, delay); + if (r < 0) { + if (errno == EINTR) continue; + perror("poll"); + fputs(_("Unable to get location" + " from provider.\n"), stderr); + return -1; + } else if (r == 0) { + continue; + } + + /* Get new location and availability + information. */ + location_t new_loc; + int new_available; + r = provider->handle( + location_state, &new_loc, + &new_available); + if (r < 0) { + fputs(_("Unable to get location" + " from provider.\n"), stderr); + return -1; + } + + if (!new_available && + new_available != location_available) { + fputs(_("Location is temporarily" + " unavailable; Using previous" + " location until it becomes" + " available...\n"), stderr); + } + + if (new_available && + (new_loc.lat != loc.lat || + new_loc.lon != loc.lon || + new_available != location_available)) { + loc = new_loc; + print_location(&loc); + } + + location_available = new_available; + + if (!location_is_valid(&loc)) { + fputs(_("Invalid location returned" + " from provider.\n"), stderr); + return -1; + } + } else { + systemtime_msleep(delay); + } + } + + /* Restore saved gamma ramps */ + method->restore(method_state); + + return 0; } int main(int argc, char *argv[]) { - int r; + int r; #ifdef ENABLE_NLS - /* Init locale */ - setlocale(LC_CTYPE, ""); - setlocale(LC_MESSAGES, ""); + /* Init locale */ + setlocale(LC_CTYPE, ""); + setlocale(LC_MESSAGES, ""); - /* Internationalisation */ - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); + /* Internationalisation */ + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); #endif - /* List of gamma methods. */ - const gamma_method_t gamma_methods[] = { + /* List of gamma methods. */ + const gamma_method_t gamma_methods[] = { #ifdef ENABLE_DRM - drm_gamma_method, + drm_gamma_method, #endif #ifdef ENABLE_RANDR - randr_gamma_method, + randr_gamma_method, #endif #ifdef ENABLE_VIDMODE - vidmode_gamma_method, + vidmode_gamma_method, #endif #ifdef ENABLE_QUARTZ - quartz_gamma_method, + quartz_gamma_method, #endif #ifdef ENABLE_WINGDI - w32gdi_gamma_method, + w32gdi_gamma_method, #endif - dummy_gamma_method, - { NULL } - }; + dummy_gamma_method, + { NULL } + }; - /* List of location providers. */ - const location_provider_t location_providers[] = { + /* List of location providers. */ + const location_provider_t location_providers[] = { #ifdef ENABLE_GEOCLUE2 - geoclue2_location_provider, + geoclue2_location_provider, #endif #ifdef ENABLE_CORELOCATION - corelocation_location_provider, + corelocation_location_provider, #endif - manual_location_provider, - { NULL } - }; - - /* Flush messages consistently even if redirected to a pipe or - file. Change the flush behaviour to line-buffered, without - changing the actual buffers being used. */ - setvbuf(stdout, NULL, _IOLBF, 0); - setvbuf(stderr, NULL, _IOLBF, 0); - - options_t options; - options_init(&options); - options_parse_args( - &options, argc, argv, gamma_methods, location_providers); - - /* Load settings from config file. */ - config_ini_state_t config_state; - r = config_ini_init(&config_state, options.config_filepath); - if (r < 0) { - fputs("Unable to load config file.\n", stderr); - exit(EXIT_FAILURE); - } - - free(options.config_filepath); - - options_parse_config_file( - &options, &config_state, gamma_methods, location_providers); - - options_set_defaults(&options); - - if (options.scheme.dawn.start >= 0 || options.scheme.dawn.end >= 0 || - options.scheme.dusk.start >= 0 || options.scheme.dusk.end >= 0) { - if (options.scheme.dawn.start < 0 || - options.scheme.dawn.end < 0 || - options.scheme.dusk.start < 0 || - options.scheme.dusk.end < 0) { - fputs(_("Partitial time-configuration not" - " supported!\n"), stderr); - exit(EXIT_FAILURE); - } - - if (options.scheme.dawn.start > options.scheme.dawn.end || - options.scheme.dawn.end > options.scheme.dusk.start || - options.scheme.dusk.start > options.scheme.dusk.end) { - fputs(_("Invalid dawn/dusk time configuration!\n"), - stderr); - exit(EXIT_FAILURE); - } - - options.scheme.use_time = 1; - } - - /* Initialize location provider if needed. If provider is NULL - try all providers until one that works is found. */ - location_state_t *location_state; - - /* Location is not needed for reset mode and manual mode. */ - int need_location = - options.mode != PROGRAM_MODE_RESET && - options.mode != PROGRAM_MODE_MANUAL && - !options.scheme.use_time; - if (need_location) { - if (options.provider != NULL) { - /* Use provider specified on command line. */ - r = provider_try_start( - options.provider, &location_state, - &config_state, options.provider_args); - if (r < 0) exit(EXIT_FAILURE); - } else { - /* Try all providers, use the first that works. */ - for (int i = 0; - location_providers[i].name != NULL; i++) { - const location_provider_t *p = - &location_providers[i]; - fprintf(stderr, - _("Trying location provider `%s'...\n"), - p->name); - r = provider_try_start(p, &location_state, - &config_state, NULL); - if (r < 0) { - fputs(_("Trying next provider...\n"), - stderr); - continue; - } - - /* Found provider that works. */ - printf(_("Using provider `%s'.\n"), p->name); - options.provider = p; - break; - } - - /* Failure if no providers were successful at this - point. */ - if (options.provider == NULL) { - fputs(_("No more location providers" - " to try.\n"), stderr); - exit(EXIT_FAILURE); - } - } - - /* Solar elevations */ - if (options.scheme.high < options.scheme.low) { - fprintf(stderr, - _("High transition elevation cannot be lower than" - " the low transition elevation.\n")); - exit(EXIT_FAILURE); - } - - if (options.verbose) { - /* TRANSLATORS: Append degree symbols if possible. */ - printf(_("Solar elevations: day above %.1f, night below %.1f\n"), - options.scheme.high, options.scheme.low); - } - } - - if (options.mode != PROGRAM_MODE_RESET && - options.mode != PROGRAM_MODE_MANUAL) { - if (options.verbose) { - printf(_("Temperatures: %dK at day, %dK at night\n"), - options.scheme.day.temperature, - options.scheme.night.temperature); - } - - /* Color temperature */ - if (options.scheme.day.temperature < MIN_TEMP || - options.scheme.day.temperature > MAX_TEMP || - options.scheme.night.temperature < MIN_TEMP || - options.scheme.night.temperature > MAX_TEMP) { - fprintf(stderr, - _("Temperature must be between %uK and %uK.\n"), - MIN_TEMP, MAX_TEMP); - exit(EXIT_FAILURE); - } - } - - if (options.mode == PROGRAM_MODE_MANUAL) { - /* Check color temperature to be set */ - if (options.temp_set < MIN_TEMP || - options.temp_set > MAX_TEMP) { - fprintf(stderr, - _("Temperature must be between %uK and %uK.\n"), - MIN_TEMP, MAX_TEMP); - exit(EXIT_FAILURE); - } - } - - /* Brightness */ - if (options.scheme.day.brightness < MIN_BRIGHTNESS || - options.scheme.day.brightness > MAX_BRIGHTNESS || - options.scheme.night.brightness < MIN_BRIGHTNESS || - options.scheme.night.brightness > MAX_BRIGHTNESS) { - fprintf(stderr, - _("Brightness values must be between %.1f and %.1f.\n"), - MIN_BRIGHTNESS, MAX_BRIGHTNESS); - exit(EXIT_FAILURE); - } - - if (options.verbose) { - printf(_("Brightness: %.2f:%.2f\n"), - options.scheme.day.brightness, - options.scheme.night.brightness); - } - - /* Gamma */ - if (!gamma_is_valid(options.scheme.day.gamma) || - !gamma_is_valid(options.scheme.night.gamma)) { - fprintf(stderr, - _("Gamma value must be between %.1f and %.1f.\n"), - MIN_GAMMA, MAX_GAMMA); - exit(EXIT_FAILURE); - } - - if (options.verbose) { - /* TRANSLATORS: The string in parenthesis is either - Daytime or Night (translated). */ - printf(_("Gamma (%s): %.3f, %.3f, %.3f\n"), - _("Daytime"), options.scheme.day.gamma[0], - options.scheme.day.gamma[1], - options.scheme.day.gamma[2]); - printf(_("Gamma (%s): %.3f, %.3f, %.3f\n"), - _("Night"), options.scheme.night.gamma[0], - options.scheme.night.gamma[1], - options.scheme.night.gamma[2]); - } - - transition_scheme_t *scheme = &options.scheme; - - /* Initialize gamma adjustment method. If method is NULL - try all methods until one that works is found. */ - gamma_state_t *method_state; - - /* Gamma adjustment not needed for print mode */ - if (options.mode != PROGRAM_MODE_PRINT) { - if (options.method != NULL) { - /* Use method specified on command line. */ - r = method_try_start( - options.method, &method_state, &config_state, - options.method_args); - if (r < 0) exit(EXIT_FAILURE); - } else { - /* Try all methods, use the first that works. */ - for (int i = 0; gamma_methods[i].name != NULL; i++) { - const gamma_method_t *m = &gamma_methods[i]; - if (!m->autostart) continue; - - r = method_try_start( - m, &method_state, &config_state, NULL); - if (r < 0) { - fputs(_("Trying next method...\n"), stderr); - continue; - } - - /* Found method that works. */ - printf(_("Using method `%s'.\n"), m->name); - options.method = m; - break; - } - - /* Failure if no methods were successful at this point. */ - if (options.method == NULL) { - fputs(_("No more methods to try.\n"), stderr); - exit(EXIT_FAILURE); - } - } - } - - config_ini_free(&config_state); - - switch (options.mode) { - case PROGRAM_MODE_ONE_SHOT: - case PROGRAM_MODE_PRINT: - { - location_t loc = { NAN, NAN }; - if (need_location) { - fputs(_("Waiting for current location" - " to become available...\n"), stderr); - - /* Wait for location provider. */ - int r = provider_get_location( - options.provider, location_state, -1, &loc); - if (r < 0) { - fputs(_("Unable to get location" - " from provider.\n"), stderr); - exit(EXIT_FAILURE); - } - - if (!location_is_valid(&loc)) { - exit(EXIT_FAILURE); - } - - print_location(&loc); - } - - double now; - r = systemtime_get_time(&now); - if (r < 0) { - fputs(_("Unable to read system time.\n"), stderr); - options.method->free(method_state); - exit(EXIT_FAILURE); - } - - period_t period; - double transition_prog; - if (options.scheme.use_time) { - int time_offset = get_seconds_since_midnight(now); - period = get_period_from_time(scheme, time_offset); - transition_prog = get_transition_progress_from_time( - scheme, time_offset); - } else { - /* Current angular elevation of the sun */ - double elevation = solar_elevation( - now, loc.lat, loc.lon); - if (options.verbose) { - /* TRANSLATORS: Append degree symbol if - possible. */ - printf(_("Solar elevation: %f\n"), elevation); - } - - period = get_period_from_elevation(scheme, elevation); - transition_prog = - get_transition_progress_from_elevation( - scheme, elevation); - } - - /* Use transition progress to set color temperature */ - color_setting_t interp; - interpolate_transition_scheme( - scheme, transition_prog, &interp); - - if (options.verbose || options.mode == PROGRAM_MODE_PRINT) { - print_period(period, transition_prog); - printf(_("Color temperature: %uK\n"), - interp.temperature); - printf(_("Brightness: %.2f\n"), - interp.brightness); - } - - if (options.mode != PROGRAM_MODE_PRINT) { - /* Adjust temperature */ - r = options.method->set_temperature( - method_state, &interp, options.preserve_gamma); - if (r < 0) { - fputs(_("Temperature adjustment failed.\n"), - stderr); - options.method->free(method_state); - exit(EXIT_FAILURE); - } - - /* In Quartz (macOS) the gamma adjustments will - automatically revert when the process exits. - Therefore, we have to loop until CTRL-C is received. - */ - if (strcmp(options.method->name, "quartz") == 0) { - fputs(_("Press ctrl-c to stop...\n"), stderr); - pause(); - } - } - } - break; - case PROGRAM_MODE_MANUAL: - { - if (options.verbose) { - printf(_("Color temperature: %uK\n"), - options.temp_set); - } - - /* Adjust temperature */ - color_setting_t manual = scheme->day; - manual.temperature = options.temp_set; - r = options.method->set_temperature( - method_state, &manual, options.preserve_gamma); - if (r < 0) { - fputs(_("Temperature adjustment failed.\n"), stderr); - options.method->free(method_state); - exit(EXIT_FAILURE); - } - - /* In Quartz (OSX) the gamma adjustments will automatically - revert when the process exits. Therefore, we have to loop - until CTRL-C is received. */ - if (strcmp(options.method->name, "quartz") == 0) { - fputs(_("Press ctrl-c to stop...\n"), stderr); - pause(); - } - } - break; - case PROGRAM_MODE_RESET: - { - /* Reset screen */ - color_setting_t reset; - color_setting_reset(&reset); - - r = options.method->set_temperature(method_state, &reset, 0); - if (r < 0) { - fputs(_("Temperature adjustment failed.\n"), stderr); - options.method->free(method_state); - exit(EXIT_FAILURE); - } - - /* In Quartz (OSX) the gamma adjustments will automatically - revert when the process exits. Therefore, we have to loop - until CTRL-C is received. */ - if (strcmp(options.method->name, "quartz") == 0) { - fputs(_("Press ctrl-c to stop...\n"), stderr); - pause(); - } - } - break; - case PROGRAM_MODE_CONTINUAL: - { - r = run_continual_mode( - options.provider, location_state, scheme, - options.method, method_state, - options.use_fade, options.preserve_gamma, - options.verbose); - if (r < 0) exit(EXIT_FAILURE); - } - break; - } - - /* Clean up gamma adjustment state */ - if (options.mode != PROGRAM_MODE_PRINT) { - options.method->free(method_state); - } - - /* Clean up location provider state */ - if (need_location) { - options.provider->free(location_state); - } - - return EXIT_SUCCESS; + manual_location_provider, + { NULL } + }; + + /* Flush messages consistently even if redirected to a pipe or + file. Change the flush behaviour to line-buffered, without + changing the actual buffers being used. */ + setvbuf(stdout, NULL, _IOLBF, 0); + setvbuf(stderr, NULL, _IOLBF, 0); + + options_t options; + options_init(&options); + options_parse_args( + &options, argc, argv, gamma_methods, location_providers); + + /* Load settings from config file. */ + config_ini_state_t config_state; + r = config_ini_init(&config_state, options.config_filepath); + if (r < 0) { + fputs("Unable to load config file.\n", stderr); + exit(EXIT_FAILURE); + } + + free(options.config_filepath); + + options_parse_config_file( + &options, &config_state, gamma_methods, location_providers); + + options_set_defaults(&options); + + if (options.scheme.dawn.start >= 0 || options.scheme.dawn.end >= 0 || + options.scheme.dusk.start >= 0 || options.scheme.dusk.end >= 0) { + if (options.scheme.dawn.start < 0 || + options.scheme.dawn.end < 0 || + options.scheme.dusk.start < 0 || + options.scheme.dusk.end < 0) { + fputs(_("Partitial time-configuration not" + " supported!\n"), stderr); + exit(EXIT_FAILURE); + } + + if (options.scheme.dawn.start > options.scheme.dawn.end || + options.scheme.dawn.end > options.scheme.dusk.start || + options.scheme.dusk.start > options.scheme.dusk.end) { + fputs(_("Invalid dawn/dusk time configuration!\n"), + stderr); + exit(EXIT_FAILURE); + } + + options.scheme.use_time = 1; + } + + /* Initialize location provider if needed. If provider is NULL + try all providers until one that works is found. */ + location_state_t *location_state; + + /* Location is not needed for reset mode and manual mode. */ + int need_location = + options.mode != PROGRAM_MODE_RESET && + options.mode != PROGRAM_MODE_MANUAL && + !options.scheme.use_time; + if (need_location) { + if (options.provider != NULL) { + /* Use provider specified on command line. */ + r = provider_try_start( + options.provider, &location_state, + &config_state, options.provider_args); + if (r < 0) exit(EXIT_FAILURE); + } else { + /* Try all providers, use the first that works. */ + for (int i = 0; + location_providers[i].name != NULL; i++) { + const location_provider_t *p = + &location_providers[i]; + fprintf(stderr, + _("Trying location provider `%s'...\n"), + p->name); + r = provider_try_start(p, &location_state, + &config_state, NULL); + if (r < 0) { + fputs(_("Trying next provider...\n"), + stderr); + continue; + } + + /* Found provider that works. */ + printf(_("Using provider `%s'.\n"), p->name); + options.provider = p; + break; + } + + /* Failure if no providers were successful at this + point. */ + if (options.provider == NULL) { + fputs(_("No more location providers" + " to try.\n"), stderr); + exit(EXIT_FAILURE); + } + } + + /* Solar elevations */ + if (options.scheme.high < options.scheme.low) { + fprintf(stderr, + _("High transition elevation cannot be lower than" + " the low transition elevation.\n")); + exit(EXIT_FAILURE); + } + + if (options.verbose) { + /* TRANSLATORS: Append degree symbols if possible. */ + printf(_("Solar elevations: day above %.1f, night below %.1f\n"), + options.scheme.high, options.scheme.low); + } + } + + if (options.mode != PROGRAM_MODE_RESET && + options.mode != PROGRAM_MODE_MANUAL) { + if (options.verbose) { + printf(_("Temperatures: %dK at day, %dK at night\n"), + options.scheme.day.temperature, + options.scheme.night.temperature); + } + + /* Color temperature */ + if (options.scheme.day.temperature < MIN_TEMP || + options.scheme.day.temperature > MAX_TEMP || + options.scheme.night.temperature < MIN_TEMP || + options.scheme.night.temperature > MAX_TEMP) { + fprintf(stderr, + _("Temperature must be between %uK and %uK.\n"), + MIN_TEMP, MAX_TEMP); + exit(EXIT_FAILURE); + } + } + + if (options.mode == PROGRAM_MODE_MANUAL) { + /* Check color temperature to be set */ + if (options.temp_set < MIN_TEMP || + options.temp_set > MAX_TEMP) { + fprintf(stderr, + _("Temperature must be between %uK and %uK.\n"), + MIN_TEMP, MAX_TEMP); + exit(EXIT_FAILURE); + } + } + + /* Brightness */ + if (options.scheme.day.brightness < MIN_BRIGHTNESS || + options.scheme.day.brightness > MAX_BRIGHTNESS || + options.scheme.night.brightness < MIN_BRIGHTNESS || + options.scheme.night.brightness > MAX_BRIGHTNESS) { + fprintf(stderr, + _("Brightness values must be between %.1f and %.1f.\n"), + MIN_BRIGHTNESS, MAX_BRIGHTNESS); + exit(EXIT_FAILURE); + } + + if (options.verbose) { + printf(_("Brightness: %.2f:%.2f\n"), + options.scheme.day.brightness, + options.scheme.night.brightness); + } + + /* Gamma */ + if (!gamma_is_valid(options.scheme.day.gamma) || + !gamma_is_valid(options.scheme.night.gamma)) { + fprintf(stderr, + _("Gamma value must be between %.1f and %.1f.\n"), + MIN_GAMMA, MAX_GAMMA); + exit(EXIT_FAILURE); + } + + if (options.verbose) { + /* TRANSLATORS: The string in parenthesis is either + Daytime or Night (translated). */ + printf(_("Gamma (%s): %.3f, %.3f, %.3f\n"), + _("Daytime"), options.scheme.day.gamma[0], + options.scheme.day.gamma[1], + options.scheme.day.gamma[2]); + printf(_("Gamma (%s): %.3f, %.3f, %.3f\n"), + _("Night"), options.scheme.night.gamma[0], + options.scheme.night.gamma[1], + options.scheme.night.gamma[2]); + } + + transition_scheme_t *scheme = &options.scheme; + + /* Initialize gamma adjustment method. If method is NULL + try all methods until one that works is found. */ + gamma_state_t *method_state; + + /* Gamma adjustment not needed for print mode */ + if (options.mode != PROGRAM_MODE_PRINT) { + if (options.method != NULL) { + /* Use method specified on command line. */ + r = method_try_start( + options.method, &method_state, &config_state, + options.method_args); + if (r < 0) exit(EXIT_FAILURE); + } else { + /* Try all methods, use the first that works. */ + for (int i = 0; gamma_methods[i].name != NULL; i++) { + const gamma_method_t *m = &gamma_methods[i]; + if (!m->autostart) continue; + + r = method_try_start( + m, &method_state, &config_state, NULL); + if (r < 0) { + fputs(_("Trying next method...\n"), stderr); + continue; + } + + /* Found method that works. */ + printf(_("Using method `%s'.\n"), m->name); + options.method = m; + break; + } + + /* Failure if no methods were successful at this point. */ + if (options.method == NULL) { + fputs(_("No more methods to try.\n"), stderr); + exit(EXIT_FAILURE); + } + } + } + + config_ini_free(&config_state); + + switch (options.mode) { + case PROGRAM_MODE_ONE_SHOT: + case PROGRAM_MODE_PRINT: + { + location_t loc = { NAN, NAN }; + if (need_location) { + fputs(_("Waiting for current location" + " to become available...\n"), stderr); + + /* Wait for location provider. */ + int r = provider_get_location( + options.provider, location_state, -1, &loc); + if (r < 0) { + fputs(_("Unable to get location" + " from provider.\n"), stderr); + exit(EXIT_FAILURE); + } + + if (!location_is_valid(&loc)) { + exit(EXIT_FAILURE); + } + + print_location(&loc); + } + + double now; + r = systemtime_get_time(&now); + if (r < 0) { + fputs(_("Unable to read system time.\n"), stderr); + options.method->free(method_state); + exit(EXIT_FAILURE); + } + + period_t period; + double transition_prog; + if (options.scheme.use_time) { + int time_offset = get_seconds_since_midnight(now); + period = get_period_from_time(scheme, time_offset); + transition_prog = get_transition_progress_from_time( + scheme, time_offset); + } else { + /* Current angular elevation of the sun */ + double elevation = solar_elevation( + now, loc.lat, loc.lon); + if (options.verbose) { + /* TRANSLATORS: Append degree symbol if + possible. */ + printf(_("Solar elevation: %f\n"), elevation); + } + + period = get_period_from_elevation(scheme, elevation); + transition_prog = + get_transition_progress_from_elevation( + scheme, elevation); + } + + /* Use transition progress to set color temperature */ + color_setting_t interp; + interpolate_transition_scheme( + scheme, transition_prog, &interp); + + if (options.verbose || options.mode == PROGRAM_MODE_PRINT) { + print_period(period, transition_prog); + printf(_("Color temperature: %uK\n"), + interp.temperature); + printf(_("Brightness: %.2f\n"), + interp.brightness); + } + + if (options.mode != PROGRAM_MODE_PRINT) { + /* Adjust temperature */ + r = options.method->set_temperature( + method_state, &interp, options.preserve_gamma); + if (r < 0) { + fputs(_("Temperature adjustment failed.\n"), + stderr); + options.method->free(method_state); + exit(EXIT_FAILURE); + } + + /* In Quartz (macOS) the gamma adjustments will + automatically revert when the process exits. + Therefore, we have to loop until CTRL-C is received. + */ + if (strcmp(options.method->name, "quartz") == 0) { + fputs(_("Press ctrl-c to stop...\n"), stderr); + pause(); + } + } + } + break; + case PROGRAM_MODE_MANUAL: + { + if (options.verbose) { + printf(_("Color temperature: %uK\n"), + options.temp_set); + } + + /* Adjust temperature */ + color_setting_t manual = scheme->day; + manual.temperature = options.temp_set; + r = options.method->set_temperature( + method_state, &manual, options.preserve_gamma); + if (r < 0) { + fputs(_("Temperature adjustment failed.\n"), stderr); + options.method->free(method_state); + exit(EXIT_FAILURE); + } + + /* In Quartz (OSX) the gamma adjustments will automatically + revert when the process exits. Therefore, we have to loop + until CTRL-C is received. */ + if (strcmp(options.method->name, "quartz") == 0) { + fputs(_("Press ctrl-c to stop...\n"), stderr); + pause(); + } + } + break; + case PROGRAM_MODE_RESET: + { + /* Reset screen */ + color_setting_t reset; + color_setting_reset(&reset); + + r = options.method->set_temperature(method_state, &reset, 0); + if (r < 0) { + fputs(_("Temperature adjustment failed.\n"), stderr); + options.method->free(method_state); + exit(EXIT_FAILURE); + } + + /* In Quartz (OSX) the gamma adjustments will automatically + revert when the process exits. Therefore, we have to loop + until CTRL-C is received. */ + if (strcmp(options.method->name, "quartz") == 0) { + fputs(_("Press ctrl-c to stop...\n"), stderr); + pause(); + } + } + break; + case PROGRAM_MODE_CONTINUAL: + { + r = run_continual_mode( + options.provider, location_state, scheme, + options.method, method_state, + options.use_fade, options.preserve_gamma, + options.verbose); + if (r < 0) exit(EXIT_FAILURE); + } + break; + } + + /* Clean up gamma adjustment state */ + if (options.mode != PROGRAM_MODE_PRINT) { + options.method->free(method_state); + } + + /* Clean up location provider state */ + if (need_location) { + options.provider->free(location_state); + } + + return EXIT_SUCCESS; }