~kennylevinsen/wlsunset

111181106e416b6af90784c627d7b1100c3dba7d — Kenny Levinsen 27 days ago 93d7d01
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.
2 files changed, 92 insertions(+), 24 deletions(-)

M main.c
M wlsunset.1.scd
M main.c => main.c +81 -24
@@ 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 <temp>     set low temperature (default: 4000)\n"
"  -T <temp>     set high temperature (default: 6500)\n"
"  -l <lat>      set latitude (e.g. 39.9)\n"
"  -L <long>     set longitude (e.g. 116.3)\n"
"  -g <gamma>    set gamma (default: 1.0)\n";
"  -h             show this help message\n"
"  -t <temp>      set low temperature (default: 4000)\n"
"  -T <temp>      set high temperature (default: 6500)\n"
"  -l <lat>       set latitude (e.g. 39.9)\n"
"  -L <long>      set longitude (e.g. 116.3)\n"
"  -S <sunrise>   set manual sunrise (e.g. 06:30)\n"
"  -s <sunset>    set manual sunset (e.g. 18:30)\n"
"  -d <duration>  set manual duration in seconds (e.g. 1800)\n"
"  -g <gamma>     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);
}

M wlsunset.1.scd => wlsunset.1.scd +11 -0
@@ 26,6 26,17 @@ wlr-gamma-control-unstable-v1
*-L* <long>
	set longitude (e.g. 116.3)

*-S* <sunrise>
	Manual time for sunrise as HH:MM (e.g. 06:30)

*-s* <sunset>
	Manual time for sunset as HH:MM (e.g. 18:30)

*-d* <duration>
	Manual animation time in seconds (e.g. 1800)

	Only applicable when using manual sunset/sunrise times.

*-g* <gamma>
	set gamma (default: 1.0)