Skip to content

Commit be9150f

Browse files
committed
Winpower
0 parents  commit be9150f

15 files changed

+1894
-0
lines changed

.gitignore

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
env/
2+
__pycache__/
3+
*-report.html
4+
*.spec
5+
*.txt
6+
dist/
7+
build/
8+
Output/

LICENSE

+661
Large diffs are not rendered by default.

README.md

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<p align="center">
2+
<img src="./icon.svg" width="100" height="100"/>
3+
</p>
4+
5+
<h3 align="center">Winpower</h3>
6+
7+
<p align="center">Improved power settings for Windows</p>
8+
9+
## 💻 Preview
10+
11+
<p align="center">
12+
<img src="./preview.png"/>
13+
</p>
14+
15+
## ✨ Features
16+
17+
- Add custom sleep and screen shutdown times.
18+
- Write custom scripts.
19+
- Execute scripts, shutdown, restart and lock commands after specified time.
20+
- Generate reports.
21+
- Manage changed settings to cancel or apply them.
22+
23+
---
24+
25+
<p align="center"><a href="https://www.patreon.com/axorax">Support me on Patreon</a> — <a href="https://github.com/axorax/socials">Check out my socials</a></p>

build.bat

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
@echo off
2+
3+
pyinstaller ^
4+
--name="Winpower" ^
5+
--onefile ^
6+
--strip ^
7+
--clean ^
8+
--paths=env/Lib/site-packages ^
9+
--add-data="env/Lib/site-packages/sv_ttk;sv_ttk" ^
10+
--add-data="icon.ico;." ^
11+
--noconsole ^
12+
--icon=icon.png ^
13+
main.py

build.py

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import subprocess
2+
3+
subprocess.run([
4+
"pyinstaller",
5+
"--name=Winpower",
6+
"--onefile",
7+
"--strip",
8+
"--clean",
9+
"--paths=env/Lib/site-packages",
10+
"--add-data=env/Lib/site-packages/sv_ttk:sv_ttk",
11+
"--add-data=icon.ico:.",
12+
"--noconsole",
13+
"--icon=icon.png",
14+
"main.py"
15+
])

build.sh

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/bin/bash
2+
3+
pyinstaller \
4+
--name="Winpower" \
5+
--onefile \
6+
--strip \
7+
--clean \
8+
--paths=env/Lib/site-packages \
9+
--add-data="env/Lib/site-packages/sv_ttk:sv_ttk" \
10+
--add-data="icon.ico:." \
11+
--noconsole \
12+
--icon=icon.png \
13+
main.py

core.py

+233
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
import os
2+
import re
3+
import ctypes
4+
import subprocess
5+
6+
power_schemes = {
7+
"Best power efficiency": "a1841308-3541-4fab-bc81-f71556f20b4a",
8+
"Balanced": "381b4222-f694-41f0-9685-ff5bb260df2e",
9+
"Best performance": "8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c",
10+
}
11+
12+
CREATE_NO_WINDOW = 0x08000000
13+
14+
15+
def get_power_mode():
16+
try:
17+
output = subprocess.check_output(
18+
["powercfg", "/getactivescheme"],
19+
encoding="utf-8",
20+
creationflags=CREATE_NO_WINDOW,
21+
)
22+
for mode, guid in power_schemes.items():
23+
if guid in output:
24+
return mode
25+
return "Unknown"
26+
except subprocess.CalledProcessError:
27+
return "Unknown"
28+
29+
30+
def set_power_mode(mode):
31+
if mode in power_schemes:
32+
try:
33+
subprocess.check_call(
34+
["powercfg", "/setactive", power_schemes[mode]],
35+
creationflags=CREATE_NO_WINDOW,
36+
)
37+
return f"Power mode set to {mode}"
38+
except subprocess.CalledProcessError:
39+
return "Failed to set power mode"
40+
return "Invalid mode"
41+
42+
43+
def get_powercfg_value(subgroup_guid, setting_guid):
44+
command = ["powercfg", "/query", "SCHEME_CURRENT", subgroup_guid, setting_guid]
45+
result = subprocess.run(
46+
command, capture_output=True, text=True, creationflags=CREATE_NO_WINDOW
47+
)
48+
output = result.stdout
49+
match_ac = re.search(r"Current AC Power Setting Index:\s+0x([0-9a-fA-F]+)", output)
50+
match_dc = re.search(r"Current DC Power Setting Index:\s+0x([0-9a-fA-F]+)", output)
51+
ac_value = int(match_ac.group(1), 16) if match_ac else None
52+
dc_value = int(match_dc.group(1), 16) if match_dc else None
53+
return ac_value, dc_value
54+
55+
56+
def set_powercfg_value(subgroup_guid, setting_guid, seconds, power_source):
57+
command = []
58+
if power_source == "AC":
59+
command = [
60+
"powercfg",
61+
"/setacvalueindex",
62+
"SCHEME_CURRENT",
63+
subgroup_guid,
64+
setting_guid,
65+
str(seconds),
66+
]
67+
elif power_source == "DC":
68+
command = [
69+
"powercfg",
70+
"/setdcvalueindex",
71+
"SCHEME_CURRENT",
72+
subgroup_guid,
73+
setting_guid,
74+
str(seconds),
75+
]
76+
77+
subprocess.run(command, creationflags=CREATE_NO_WINDOW)
78+
subprocess.run(
79+
["powercfg", "/setactive", "SCHEME_CURRENT"], creationflags=CREATE_NO_WINDOW
80+
)
81+
82+
83+
def set_screen_timeout(seconds, power_source):
84+
set_powercfg_value("SUB_VIDEO", "VIDEOIDLE", seconds, power_source)
85+
86+
87+
def set_sleep_timeout(seconds, power_source):
88+
set_powercfg_value("SUB_SLEEP", "STANDBYIDLE", seconds, power_source)
89+
90+
91+
def reset_timeouts():
92+
set_screen_timeout(600, "AC")
93+
set_sleep_timeout(1200, "AC")
94+
set_screen_timeout(600, "DC")
95+
set_sleep_timeout(1200, "DC")
96+
97+
98+
def get_timeouts():
99+
def pretty(value):
100+
if value is None:
101+
return "Never (Couldn't fetch)"
102+
rounded_value = round(value / 60, 1)
103+
return "Never" if rounded_value == 0 else f"{rounded_value}m"
104+
105+
sleep = get_powercfg_value("SUB_SLEEP", "STANDBYIDLE")
106+
screen = get_powercfg_value("SUB_VIDEO", "VIDEOIDLE")
107+
108+
return {
109+
"screen_ac": pretty(screen[0]),
110+
"screen_dc": pretty(screen[1]),
111+
"sleep_ac": pretty(sleep[0]),
112+
"sleep_dc": pretty(sleep[1]),
113+
}
114+
115+
116+
def enable_hibernation():
117+
try:
118+
subprocess.check_call(
119+
["powercfg", "/hibernate", "on"], creationflags=CREATE_NO_WINDOW
120+
)
121+
return "Hibernation enabled"
122+
except subprocess.CalledProcessError:
123+
return "Failed to enable hibernation"
124+
125+
126+
def disable_hibernation():
127+
try:
128+
subprocess.check_call(
129+
["powercfg", "/hibernate", "off"], creationflags=CREATE_NO_WINDOW
130+
)
131+
return "Hibernation disabled"
132+
except subprocess.CalledProcessError:
133+
return "Failed to disable hibernation"
134+
135+
136+
def get_hibernation():
137+
try:
138+
output = subprocess.check_output(
139+
["powercfg", "/a"],
140+
encoding="utf-8",
141+
errors="ignore",
142+
creationflags=CREATE_NO_WINDOW,
143+
)
144+
return (
145+
"Hibernate" in output and "Hibernation has not been enabled." not in output
146+
)
147+
except subprocess.CalledProcessError:
148+
return False
149+
150+
151+
def generate_battery_report():
152+
try:
153+
subprocess.check_call(
154+
["powercfg", "/batteryreport"], creationflags=CREATE_NO_WINDOW
155+
)
156+
return True
157+
except subprocess.CalledProcessError:
158+
return False
159+
160+
161+
def generate_sleepstudy_report():
162+
try:
163+
subprocess.check_call(
164+
["powercfg", "/sleepstudy"], creationflags=CREATE_NO_WINDOW
165+
)
166+
return True
167+
except subprocess.CalledProcessError:
168+
return False
169+
170+
171+
def get_brightness():
172+
try:
173+
cmd = [
174+
"powershell",
175+
"-Command",
176+
"(Get-WmiObject -Namespace root/wmi -Class WmiMonitorBrightness).CurrentBrightness",
177+
]
178+
result = subprocess.run(
179+
cmd, capture_output=True, text=True, creationflags=CREATE_NO_WINDOW
180+
)
181+
182+
if result.returncode != 0:
183+
raise Exception(result.stderr.strip())
184+
185+
brightness = int(result.stdout.strip())
186+
return brightness
187+
188+
except Exception as e:
189+
return None
190+
191+
192+
def set_brightness(brightness_value):
193+
try:
194+
if brightness_value < 0 or brightness_value > 100:
195+
raise ValueError("Brightness value must be between 0 and 100")
196+
197+
cmd = [
198+
"powershell",
199+
"-Command",
200+
f"(Get-WmiObject -Namespace root/WMI -Class WmiMonitorBrightnessMethods).WmiSetBrightness(1,{brightness_value})",
201+
]
202+
result = subprocess.run(
203+
cmd, capture_output=True, text=True, creationflags=CREATE_NO_WINDOW
204+
)
205+
206+
if result.returncode != 0:
207+
raise Exception(result.stderr.strip())
208+
209+
except Exception as e:
210+
pass
211+
212+
213+
def set_mouse_speed(speed):
214+
ctypes.windll.user32.SystemParametersInfoA(113, 0, speed, 0)
215+
216+
217+
def get_mouse_speed():
218+
speed = ctypes.c_int()
219+
ctypes.windll.user32.SystemParametersInfoA(112, 0, ctypes.byref(speed), 0)
220+
221+
return speed.value
222+
223+
224+
def lock_device():
225+
ctypes.windll.user32.LockWorkStation()
226+
227+
228+
def restart_device():
229+
os.system("shutdown /r /t 0")
230+
231+
232+
def shutdown_device():
233+
os.system("shutdown /s /t 0")

format.py

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import subprocess
2+
import sys
3+
4+
5+
def format():
6+
try:
7+
import black
8+
9+
installed = True
10+
except ImportError:
11+
installed = False
12+
13+
if not installed:
14+
subprocess.check_call([sys.executable, "-m", "pip", "install", "black"])
15+
16+
subprocess.check_call([sys.executable, "-m", "black", "core.py"])
17+
subprocess.check_call([sys.executable, "-m", "black", "main.py"])
18+
19+
20+
if __name__ == "__main__":
21+
format()

icon.ico

169 KB
Binary file not shown.

icon.png

16.5 KB
Loading

icon.svg

+14
Loading

0 commit comments

Comments
 (0)