-
Notifications
You must be signed in to change notification settings - Fork 1
/
intel-13thGen-Fedora.sh
228 lines (192 loc) · 9.3 KB
/
intel-13thGen-Fedora.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#!/bin/bash
# IMPORTANT: For Widget to work on Fedora, you must install "AppIndicator/KStatusNotifierItem support" GNOME shell extension.
# Install dependencies
sudo systemctl stop power-profiles-daemon && sudo systemctl disable power-profiles-daemon && sudo systemctl mask power-profiles-daemon && sleep 2 && sudo dnf install -y python3-gobject python3-cairo gobject-introspection gtk3 libappindicator-gtk3 tuned && sudo systemctl enable --now tuned
# Create directory for the script
mkdir -p ~/.local/bin
# Create the Python script
cat << EOF > ~/.local/bin/tuned_indicator.py
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('AppIndicator3', '0.1')
from gi.repository import Gtk, AppIndicator3, GLib
import subprocess
import logging
import signal
import os
import urllib.request
# Configure logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
PROFILES_PER_PAGE = 10
ICON_URL = "https://raw.githubusercontent.com/FrameworkComputer/tuned-gui/main/images/logo_white_targeted.png"
ICON_PATH = os.path.expanduser("~/.local/share/icons/tuned_logo.png") # Path to save the downloaded icon
class TunedIndicator:
def __init__(self):
# Verify 'tuned-adm' command availability
if not self.command_exists('tuned-adm'):
logging.error("'tuned-adm' command not found. Make sure 'tuned' is installed.")
return
# Download the PNG icon
self.download_icon(ICON_URL, ICON_PATH)
# Initialize the AppIndicator with the PNG icon
self.indicator = AppIndicator3.Indicator.new(
"tuned-indicator",
ICON_PATH,
AppIndicator3.IndicatorCategory.SYSTEM_SERVICES)
self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
self.current_page = 0 # Current page for pagination
self.indicator.set_menu(self.create_menu())
# Initial update to ensure system is ready
self.update_menu_items()
# Setup signal handlers for system events
signal.signal(signal.SIGUSR1, self.handle_signal)
signal.signal(signal.SIGUSR2, self.handle_signal)
def command_exists(self, cmd):
"""Check if a command exists."""
return subprocess.call(f"type {cmd}", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0
def download_icon(self, url, path):
"""Download the icon from the specified URL and save it to the specified path."""
try:
os.makedirs(os.path.dirname(path), exist_ok=True)
urllib.request.urlretrieve(url, path)
logging.info(f"Icon downloaded successfully: {path}")
except Exception as e:
logging.error(f"Failed to download icon: {e}")
def create_menu(self):
"""Create the indicator menu and populate it with profile items and controls."""
self.menu = Gtk.Menu()
self.menu.set_size_request(300, -1) # Set the minimum width of the menu
return self.menu
def get_profiles(self):
"""Retrieve the list of available profiles using the 'tuned-adm list' command."""
try:
output = subprocess.check_output(['tuned-adm', 'list'], stderr=subprocess.STDOUT, text=True)
profiles = [line.strip('- ').split(' - ')[0].strip() for line in output.split('\n') if line.startswith('- ')]
logging.debug(f"Profiles retrieved: {profiles}")
return profiles
except subprocess.CalledProcessError as e:
logging.error(f"Error getting profiles: {e.output}")
return []
def get_active_profile(self):
"""Retrieve the current active profile using the 'tuned-adm active' command."""
try:
output = subprocess.check_output(['tuned-adm', 'active'], stderr=subprocess.STDOUT, text=True)
if "No current active profile" in output:
return None
else:
# Extract the profile name
active_profile = output.split(':', 1)[1].strip().split()[0]
logging.debug(f"Active profile detected: {active_profile}")
return active_profile
except subprocess.CalledProcessError as e:
logging.error(f"Error getting active profile: {e.output}")
return None
def normalize_profile_name(self, profile):
"""Normalize profile name by removing trailing hyphen."""
if profile == 'intel-best_power_efficiency_mode- Intel epp 70 TuneD profile':
return 'intel-best_power_efficiency_mode'
return profile
def update_menu_items(self):
"""Update the indicator menu with the current set of profiles and pagination controls."""
# Clear existing menu items
for item in self.menu.get_children():
self.menu.remove(item)
profiles = self.get_profiles()
active_profile = self.get_active_profile()
logging.debug(f"Updating menu items. Active profile: {active_profile}")
start = self.current_page * PROFILES_PER_PAGE
end = min(start + PROFILES_PER_PAGE, len(profiles))
current_profiles = profiles[start:end]
# Add profile items to the menu
for profile in current_profiles:
logging.debug(f"Adding profile to menu: {profile}")
item = Gtk.CheckMenuItem(label=profile)
item.set_size_request(300, -1) # Set the minimum width of each menu item
normalized_profile = self.normalize_profile_name(profile)
if normalized_profile == active_profile:
item.set_active(True)
logging.debug(f"Set active profile: {profile}")
item.set_tooltip_text(profile) # Ensure the full profile name is visible
item.connect('activate', self.on_profile_click, profile)
self.menu.append(item)
item.show_all()
# Add pagination controls if needed
if self.current_page > 0:
prev_item = Gtk.MenuItem(label="Previous")
prev_item.connect('activate', self.on_prev_page)
self.menu.append(prev_item)
prev_item.show_all()
if end < len(profiles):
next_item = Gtk.MenuItem(label="Next")
next_item.connect('activate', self.on_next_page)
self.menu.append(next_item)
next_item.show_all()
separator = Gtk.SeparatorMenuItem()
self.menu.append(separator)
separator.show_all()
# Add option to turn off the applet
off_item = Gtk.MenuItem(label="Turn Off Applet")
off_item.connect('activate', self.on_turn_off_applet_click)
self.menu.append(off_item)
off_item.show_all()
self.menu.show_all()
def on_prev_page(self, widget):
"""Handle the 'Previous' button click to show the previous page of profiles."""
if self.current_page > 0:
self.current_page -= 1
self.update_menu_items()
def on_next_page(self, widget):
"""Handle the 'Next' button click to show the next page of profiles."""
profiles = self.get_profiles()
if (self.current_page + 1) * PROFILES_PER_PAGE < len(profiles):
self.current_page += 1
self.update_menu_items()
def on_profile_click(self, widget, profile):
"""Handle profile menu item click to switch to the selected profile."""
if widget.get_active():
# Use the correct profile name
normalized_profile = self.normalize_profile_name(profile)
logging.debug(f"Attempting to switch to profile: {normalized_profile} (original: {profile})")
try:
# Use the correct profile name
command = ['tuned-adm', 'profile', normalized_profile]
logging.debug(f"Running command: {command}")
subprocess.check_output(command, stderr=subprocess.STDOUT, text=True)
logging.info(f"Successfully switched to profile: {normalized_profile}")
# Update the menu items to reflect the new active profile
self.update_menu_items()
except subprocess.CalledProcessError as e:
logging.error(f"Failed to switch profile: {e.output}")
def on_turn_off_applet_click(self, widget):
"""Handle the 'Turn Off Applet' menu item click to exit the applet."""
logging.info("Turning off the applet")
os._exit(0) # Exit the applet
def handle_signal(self, signum, frame):
"""Handle signals to update the active profile."""
if signum in (signal.SIGUSR1, signal.SIGUSR2):
self.update_menu_items()
if __name__ == "__main__":
# Initialize and run the applet
try:
indicator = TunedIndicator()
Gtk.main()
except Exception as e:
logging.error(f"Error initializing the TunedIndicator: {e}")
EOF
# Make the script executable
chmod +x ~/.local/bin/tuned_indicator.py
# Create autostart desktop entry
mkdir -p ~/.config/autostart
cat << EOF > ~/.config/autostart/tuned-indicator.desktop
[Desktop Entry]
Type=Application
Exec=/usr/bin/python3 ${HOME}/.local/bin/tuned_indicator.py
Hidden=false
NoDisplay=false
X-GNOME-Autostart-enabled=true
Name[en_US]=TuneD Indicator
Name=TuneD Indicator
Comment[en_US]=TuneD profile switcher indicator
Comment=TuneD profile switcher indicator
EOF
echo "Installation complete. The TuneD Indicator will start automatically on your next login."