Last active
September 20, 2022 17:29
-
-
Save jbarrett/5cdc000789bc18c1bdf2e9ef2a9997b6 to your computer and use it in GitHub Desktop.
Quick and dirty power profile switching script - detects fullscreen state or process name from a list
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!perl.exe | |
# Attempt to set power profile based on whether fullscreen app (game) running OR process name | |
# No guarantees if you have more than one monitor :) | |
# Edit these | |
# > powercfg /list | |
my $LOW = 'a1841308-3541-4fab-bc81-f71556f20b4a'; | |
my $BALANCED = '381b4222-f694-41f0-9685-ff5bb260df2e'; | |
my $HIGH = '8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c'; | |
my $DEFAULT = $LOW; | |
my $HIGH_PROCESSES = [ qw/ | |
Rack.exe | |
/ ]; | |
# Getting a window title from the foreground window HWND seems easier than process or exe name, | |
# so blacklist is strings or regexen... | |
my $BLACKLIST = [ | |
qr/Mozilla\ Firefox/i, | |
'VLC media player', | |
]; | |
my $CHECK_TIME = 15; # seconds | |
# Maybe don't edit below here | |
use Win32::API; | |
use Win32::Process::List; | |
use IO::Async::Loop; | |
use IO::Async::Timer::Periodic; | |
use feature qw/ state /; | |
use experimental qw/ signatures /; | |
my $loop = IO::Async::Loop->new; | |
my $SHQueryUserNotificationState = Win32::API::More->new(qw/ | |
shell32 SHQueryUserNotificationState P P | |
/); | |
my $GetForegroundWindow = Win32::API::More->new( | |
'user32', 'GetForegroundWindow', '', 'N' | |
); | |
my $GetWindowText = Win32::API::More->new(qw/ | |
user32 GetWindowText NPI I | |
/); | |
# https://stackoverflow.com/a/58755620 | |
# https://learn.microsoft.com/en-us/windows/win32/api/shellapi/ne-shellapi-query_user_notification_state | |
my $fullscreen_states = [ 2, 3 ]; | |
sub set_profile( $profile = $DEFAULT ) { | |
state $last = ''; | |
if ( $last ne $profile ) { | |
system( qw{ powercfg /setactive }, $profile ); # 😬 | |
} | |
$last = $profile; | |
} | |
sub check_high_performance_app { | |
my $process_list = Win32::Process::List->new; | |
grep { $process_list->GetProcessPid($_) } @{ $HIGH_PROCESSES }; | |
} | |
sub foreground_window_title { | |
my $buf = ' ' x 1024; | |
my $hwnd = $GetForegroundWindow->Call(); | |
my $chars = $GetWindowText->Call( $hwnd, $buf, 1023 ); | |
substr $buf, 0, $chars; | |
} | |
sub foreground_window_not_in_blacklist { | |
my $title = foreground_window_title; | |
! grep { $title =~ $_ } @{ $BLACKLIST }; | |
} | |
sub check_fullscreen_app { | |
# This parameter packing is likely wrong | |
my $quns = pack('P'); | |
$SHQueryUserNotificationState->Call( $quns ); | |
my $state = unpack('L', $quns); | |
foreground_window_not_in_blacklist && grep { $state == $_ } @{ $fullscreen_states }; | |
} | |
$loop->add( | |
IO::Async::Timer::Periodic->new( | |
interval => $CHECK_TIME, | |
reschedule => 'drift', | |
on_tick => sub { | |
if ( check_fullscreen_app || check_high_performance_app ) { | |
set_profile( $HIGH ); | |
} | |
else { | |
set_profile( $DEFAULT ); | |
} | |
} | |
)->start | |
); | |
$loop->run; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment