@@ -10,25 +10,16 @@ enum VALUE {
1010 RELATIVE ,
1111}
1212
13- enum BRIGHTNESS_PROVIDER {
14- NONE ,
15- STEAMOS ,
16- }
17-
1813signal brightness_changed
1914
20- const backlight_path := "/sys/class/backlight"
21- const steamos_write_bin := "/usr/bin/steamos-polkit-helpers/steamos-priv-write"
22-
2315var logger := Log .get_logger ("DisplayManager" , Log .LEVEL .INFO )
16+ var brightness_provider := _get_backlight_provider ()
2417var backlights := get_backlight_paths ()
25- var brightness_provider := _get_brightness_provider ()
2618
2719
2820## Returns true if OpenGamepadUI has access to adjust brightness
2921func supports_brightness () -> bool :
30- brightness_provider = _get_brightness_provider ()
31- if brightness_provider == BRIGHTNESS_PROVIDER .NONE :
22+ if brightness_provider == null :
3223 logger .debug ("No brightness setter found" )
3324 return false
3425 backlights = get_backlight_paths ()
@@ -40,97 +31,273 @@ func supports_brightness() -> bool:
4031
4132## Sets the brightness on all discovered backlights to the given value as a
4233## percentage (e.g. 1.0 is 100% brightness)
43- func set_brightness (value : float , type : VALUE = VALUE .ABSOLUTE ) -> int :
34+ func set_brightness (value : float , type : VALUE = VALUE .ABSOLUTE , backlight : String = "" ) -> int :
4435 if not supports_brightness ():
4536 logger .debug ("Failed to set brightness, no providers found" )
4637 return FAILED
47- value = minf (value , 1.0 )
48- value = maxf (value , 0.0 )
49- backlights = get_backlight_paths ()
50-
51- # Set the brightness for all backlights
52- for backlight_path in backlights :
53- # Calculate the value based on whether this is an absolute or relative change
54- var abs_value := value
55- if type == VALUE .RELATIVE :
56- abs_value = get_brightness (backlight_path ) + value
57- abs_value = minf (abs_value , 1.0 )
58- abs_value = maxf (abs_value , 0.0 )
59- var real_value := int (abs_value * get_max_brightness_value (backlight_path ))
60-
61- # Use the preferred method of setting brightness
62- var brightness_file := "/" .join ([backlight_path , "brightness" ])
63- logger .debug ("Setting brightness on " + brightness_file + " to " + str (real_value ))
64- if brightness_provider == BRIGHTNESS_PROVIDER .STEAMOS :
65- if _steamos_priv_write (brightness_file , real_value ) != OK :
66- return FAILED
67- continue
68-
69- return FAILED
70-
38+
39+ var err := brightness_provider .set_brightness (value , type , backlight )
40+ if err != OK :
41+ return err
7142 brightness_changed .emit ()
72-
73- return OK
43+
44+ return err
7445
7546
7647## Returns the current brightness level for the given backlight as a percent
7748func get_brightness (backlight_path : String ) -> float :
78- var cur_brightness := get_brightness_value (backlight_path )
79- var max_brightness := get_max_brightness_value (backlight_path )
80- if cur_brightness == - 1 or max_brightness == - 1 :
81- return - 1
82- return float (cur_brightness ) / max_brightness
49+ if brightness_provider == null :
50+ return - 1.0
51+ return brightness_provider .get_brightness (backlight_path )
8352
8453
8554## Returns the current brightness value for the given backlight
8655func get_brightness_value (backlight_path : String ) -> int :
87- var brightness_file := "/" .join ([backlight_path , "brightness" ])
88- var output := []
89- var code := OS .execute ("cat" , [brightness_file ], output )
90- if code != OK :
91- logger .debug ("Unable to get current brightness: " + output [0 ])
56+ if brightness_provider == null :
9257 return - 1
93- var value := (output [0 ] as String ).strip_edges ()
94- if value .is_valid_int ():
95- return value .to_int ()
96- logger .debug ("Brightness is not a valid number: " + value )
97- return - 1
58+ return brightness_provider .get_brightness_value (backlight_path )
9859
9960
10061## Returns the maximum brightness for the given backlight
10162func get_max_brightness_value (backlight_path : String ) -> int :
102- var max_brightness_file := "/" .join ([backlight_path , "max_brightness" ])
103- var output := []
104- var code := OS .execute ("cat" , [max_brightness_file ], output )
105- if code != OK :
106- logger .debug ("Unable to get max brightness: " + output [0 ])
63+ if brightness_provider == null :
10764 return - 1
108- var value := (output [0 ] as String ).strip_edges ()
109- if value .is_valid_int ():
110- return value .to_int ()
111- logger .debug ("Max brightness is not a valid number: " + value )
112- return - 1
65+ return brightness_provider .get_max_brightness_value (backlight_path )
11366
11467
11568## Returns a list of all detected backlight devices
11669func get_backlight_paths () -> PackedStringArray :
117- var backlights := PackedStringArray ()
118- var backlight_dir := DirAccess .open (backlight_path )
119- var devices := backlight_dir .get_directories ()
120- for device in devices :
121- backlights .append ("/" .join ([backlight_path , device ]))
122- logger .debug ("Found backlights: " + str (backlights ))
123- return backlights
70+ if brightness_provider == null :
71+ return PackedStringArray ()
72+ return brightness_provider .get_backlights ()
12473
12574
126- func _get_brightness_provider () -> BRIGHTNESS_PROVIDER :
127- if FileAccess .file_exists (steamos_write_bin ):
75+ func _get_backlight_provider () -> BacklightProvider :
76+ if FileAccess .file_exists ("/usr/bin/steamos-polkit-helpers/steamos-priv-write" ):
12877 logger .debug ("Using SteamOS backlight writer" )
129- return BRIGHTNESS_PROVIDER .STEAMOS
78+ return SteamOsBacklight .new ()
79+ if OS .execute ("which" , ["brightnessctl" ]) == OK :
80+ logger .debug ("Using brightnessctl backlight provider" )
81+ return BrightnessctlBacklight .new ()
13082 logger .debug ("No backlight writer found" )
131- return BRIGHTNESS_PROVIDER .NONE
83+ return null
84+
85+
86+ ## Interface for controlling backlights (e.g. screen brightness)
87+ class BacklightProvider :
88+ ## Returns all available backlights
89+ func get_backlights () -> PackedStringArray :
90+ return PackedStringArray ()
91+
92+ ## Returns the maximum raw brightness value of the given backlight. If
93+ ## No backlight is passed, then this should return the value for the "main"
94+ ## display. Returns -1 if there is an error fetching the value.
95+ func get_max_brightness_value (_backlight : String = "" ) -> int :
96+ return - 1
97+
98+ ## Returns the current raw brightness value of the given backlight. If no
99+ ## backlight is passed, then this should return the value for the "main"
100+ ## display. Returns -1 if there is an error fetching the value.
101+ func get_brightness_value (_backlight : String = "" ) -> int :
102+ return - 1
103+
104+ ## Returns the current brightness level for the given backlight as a percent.
105+ ## Returns -1 if there is an error fetching the value
106+ func get_brightness (_backlight : String = "" ) -> float :
107+ return - 1.0
108+
109+ ## Sets the brightness for the given backlight to the given value as a
110+ ## percentage (e.g. 1.0 is 100% brightness). If no backlight is specified,
111+ ## this should set the value on _all_ discovered backlights. Returns OK
112+ ## if set successfully.
113+ func set_brightness (_value : float , _type : VALUE = VALUE .ABSOLUTE , _backlight : String = "" ) -> int :
114+ return ERR_METHOD_NOT_FOUND
115+
116+
117+ ## SteamOS implementation of backlight control
118+ class SteamOsBacklight extends BacklightProvider :
119+ const backlight_path_base := "/sys/class/backlight"
120+ const steamos_write_bin := "/usr/bin/steamos-polkit-helpers/steamos-priv-write"
121+ var logger := Log .get_logger ("SteamOsBacklight" , Log .LEVEL .INFO )
122+
123+ func get_backlights () -> PackedStringArray :
124+ var backlights := PackedStringArray ()
125+ var backlight_dir := DirAccess .open (backlight_path_base )
126+ var devices := backlight_dir .get_directories ()
127+ for device in devices :
128+ backlights .append ("/" .join ([backlight_path_base , device ]))
129+ self .logger .debug ("Found backlights: " + str (backlights ))
130+ return backlights
131+
132+ func set_brightness (value : float , type : VALUE = VALUE .ABSOLUTE , backlight : String = "" ) -> int :
133+ value = minf (value , 1.0 )
134+ value = maxf (value , 0.0 )
135+ var backlights := PackedStringArray ()
136+ if backlight .is_empty ():
137+ backlights = self .get_backlights ()
138+ else :
139+ backlights .push_back (backlight )
140+
141+ # Set the brightness for all backlights
142+ for backlight_path in backlights :
143+ # Calculate the value based on whether this is an absolute or relative change
144+ var abs_value := value
145+ if type == VALUE .RELATIVE :
146+ abs_value = self .get_brightness (backlight_path ) + value
147+ abs_value = minf (abs_value , 1.0 )
148+ abs_value = maxf (abs_value , 0.0 )
149+ var real_value := int (abs_value * self .get_max_brightness_value (backlight_path ))
150+
151+ # Use the preferred method of setting brightness
152+ var brightness_file := "/" .join ([backlight_path , "brightness" ])
153+ self .logger .debug ("Setting brightness on " + brightness_file + " to " + str (real_value ))
154+ if self ._steamos_priv_write (brightness_file , real_value ) != OK :
155+ return FAILED
156+
157+ return OK
158+
159+ func get_brightness (backlight_path : String = "" ) -> float :
160+ var cur_brightness := self .get_brightness_value (backlight_path )
161+ var max_brightness := self .get_max_brightness_value (backlight_path )
162+ if cur_brightness == - 1 or max_brightness == - 1 :
163+ return - 1
164+ return float (cur_brightness ) / max_brightness
165+
166+ func get_brightness_value (backlight_path : String = "" ) -> int :
167+ var brightness_file := "/" .join ([backlight_path , "brightness" ])
168+ var output := []
169+ var code := OS .execute ("cat" , [brightness_file ], output )
170+ if code != OK :
171+ logger .debug ("Unable to get current brightness: " + output [0 ])
172+ return - 1
173+ var value := (output [0 ] as String ).strip_edges ()
174+ if value .is_valid_int ():
175+ return value .to_int ()
176+ self .logger .debug ("Brightness is not a valid number: " + value )
177+ return - 1
178+
179+ func get_max_brightness_value (backlight_path : String = "" ) -> int :
180+ var max_brightness_file := "/" .join ([backlight_path , "max_brightness" ])
181+ var output := []
182+ var code := OS .execute ("cat" , [max_brightness_file ], output )
183+ if code != OK :
184+ self .logger .debug ("Unable to get max brightness: " + output [0 ])
185+ return - 1
186+ var value := (output [0 ] as String ).strip_edges ()
187+ if value .is_valid_int ():
188+ return value .to_int ()
189+ self .logger .debug ("Max brightness is not a valid number: " + value )
190+ return - 1
191+
192+ ## Write a value using steamos polkit helper
193+ func _steamos_priv_write (path : String , value : int ) -> int :
194+ return OS .execute (steamos_write_bin , [path , str (value )])
195+
196+
197+ ## Brightnessctl implementation of backlight control
198+ class BrightnessctlBacklight extends BacklightProvider :
199+ var logger := Log .get_logger ("BrightnessctlBacklight" , Log .LEVEL .INFO )
200+
201+ func _exec (args : Array [String ]) -> Command :
202+ var cmd := Command .create ("brightnessctl" , args )
203+ cmd .execute_blocking ()
204+ return cmd
205+
206+ func _get_info (backlight : String = "" ) -> PackedStringArray :
207+ var args : Array [String ] = ["--machine" , "--class" , "backlight" , "info" ]
208+ if not backlight .is_empty ():
209+ args .push_front (backlight )
210+ args .push_front ("--device" )
211+ var cmd := _exec (args )
212+ if cmd .code != OK :
213+ return PackedStringArray ()
214+
215+ var lines := cmd .stdout .split ("\n " , false )
216+ if lines .is_empty ():
217+ return PackedStringArray ()
218+
219+ # Example Output: amdgpu_bl1,backlight,128,50%,255
220+ var parts := lines [0 ].split ("," , false )
221+ return parts
222+
223+ func get_backlights () -> PackedStringArray :
224+ # brightnessctl -l -c backlight -m
225+ # Output: amdgpu_bl1,backlight,128,50%,255
226+ var backlights := PackedStringArray ()
227+ var cmd := self ._exec (["--list" , "--class" , "backlight" , "--machine" ])
228+ if cmd .code != OK :
229+ return backlights
230+
231+ var lines := cmd .stdout .split ("\n " , false )
232+ for line in lines :
233+ var parts := line .split ("," )
234+ if parts .is_empty ():
235+ continue
236+ backlights .push_back (parts [0 ])
237+
238+ self .logger .debug ("Found backlights: " + str (backlights ))
239+ return backlights
240+
241+ func set_brightness (value : float , type : VALUE = VALUE .ABSOLUTE , backlight : String = "" ) -> int :
242+ value = minf (value , 1.0 )
243+ value = maxf (value , - 1.0 )
244+ value = value * 100.0
245+ var backlights := PackedStringArray ()
246+ if backlight .is_empty ():
247+ backlights = self .get_backlights ()
248+ else :
249+ backlights .push_back (backlight )
250+
251+ # Set the brightness for all backlights
252+ for backlight_name in backlights :
253+ var value_str := str (value ) + "%"
254+ if type == VALUE .RELATIVE :
255+ if value > 0.0 :
256+ value_str = "+" + value_str
257+ else :
258+ value_str = value_str + "-"
259+
260+ self .logger .debug ("Setting brightness on " + backlight_name + " to " + value_str )
261+ var cmd := _exec (["--device" , backlight , "set" , value_str ])
262+ if cmd .code != OK :
263+ return FAILED
264+
265+ return OK
266+
267+ func get_brightness (backlight : String = "" ) -> float :
268+ var info := self ._get_info (backlight )
269+ if info .size () < 4 :
270+ return - 1.0
271+
272+ # Example Output: amdgpu_bl1,backlight,128,50%,255
273+ var cur_brightness := info [3 ]
274+ cur_brightness = cur_brightness .replace ("%" , "" )
275+ if not cur_brightness .is_valid_int ():
276+ return - 1.0
277+
278+ return cur_brightness .to_float () / 100.0
279+
280+
281+ func get_brightness_value (backlight : String = "" ) -> int :
282+ var info := self ._get_info (backlight )
283+ if info .size () < 4 :
284+ return - 1
285+
286+ # Example Output: amdgpu_bl1,backlight,128,50%,255
287+ var cur_brightness := info [2 ]
288+ if not cur_brightness .is_valid_int ():
289+ return - 1
290+
291+ return cur_brightness .to_int ()
292+
293+ func get_max_brightness_value (backlight : String = "" ) -> int :
294+ var info := self ._get_info (backlight )
295+ if info .size () < 5 :
296+ return - 1
132297
298+ # Example Output: amdgpu_bl1,backlight,128,50%,255
299+ var max_brightness := info [4 ]
300+ if not max_brightness .is_valid_int ():
301+ return - 1
133302
134- ## Write a value using steamos polkit helper
135- func _steamos_priv_write (path : String , value : int ) -> int :
136- return OS .execute (steamos_write_bin , [path , str (value )])
303+ return max_brightness .to_int ()
0 commit comments