Advertisement
Guest User

Untitled

a guest
Feb 20th, 2017
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.66 KB | None | 0 0
  1. #!/strawberry/perl/bin/wperl.exe
  2.  
  3. =head1 NAME
  4.  
  5. auto-brightness.pl - adjust display brightness based on a nearby traffic cam
  6.  
  7. =head1 DESCRIPTION
  8.  
  9. ClickMonitorDDC is a really handy tool for desktop PCs, as you can set hotkeys
  10. to adjust display brightness as conditions change. It gets a bit repetitive
  11. through the day though, so in absence of a light sensor or local webcam, I used
  12. a nearby traffic cam (thanks VDOT!) to get light samples and adjust
  13. accordingly.
  14.  
  15. This script is set to run via wperl.exe in my task manager, every 30 minutes
  16. through the day. It quietly tells ClickMonitorDDC to tweak display brightness
  17. as needed.
  18.  
  19. =head1 ISSUES
  20.  
  21. My displays don't listen to DDC commands when asleep, which is fair, so
  22. ClickMonitorDDC shows an incorrect number compared to the real backlight when
  23. the displays wake up. Windows doesn't have an easy "no longer idle" hook and
  24. I haven't moved on any of the wacky solutions to that you can find out there.
  25.  
  26. You can set up another task that triggers at unlock though, to run this script
  27. with the extra arg 'refresh', to reassert the last brightness the script tried
  28. to set.
  29.  
  30. =head1 DEPENDENCIES
  31.  
  32. Strawberry Perl 5.24, ffmpeg, ClickMonitorDDC
  33.  
  34. =cut
  35.  
  36. use 5.024;
  37. use warnings;
  38. use strict;
  39. use autodie ':all';
  40.  
  41. use feature 'signatures';
  42. no warnings 'experimental::signatures';
  43.  
  44. use GD;
  45. use IPC::Cmd qw(can_run);
  46. use List::Util qw(sum min max);
  47. use Path::Tiny;
  48. use Time::HiRes;
  49. use Win32::Process;
  50.  
  51. my $stream_url = 'rtsp://8.15.251.53:1935/rtplive/FairfaxVideo0520';
  52. my $sample_low = 26; # min brightness here (of 255)
  53. my $sample_high = 120; # max brightness here (of 255)
  54.  
  55. GD::Image->trueColor(1);
  56.  
  57. my $tmp = Path::Tiny->tempdir;
  58. my $DDC = path($ENV{USERPROFILE})->child('bin/ClickMonitorDDC.EXE');
  59. my $state = path("$0.state");
  60.  
  61. sub main($cmd = '') {
  62. my $current = $state->touch->slurp;
  63.  
  64. system "$DDC b$current", return 0
  65. if $cmd eq 'refresh' && $current ne '';
  66.  
  67. my $backlight = backlight_value(get_sample_from(camera_capture()));
  68.  
  69. # say "b$backlight";
  70. adjust($current || 0, $backlight);
  71. $state->spew($backlight);
  72.  
  73. return 0;
  74. }
  75.  
  76. # gradually change brightness
  77. sub adjust ($from, $to) {
  78. for my $step ($from <= $to ? ($from .. $to) : reverse($to .. $from)) {
  79. system "$DDC b$step";
  80. sleep 0.5;
  81. }
  82. }
  83.  
  84. # Get 5 frames, one per sec, return
  85. sub camera_capture {
  86. my $path = $tmp->child("sample-%d.png");
  87. run_hidden("ffmpeg -i $stream_url -rtsp_transport tcp -vframes 5 -vf fps=1 -loglevel fatal $path");
  88. $tmp->children(qr/^sample-\d+\.png$/);
  89. }
  90.  
  91. # for all files, resample (a chunk from the top w/o the banner) down to 1px,
  92. # get luminance, average out
  93. sub get_sample_from (@files) {
  94. sum(
  95. map {
  96. my $sample = GD::Image->new(1, 1);
  97. $sample->copyResampled(
  98. GD::Image->newFromPng("$_"),
  99. 0, 0, 5, 42,
  100. 1, 1, 311, 70,
  101. );
  102.  
  103. my @rgb = $sample->rgb($sample->getPixel(0, 0));
  104. (min(@rgb) + max(@rgb)) / 2;
  105. } @files
  106. ) / scalar(@files);
  107. }
  108.  
  109. # Linear scale + clamp
  110. sub backlight_value ($lum) {
  111. # say sprintf 'luminance: %d / 255, %d%%', $lum, ($lum / 255 * 100);
  112. clamp(int(($lum - $sample_low) / ($sample_high - $sample_low) * 100));
  113. }
  114.  
  115. sub clamp ($n, $min = 0, $max = 100) {
  116. max(min($n, $max), $min);
  117. }
  118.  
  119. # Keep ffmpeg from popping a console window when we're running via wperl as
  120. # a scheduled task.
  121. sub run_hidden ($cmdline) {
  122. my ($prog) = split /\s+/, $cmdline;
  123. my $fullpath = can_run($prog)
  124. or die "Can't find $prog in path";
  125.  
  126. my ($proc, $code);
  127. Win32::Process::Create($proc, $fullpath, $cmdline, 0, CREATE_NO_WINDOW, '.')
  128. || die "Failed to execute $cmdline";
  129. $proc->Wait(INFINITE);
  130. $proc->GetExitCode($code);
  131.  
  132. $code == 0
  133. or die "$prog exited with failure $code";
  134. }
  135.  
  136. exit main(@ARGV);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement