Skip to content

Instantly share code, notes, and snippets.

@jbarrett
Last active September 20, 2022 17:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jbarrett/5cdc000789bc18c1bdf2e9ef2a9997b6 to your computer and use it in GitHub Desktop.
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
#!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