Split state from config, cleanup
parent
67896358cf
commit
7bd167e9d3
24
color_math.c
24
color_math.c
|
@ -24,11 +24,9 @@ static double degrees(double radians) {
|
||||||
return radians * 180.0 / M_PI;
|
return radians * 180.0 / M_PI;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sun_angle(struct tm *tm, double longitude, double latitude, time_t *sunrise, time_t *sunset, double angle) {
|
void calc_sun(struct tm *tm, double longitude, double latitude, struct sun *sun) {
|
||||||
// https://www.esrl.noaa.gov/gmd/grad/solcalc/solareqns.PDF
|
// https://www.esrl.noaa.gov/gmd/grad/solcalc/solareqns.PDF
|
||||||
double year_rad = 2 * M_PI /
|
double year_rad = 2 * M_PI / days_in_year(tm->tm_year) * (tm->tm_yday - 1);
|
||||||
days_in_year(tm->tm_year) *
|
|
||||||
(tm->tm_yday - 1 + (tm->tm_hour - 12)/24);
|
|
||||||
double eqtime = 229.18 * (0.000075 +
|
double eqtime = 229.18 * (0.000075 +
|
||||||
0.001868 * cos(year_rad) -
|
0.001868 * cos(year_rad) -
|
||||||
0.032077 * sin(year_rad) -
|
0.032077 * sin(year_rad) -
|
||||||
|
@ -41,16 +39,16 @@ static void sun_angle(struct tm *tm, double longitude, double latitude, time_t *
|
||||||
0.000907 * sin(2*year_rad) -
|
0.000907 * sin(2*year_rad) -
|
||||||
0.002697 * cos(3*year_rad) +
|
0.002697 * cos(3*year_rad) +
|
||||||
0.00148 * sin(3*year_rad);
|
0.00148 * sin(3*year_rad);
|
||||||
double ha = degrees(acos(
|
double ha1 = degrees(acos(
|
||||||
cos(radians(angle)) / (cos(radians(latitude)) * cos(decl)) -
|
cos(radians(SOLAR_HORIZON + SOLAR_START_TWILIGHT)) / (cos(radians(latitude)) * cos(decl)) -
|
||||||
tan(radians(latitude)) * tan(decl)));
|
tan(radians(latitude)) * tan(decl)));
|
||||||
*sunrise = (720 - 4 * (longitude + fabs(ha)) - eqtime) * 60;
|
double ha2 = degrees(acos(
|
||||||
*sunset = (720 - 4 * (longitude - fabs(ha)) - eqtime) * 60;
|
cos(radians(SOLAR_HORIZON + SOLAR_END_TWILIGHT)) / (cos(radians(latitude)) * cos(decl)) -
|
||||||
}
|
tan(radians(latitude)) * tan(decl)));
|
||||||
|
sun->dawn = (720 - 4 * (longitude + fabs(ha1)) - eqtime) * 60;
|
||||||
void sun(struct tm *tm, double longitude, double latitude, time_t *dawn, time_t *sunrise, time_t *sunset, time_t *dusk) {
|
sun->sunrise = (720 - 4 * (longitude + fabs(ha2)) - eqtime) * 60;
|
||||||
sun_angle(tm, longitude, latitude, dawn, dusk, SOLAR_HORIZON + SOLAR_START_TWILIGHT);
|
sun->sunset = (720 - 4 * (longitude - fabs(ha2)) - eqtime) * 60;
|
||||||
sun_angle(tm, longitude, latitude, sunrise, sunset, SOLAR_HORIZON + SOLAR_END_TWILIGHT);
|
sun->dusk = (720 - 4 * (longitude - fabs(ha1)) - eqtime) * 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int illuminant_d(int temp, double *x, double *y) {
|
static int illuminant_d(int temp, double *x, double *y) {
|
||||||
|
|
11
color_math.h
11
color_math.h
|
@ -1,7 +1,16 @@
|
||||||
#ifndef _COLOR_MATH_H
|
#ifndef _COLOR_MATH_H
|
||||||
#define _COLOR_MATH_H
|
#define _COLOR_MATH_H
|
||||||
|
|
||||||
void sun(struct tm *tm, double longitude, double latitude, time_t *dawn, time_t *sunrise, time_t *sunset, time_t *dusk);
|
#include "time.h"
|
||||||
|
|
||||||
|
struct sun {
|
||||||
|
time_t dawn;
|
||||||
|
time_t sunrise;
|
||||||
|
time_t sunset;
|
||||||
|
time_t dusk;
|
||||||
|
};
|
||||||
|
|
||||||
|
void calc_sun(struct tm *tm, double longitude, double latitude, struct sun *sun);
|
||||||
double clamp(double value);
|
double clamp(double value);
|
||||||
void calc_whitepoint(int temp, double *rw, double *gw, double *bw);
|
void calc_whitepoint(int temp, double *rw, double *gw, double *bw);
|
||||||
|
|
||||||
|
|
113
main.c
113
main.c
|
@ -63,17 +63,17 @@ static int set_timer(timer_t timer, time_t deadline) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct context {
|
struct config {
|
||||||
int high_temp;
|
int high_temp;
|
||||||
int low_temp;
|
int low_temp;
|
||||||
int duration;
|
int duration;
|
||||||
double longitude;
|
double longitude;
|
||||||
double latitude;
|
double latitude;
|
||||||
|
};
|
||||||
|
|
||||||
time_t dawn;
|
struct context {
|
||||||
time_t sunrise;
|
struct config config;
|
||||||
time_t sunset;
|
struct sun sun;
|
||||||
time_t dusk;
|
|
||||||
|
|
||||||
time_t dawn_step_time;
|
time_t dawn_step_time;
|
||||||
time_t dusk_step_time;
|
time_t dusk_step_time;
|
||||||
|
@ -270,38 +270,41 @@ static void set_temperature(struct wl_list *outputs, int temp, int gamma) {
|
||||||
static int anim_kelvin_step = 25;
|
static int anim_kelvin_step = 25;
|
||||||
|
|
||||||
static void recalc_stops(struct context *ctx, time_t now) {
|
static void recalc_stops(struct context *ctx, time_t now) {
|
||||||
time_t day = now - (now % 86400);
|
if (now < ctx->sun.dusk) {
|
||||||
if (ctx->dusk == 0) {
|
|
||||||
// First calculation
|
|
||||||
} else if (now >= ctx->dusk) {
|
|
||||||
day += 86400;
|
|
||||||
} else if (day < ctx->dusk) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tm tm = { 0 };
|
time_t day = now - (now % 86400);
|
||||||
gmtime_r(&now, &tm);
|
if (day < ctx->sun.dusk) {
|
||||||
sun(&tm, ctx->longitude, ctx->latitude, &ctx->dawn, &ctx->sunrise, &ctx->sunset, &ctx->dusk);
|
day += 86400;
|
||||||
if (ctx->duration != -1) {
|
|
||||||
ctx->dawn = ctx->sunrise - ctx->duration;
|
|
||||||
ctx->dusk = ctx->sunset + ctx->duration;
|
|
||||||
}
|
}
|
||||||
ctx->dawn += day;
|
|
||||||
ctx->sunrise += day;
|
|
||||||
ctx->sunset += day;
|
|
||||||
ctx->dusk += day;
|
|
||||||
|
|
||||||
int temp_diff = ctx->high_temp - ctx->low_temp;
|
struct tm tm = { 0 };
|
||||||
ctx->dawn_step_time = (ctx->sunrise - ctx->dawn) * anim_kelvin_step / temp_diff;
|
gmtime_r(&day, &tm);
|
||||||
ctx->dusk_step_time = (ctx->dusk - ctx->sunset) * anim_kelvin_step / temp_diff;
|
calc_sun(&tm, ctx->config.longitude, ctx->config.latitude, &ctx->sun);
|
||||||
|
if (ctx->config.duration != -1) {
|
||||||
|
ctx->sun.dawn = ctx->sun.sunrise - ctx->config.duration;
|
||||||
|
ctx->sun.dusk = ctx->sun.sunset + ctx->config.duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Cap on eternal days?
|
||||||
|
ctx->sun.dawn += day;
|
||||||
|
ctx->sun.sunrise += day;
|
||||||
|
ctx->sun.sunset += day;
|
||||||
|
ctx->sun.dusk += day;
|
||||||
|
assert(ctx->sun.dusk > now);
|
||||||
|
|
||||||
|
int temp_diff = ctx->config.high_temp - ctx->config.low_temp;
|
||||||
|
ctx->dawn_step_time = (ctx->sun.sunrise - ctx->sun.dawn) * anim_kelvin_step / temp_diff;
|
||||||
|
ctx->dusk_step_time = (ctx->sun.dusk - ctx->sun.sunset) * anim_kelvin_step / temp_diff;
|
||||||
|
|
||||||
struct tm dawn, sunrise, sunset, dusk;
|
struct tm dawn, sunrise, sunset, dusk;
|
||||||
localtime_r(&ctx->dawn, &dawn);
|
localtime_r(&ctx->sun.dawn, &dawn);
|
||||||
localtime_r(&ctx->sunrise, &sunrise);
|
localtime_r(&ctx->sun.sunrise, &sunrise);
|
||||||
localtime_r(&ctx->sunset, &sunset);
|
localtime_r(&ctx->sun.sunset, &sunset);
|
||||||
localtime_r(&ctx->dusk, &dusk);
|
localtime_r(&ctx->sun.dusk, &dusk);
|
||||||
fprintf(stderr, "calculated new sun trajectory: dawn %02d:%02d, sunrise %02d:%02d, sunset %02d:%02d, dusk %02d:%02d\n",
|
fprintf(stderr, "calculated new sun trajectory: dawn %02d:%02d, sunrise %02d:%02d, sunset %02d:%02d, dusk %02d:%02d\n",
|
||||||
dawn.tm_hour, dusk.tm_min,
|
dawn.tm_hour, dawn.tm_min,
|
||||||
sunrise.tm_hour, sunrise.tm_min,
|
sunrise.tm_hour, sunrise.tm_min,
|
||||||
sunset.tm_hour, sunset.tm_min,
|
sunset.tm_hour, sunset.tm_min,
|
||||||
dusk.tm_hour, dusk.tm_min);
|
dusk.tm_hour, dusk.tm_min);
|
||||||
|
@ -314,31 +317,30 @@ static int interpolate_temperature(time_t now, time_t start, time_t stop, int te
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_temperature(const struct context *ctx, time_t now) {
|
static int get_temperature(const struct context *ctx, time_t now) {
|
||||||
if (now < ctx->dawn) {
|
if (now < ctx->sun.dawn) {
|
||||||
return ctx->low_temp;
|
return ctx->config.low_temp;
|
||||||
} else if (now < ctx->sunrise) {
|
} else if (now < ctx->sun.sunrise) {
|
||||||
return interpolate_temperature(now, ctx->dawn, ctx->sunrise, ctx->low_temp, ctx->high_temp);
|
return interpolate_temperature(now, ctx->sun.dawn, ctx->sun.sunrise, ctx->config.low_temp, ctx->config.high_temp);
|
||||||
} else if (now < ctx->sunset) {
|
} else if (now < ctx->sun.sunset) {
|
||||||
return ctx->high_temp;
|
return ctx->config.high_temp;
|
||||||
} else if (now < ctx->dusk) {
|
} else if (now < ctx->sun.dusk) {
|
||||||
return interpolate_temperature(now, ctx->sunset, ctx->dusk, ctx->high_temp, ctx->low_temp);
|
return interpolate_temperature(now, ctx->sun.sunset, ctx->sun.dusk, ctx->config.high_temp, ctx->config.low_temp);
|
||||||
} else {
|
} else {
|
||||||
return ctx->low_temp;
|
return ctx->config.low_temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void update_timer(struct context *ctx, timer_t timer, time_t now) {
|
static void update_timer(struct context *ctx, timer_t timer, time_t now) {
|
||||||
assert(now < ctx->dusk);
|
assert(now < ctx->sun.dusk);
|
||||||
|
|
||||||
time_t deadline;
|
time_t deadline;
|
||||||
if (now < ctx->dawn) {
|
if (now < ctx->sun.dawn) {
|
||||||
deadline = ctx->dawn;
|
deadline = ctx->sun.dawn;
|
||||||
} else if (now < ctx->sunrise) {
|
} else if (now < ctx->sun.sunrise) {
|
||||||
deadline = now + ctx->dawn_step_time;
|
deadline = now + ctx->dawn_step_time;
|
||||||
} else if (now < ctx->sunset) {
|
} else if (now < ctx->sun.sunset) {
|
||||||
deadline = ctx->sunset;
|
deadline = ctx->sun.sunset;
|
||||||
} else if (now < ctx->dusk) {
|
} else if (now < ctx->sun.dusk) {
|
||||||
deadline = now + ctx->dusk_step_time;
|
deadline = now + ctx->dusk_step_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,9 +415,14 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
// Initialize defaults
|
// Initialize defaults
|
||||||
struct context ctx = {
|
struct context ctx = {
|
||||||
|
.sun = { 0 },
|
||||||
|
.config = {
|
||||||
.high_temp = 6500,
|
.high_temp = 6500,
|
||||||
.low_temp = 4000,
|
.low_temp = 4000,
|
||||||
.duration = -1,
|
.duration = -1,
|
||||||
|
.latitude = 0,
|
||||||
|
.longitude = 0,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
double gamma = 1.0;
|
double gamma = 1.0;
|
||||||
wl_list_init(&ctx.outputs);
|
wl_list_init(&ctx.outputs);
|
||||||
|
@ -442,20 +449,20 @@ int main(int argc, char *argv[]) {
|
||||||
while ((opt = getopt(argc, argv, "hT:t:g:d:l:L:")) != -1) {
|
while ((opt = getopt(argc, argv, "hT:t:g:d:l:L:")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'T':
|
case 'T':
|
||||||
ctx.high_temp = strtol(optarg, NULL, 10);
|
ctx.config.high_temp = strtol(optarg, NULL, 10);
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
ctx.low_temp = strtol(optarg, NULL, 10);
|
ctx.config.low_temp = strtol(optarg, NULL, 10);
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
ctx.latitude = strtod(optarg, NULL);
|
ctx.config.latitude = strtod(optarg, NULL);
|
||||||
break;
|
break;
|
||||||
case 'L':
|
case 'L':
|
||||||
ctx.longitude = strtod(optarg, NULL);
|
ctx.config.longitude = strtod(optarg, NULL);
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
fprintf(stderr, "using animation duration override\n");
|
fprintf(stderr, "using animation duration override\n");
|
||||||
ctx.duration = strtod(optarg, NULL) * 60;
|
ctx.config.duration = strtod(optarg, NULL) * 60;
|
||||||
break;
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
gamma = strtod(optarg, NULL);
|
gamma = strtod(optarg, NULL);
|
||||||
|
@ -467,9 +474,9 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.high_temp == ctx.low_temp) {
|
if (ctx.config.high_temp == ctx.config.low_temp) {
|
||||||
fprintf(stderr, "high (%d) and low (%d) temperature must not be identical\n",
|
fprintf(stderr, "high (%d) and low (%d) temperature must not be identical\n",
|
||||||
ctx.high_temp, ctx.low_temp);
|
ctx.config.high_temp, ctx.config.low_temp);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue