From 111181106e416b6af90784c627d7b1100c3dba7d Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Fri, 29 Jan 2021 17:32:51 +0100 Subject: [PATCH] Add support for manual sunset/sunrise The new -S/-s/-d flags allow for manually specifying the time of sunset, ssunrise in the format of HH:MM, and the transitional animation duration in seconds, respectively. This is implemented by sidestepping the calc_sun call in manual mode. The rest of wlsunset operates as usual. --- main.c | 105 ++++++++++++++++++++++++++++++++++++++----------- wlsunset.1.scd | 11 ++++++ 2 files changed, 92 insertions(+), 24 deletions(-) diff --git a/main.c b/main.c index 3f85a9f..2ea690b 100644 --- a/main.c +++ b/main.c @@ -88,7 +88,10 @@ struct config { double longitude; double latitude; - int duration; + bool manual_time; + time_t sunrise; + time_t sunset; + time_t duration; }; enum state { @@ -167,10 +170,22 @@ static void recalc_stops(struct context *ctx, time_t now) { time_t last_day = ctx->calc_day; ctx->calc_day = day; + enum sun_condition cond = NORMAL; + + if (ctx->config.manual_time) { + ctx->state = STATE_NORMAL; + ctx->sun.dawn = ctx->config.sunrise - ctx->config.duration + day; + ctx->sun.sunrise = ctx->config.sunrise + day; + ctx->sun.sunset = ctx->config.sunset + day; + ctx->sun.dusk = ctx->config.sunset + ctx->config.duration + day; + + goto done; + } + struct sun sun; struct tm tm = { 0 }; gmtime_r(&day, &tm); - enum sun_condition cond = calc_sun(&tm, ctx->config.latitude, &sun); + cond = calc_sun(&tm, ctx->config.latitude, &sun); switch (cond) { case NORMAL: @@ -211,6 +226,8 @@ static void recalc_stops(struct context *ctx, time_t now) { default: abort(); } + +done: ctx->condition = cond; int temp_diff = ctx->config.high_temp - ctx->config.low_temp; @@ -614,16 +631,18 @@ static int setup_timer(struct context *ctx) { } static int wlrun(struct config cfg) { - init_time(); // Initialize defaults struct context ctx = { .sun = { 0 }, .condition = SUN_CONDITION_LAST, - .longitude_time_offset = longitude_time_offset(cfg.longitude), .state = STATE_INITIAL, .config = cfg, }; + if (!cfg.manual_time) { + ctx.longitude_time_offset = longitude_time_offset(cfg.longitude); + } + wl_list_init(&ctx.outputs); if (setup_timer(&ctx) == -1) { @@ -682,29 +701,43 @@ static int wlrun(struct config cfg) { return EXIT_SUCCESS; } +static int parse_time_of_day(const char *s, time_t *time) { + struct tm tm = { 0 }; + + if (strptime(s, "%H:%M", &tm) == NULL) { + return -1; + } + *time = tm.tm_hour * 3600 + tm.tm_min * 60 + timezone; + return 0; +} + static const char usage[] = "usage: %s [options]\n" -" -h show this help message\n" -" -t set low temperature (default: 4000)\n" -" -T set high temperature (default: 6500)\n" -" -l set latitude (e.g. 39.9)\n" -" -L set longitude (e.g. 116.3)\n" -" -g set gamma (default: 1.0)\n"; +" -h show this help message\n" +" -t set low temperature (default: 4000)\n" +" -T set high temperature (default: 6500)\n" +" -l set latitude (e.g. 39.9)\n" +" -L set longitude (e.g. 116.3)\n" +" -S set manual sunrise (e.g. 06:30)\n" +" -s set manual sunset (e.g. 18:30)\n" +" -d set manual duration in seconds (e.g. 1800)\n" +" -g set gamma (default: 1.0)\n"; int main(int argc, char *argv[]) { #ifdef SPEEDRUN fprintf(stderr, "warning: speedrun mode enabled\n"); #endif + init_time(); struct config config = { - .latitude = 0, - .longitude = 0, + .latitude = NAN, + .longitude = NAN, .high_temp = 6500, .low_temp = 4000, .gamma = 1.0, }; int opt; - while ((opt = getopt(argc, argv, "ht:T:l:L:d:g:")) != -1) { + while ((opt = getopt(argc, argv, "ht:T:l:L:S:s:d:g:")) != -1) { switch (opt) { case 't': config.low_temp = strtol(optarg, NULL, 10); @@ -718,6 +751,23 @@ int main(int argc, char *argv[]) { case 'L': config.longitude = strtod(optarg, NULL); break; + case 'S': + if (parse_time_of_day(optarg, &config.sunrise) != 0) { + fprintf(stderr, "invalid time, expected HH:MM, got %s\n", optarg); + return EXIT_FAILURE; + } + config.manual_time = true; + break; + case 's': + if (parse_time_of_day(optarg, &config.sunset) != 0) { + fprintf(stderr, "invalid time, expected HH:MM, got %s\n", optarg); + return EXIT_FAILURE; + } + config.manual_time = true; + break; + case 'd': + config.duration = strtol(optarg, NULL, 10); + break; case 'g': config.gamma = strtod(optarg, NULL); break; @@ -731,20 +781,27 @@ int main(int argc, char *argv[]) { if (config.high_temp <= config.low_temp) { fprintf(stderr, "high temp (%d) must be higher than low (%d) temp\n", config.high_temp, config.low_temp); - return -1; - } - if (config.latitude > 90.0 || config.latitude < -90.0) { - fprintf(stderr, "latitude (%lf) must be in interval [-90,90]\n", - config.latitude); return EXIT_FAILURE; } - config.latitude = RADIANS(config.latitude); - if (config.longitude > 180.0 || config.longitude < -180.0) { - fprintf(stderr, "longitude (%lf) must be in interval [-180,180]\n", - config.longitude); - return EXIT_FAILURE; + if (config.manual_time) { + if (!isnan(config.latitude) || !isnan(config.longitude)) { + fprintf(stderr, "latitude and longitude are not valid in manual time mode\n"); + return EXIT_FAILURE; + } + } else { + if (config.latitude > 90.0 || config.latitude < -90.0) { + fprintf(stderr, "latitude (%lf) must be in interval [-90,90]\n", + config.latitude); + return EXIT_FAILURE; + } + config.latitude = RADIANS(config.latitude); + if (config.longitude > 180.0 || config.longitude < -180.0) { + fprintf(stderr, "longitude (%lf) must be in interval [-180,180]\n", + config.longitude); + return EXIT_FAILURE; + } + config.longitude = RADIANS(config.longitude); } - config.longitude = RADIANS(config.longitude); return wlrun(config); } diff --git a/wlsunset.1.scd b/wlsunset.1.scd index d7787f1..c62f2bc 100644 --- a/wlsunset.1.scd +++ b/wlsunset.1.scd @@ -26,6 +26,17 @@ wlr-gamma-control-unstable-v1 *-L* set longitude (e.g. 116.3) +*-S* + Manual time for sunrise as HH:MM (e.g. 06:30) + +*-s* + Manual time for sunset as HH:MM (e.g. 18:30) + +*-d* + Manual animation time in seconds (e.g. 1800) + + Only applicable when using manual sunset/sunrise times. + *-g* set gamma (default: 1.0)