diff --git a/ambientd.c3 b/ambientd.c3 index 675d911..6cfd808 100644 --- a/ambientd.c3 +++ b/ambientd.c3 @@ -200,13 +200,24 @@ macro float @bezier(float t) // https://docs.kernel.org/admin-guide/abi-stable-files.html#abi-file-stable-sysfs-class-backlight -macro int @read_int_from_file(String path) => ((String)file::load_temp(path)[..^2]).to_int() ?? 0; +macro int? @read_int_from_file(String path) => ((String)file::load_temp(path)[..^2]).to_int(); macro void @write_int_to_file(String path, int i) => (void)file::save(path, string::tformat("%d\n", i)); -macro int @get_luminance() => @read_int_from_file(light_sensor_path); -macro int @get_max_backlight() => @read_int_from_file(backlight_path.tconcat("/max_brightness")); -macro int @get_backlight() => @read_int_from_file(backlight_path.tconcat("/brightness")); +macro int? @get_luminance() => @read_int_from_file(light_sensor_path); +macro int? @get_max_backlight() => @read_int_from_file(backlight_path.tconcat("/max_brightness")); +macro int? @get_backlight() => @read_int_from_file(backlight_path.tconcat("/brightness")); macro void @set_backlight(int v) => @write_int_to_file(backlight_path.tconcat("/brightness"), v); -macro bool @is_screen_on() => @read_int_from_file(backlight_path.tconcat("/bl_power")) == 0; +macro bool? @is_screen_on() => @read_int_from_file(backlight_path.tconcat("/bl_power")) == 0; + +macro @retry_every(#f, int ms = 100) +{ + const sz TRIES = 10; + for (sz i = 0; i < TRIES; i++) { + if (try x = #f) return x; + thread::sleep_ms(ms); + } + io::eprintfn("ERROR: tried to execute '%s' but it failed too many times (%d)", $stringify(#f), TRIES); + std::os::exit(1); +} fn void sigusr1_handler(CInt sig, void* act, void* oldact) @@ -223,32 +234,50 @@ fn void sigusr1_handler(CInt sig, void* act, void* oldact) // TODO: override config file with arguments fn void main(String[] args) { + bool verbose = false; + foreach (a : args[1..]) { + switch (a) { + case "-v": + verbose = true; + break; + case "-h": + io::printfn("ambientd [-hv]"); + std::os::exit(0); + default: + io::eprintfn("Unrecognized argument: '%s'", a); + std::os::exit(1); + } + } + update_config(); posix::install_signal_handler(libc::SIGUSR1, &sigusr1_handler); - filter.init(@get_luminance()); - float luminance_old = filter.update(@get_luminance(), 0.0); - int brightness_set = @get_backlight(); + int _l = @get_luminance() ?? 0; + filter.init(_l); + float luminance_old = filter.update(_l, 0.0); + int brightness_set = @retry_every(@get_backlight()); int user_offset = 0; - int backlight_max = @get_max_backlight(); + int backlight_max = @get_max_backlight() ?? 0; Time start = time::now(); while (true) { - if (!@is_screen_on()) { + if (!@is_screen_on() ?? false) { thread::sleep_ms(5000); continue; } + + // Check user offset + user_offset = @retry_every(@get_backlight(), update_interval_ms/2) - brightness_set; + int _lx = @retry_every(@get_luminance(), update_interval_ms/2); + Time now = time::now(); Time dt = (Time)(now - start); - // Check user offset - user_offset = @get_backlight() - brightness_set; - // Filtered luminance, depends heavily on the type of sensor, for the CF-SV7 // seems to be in lux - float luminance = filter.update(@get_luminance(), (float)dt.to_seconds()) * light_sensor_k; + float luminance = filter.update(_lx, (float)dt.to_seconds()) * light_sensor_k; // Percent of the luminance received compared to what the panel can output float p = min((luminance/backlight_max_luminance), 1.0f); @@ -258,9 +287,9 @@ fn void main(String[] args) // perceived luminance is non-linear, I think the inverse square law is correct int new_brightness = (int)(math::pow(p*1.1f, 0.5f)*backlight_max); brightness_set = new_brightness; - @set_backlight(brightness_set + user_offset); + @set_backlight(max(brightness_set + user_offset, 0)); - // io::printfn("%f, %d, %d", luminance, brightness_set, user_offset); + if (verbose) io::printfn("%f, %d, %d", luminance, brightness_set, user_offset); start = now; thread::sleep_ms(update_interval_ms);