@@ -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,274 @@ 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-
71- brightness_changed .emit ()
72-
73- return OK
38+
39+ var err := brightness_provider .set_brightness (value , type , backlight )
40+ if err == OK :
41+ brightness_changed .emit ()
42+
43+ return err
7444
7545
7646## Returns the current brightness level for the given backlight as a percent
7747func 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
48+ if brightness_provider == null :
49+ return - 1.0
50+ return brightness_provider .get_brightness (backlight_path )
8351
8452
8553## Returns the current brightness value for the given backlight
8654func 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 ])
55+ if brightness_provider == null :
9256 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
57+ return brightness_provider .get_brightness_value (backlight_path )
9858
9959
10060## Returns the maximum brightness for the given backlight
10161func 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 ])
62+ if brightness_provider == null :
10763 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
64+ return brightness_provider .get_max_brightness_value (backlight_path )
11365
11466
11567## Returns a list of all detected backlight devices
11668func 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
69+ if brightness_provider == null :
70+ return PackedStringArray ()
71+ return brightness_provider .get_backlights ()
12472
12573
126- func _get_brightness_provider () -> BRIGHTNESS_PROVIDER :
127- if FileAccess .file_exists (steamos_write_bin ):
74+ func _get_backlight_provider () -> BacklightProvider :
75+ if OS .execute ("which" , ["brightnessctl" ]) == OK :
76+ logger .debug ("Using brightnessctl backlight provider" )
77+ return BrightnessctlBacklight .new ()
78+ if FileAccess .file_exists ("/usr/bin/steamos-polkit-helpers/steamos-priv-write" ):
12879 logger .debug ("Using SteamOS backlight writer" )
129- return BRIGHTNESS_PROVIDER . STEAMOS
80+ return SteamOsBacklight . new ()
13081 logger .debug ("No backlight writer found" )
131- return BRIGHTNESS_PROVIDER .NONE
82+ return null
83+
84+
85+ ## Interface for controlling backlights (e.g. screen brightness)
86+ class BacklightProvider :
87+ ## Returns all available backlights
88+ func get_backlights () -> PackedStringArray :
89+ return PackedStringArray ()
90+
91+ ## Returns the maximum raw brightness value of the given backlight. If
92+ ## No backlight is passed, then this should return the value for the "main"
93+ ## display. Returns -1 if there is an error fetching the value.
94+ func get_max_brightness_value (_backlight : String = "" ) -> int :
95+ return - 1
96+
97+ ## Returns the current raw brightness value of the given backlight. If no
98+ ## backlight is passed, then this should return the value for the "main"
99+ ## display. Returns -1 if there is an error fetching the value.
100+ func get_brightness_value (_backlight : String = "" ) -> int :
101+ return - 1
102+
103+ ## Returns the current brightness level for the given backlight as a percent.
104+ ## Returns -1 if there is an error fetching the value
105+ func get_brightness (_backlight : String = "" ) -> float :
106+ return - 1.0
107+
108+ ## Sets the brightness for the given backlight to the given value as a
109+ ## percentage (e.g. 1.0 is 100% brightness). If no backlight is specified,
110+ ## this should set the value on _all_ discovered backlights. Returns OK
111+ ## if set successfully.
112+ func set_brightness (_value : float , _type : VALUE = VALUE .ABSOLUTE , _backlight : String = "" ) -> int :
113+ return ERR_METHOD_NOT_FOUND
114+
115+
116+ ## SteamOS implementation of backlight control
117+ class SteamOsBacklight extends BacklightProvider :
118+ const backlight_path_base := "/sys/class/backlight"
119+ const steamos_write_bin := "/usr/bin/steamos-polkit-helpers/steamos-priv-write"
120+ var logger := Log .get_logger ("SteamOsBacklight" , Log .LEVEL .INFO )
121+
122+ func get_backlights () -> PackedStringArray :
123+ var backlights := PackedStringArray ()
124+ var backlight_dir := DirAccess .open (backlight_path_base )
125+ var devices := backlight_dir .get_directories ()
126+ for device in devices :
127+ backlights .append ("/" .join ([backlight_path_base , device ]))
128+ self .logger .debug ("Found backlights: " + str (backlights ))
129+ return backlights
130+
131+ func set_brightness (value : float , type : VALUE = VALUE .ABSOLUTE , backlight : String = "" ) -> int :
132+ value = minf (value , 1.0 )
133+ value = maxf (value , 0.0 )
134+ var backlights := PackedStringArray ()
135+ if backlight .is_empty ():
136+ backlights = self .get_backlights ()
137+ else :
138+ backlights .push_back (backlight )
139+
140+ # Set the brightness for all backlights
141+ for backlight_path in backlights :
142+ # Calculate the value based on whether this is an absolute or relative change
143+ var abs_value := value
144+ if type == VALUE .RELATIVE :
145+ abs_value = self .get_brightness (backlight_path ) + value
146+ abs_value = minf (abs_value , 1.0 )
147+ abs_value = maxf (abs_value , 0.0 )
148+ var real_value := int (abs_value * self .get_max_brightness_value (backlight_path ))
149+
150+ # Use the preferred method of setting brightness
151+ var brightness_file := "/" .join ([backlight_path , "brightness" ])
152+ self .logger .debug ("Setting brightness on " + brightness_file + " to " + str (real_value ))
153+ if self ._steamos_priv_write (brightness_file , real_value ) != OK :
154+ return FAILED
155+
156+ return OK
157+
158+ func get_brightness (backlight_path : String = "" ) -> float :
159+ var cur_brightness := self .get_brightness_value (backlight_path )
160+ var max_brightness := self .get_max_brightness_value (backlight_path )
161+ if cur_brightness == - 1 or max_brightness == - 1 :
162+ return - 1
163+ return float (cur_brightness ) / max_brightness
164+
165+ func get_brightness_value (backlight_path : String = "" ) -> int :
166+ var brightness_file := "/" .join ([backlight_path , "brightness" ])
167+ var output := []
168+ var code := OS .execute ("cat" , [brightness_file ], output )
169+ if code != OK :
170+ logger .debug ("Unable to get current brightness: " + output [0 ])
171+ return - 1
172+ var value := (output [0 ] as String ).strip_edges ()
173+ if value .is_valid_int ():
174+ return value .to_int ()
175+ self .logger .debug ("Brightness is not a valid number: " + value )
176+ return - 1
177+
178+ func get_max_brightness_value (backlight_path : String = "" ) -> int :
179+ var max_brightness_file := "/" .join ([backlight_path , "max_brightness" ])
180+ var output := []
181+ var code := OS .execute ("cat" , [max_brightness_file ], output )
182+ if code != OK :
183+ self .logger .debug ("Unable to get max brightness: " + output [0 ])
184+ return - 1
185+ var value := (output [0 ] as String ).strip_edges ()
186+ if value .is_valid_int ():
187+ return value .to_int ()
188+ self .logger .debug ("Max brightness is not a valid number: " + value )
189+ return - 1
190+
191+ ## Write a value using steamos polkit helper
192+ func _steamos_priv_write (path : String , value : int ) -> int :
193+ return OS .execute (steamos_write_bin , [path , str (value )])
194+
195+
196+ ## Brightnessctl implementation of backlight control
197+ class BrightnessctlBacklight extends BacklightProvider :
198+ var logger := Log .get_logger ("BrightnessctlBacklight" , Log .LEVEL .INFO )
199+
200+ func _exec (args : Array [String ]) -> Command :
201+ self .logger .debug ("Executing command:" , "brightnessctl" , args )
202+ var cmd := Command .create ("brightnessctl" , args )
203+ cmd .execute_blocking ()
204+ self .logger .debug ("Output:" , cmd .stdout , cmd .stderr )
205+ return cmd
206+
207+ func _get_info (backlight : String = "" ) -> PackedStringArray :
208+ var args : Array [String ] = ["--machine" , "--class" , "backlight" , "info" ]
209+ if not backlight .is_empty ():
210+ args .push_front (backlight )
211+ args .push_front ("--device" )
212+ var cmd := _exec (args )
213+ if cmd .code != OK :
214+ return PackedStringArray ()
215+
216+ var lines := cmd .stdout .split ("\n " , false )
217+ if lines .is_empty ():
218+ return PackedStringArray ()
219+
220+ # Example Output: amdgpu_bl1,backlight,128,50%,255
221+ var parts := lines [0 ].split ("," , false )
222+ return parts
223+
224+ func get_backlights () -> PackedStringArray :
225+ # brightnessctl -l -c backlight -m
226+ # Output: amdgpu_bl1,backlight,128,50%,255
227+ var backlights := PackedStringArray ()
228+ var cmd := self ._exec (["--list" , "--class" , "backlight" , "--machine" ])
229+ if cmd .code != OK :
230+ return backlights
231+
232+ var lines := cmd .stdout .split ("\n " , false )
233+ for line in lines :
234+ var parts := line .split ("," )
235+ if parts .is_empty ():
236+ continue
237+ backlights .push_back (parts [0 ])
238+
239+ self .logger .debug ("Found backlights: " + str (backlights ))
240+ return backlights
241+
242+ func set_brightness (value : float , type : VALUE = VALUE .ABSOLUTE , backlight : String = "" ) -> int :
243+ value = minf (value , 1.0 )
244+ value = maxf (value , - 1.0 )
245+ value = value * 100.0
246+ var backlights := PackedStringArray ()
247+ if backlight .is_empty ():
248+ backlights = self .get_backlights ()
249+ else :
250+ backlights .push_back (backlight )
251+
252+ # Set the brightness for all backlights
253+ for backlight_name in backlights :
254+ var value_str := str (value ) + "%"
255+ if type == VALUE .RELATIVE :
256+ if value > 0.0 :
257+ value_str = "+" + value_str
258+ else :
259+ value_str = value_str + "-"
260+
261+ self .logger .debug ("Setting brightness on " + backlight_name + " to " + value_str )
262+ var cmd := _exec (["--device" , backlight_name , "set" , value_str ])
263+ if cmd .code != OK :
264+ return FAILED
265+
266+ return OK
267+
268+ func get_brightness (backlight : String = "" ) -> float :
269+ var info := self ._get_info (backlight )
270+ if info .size () < 4 :
271+ return - 1.0
272+
273+ # Example Output: amdgpu_bl1,backlight,128,50%,255
274+ var cur_brightness := info [3 ]
275+ cur_brightness = cur_brightness .replace ("%" , "" )
276+ if not cur_brightness .is_valid_int ():
277+ return - 1.0
278+
279+ return cur_brightness .to_float () / 100.0
280+
281+
282+ func get_brightness_value (backlight : String = "" ) -> int :
283+ var info := self ._get_info (backlight )
284+ if info .size () < 4 :
285+ return - 1
286+
287+ # Example Output: amdgpu_bl1,backlight,128,50%,255
288+ var cur_brightness := info [2 ]
289+ if not cur_brightness .is_valid_int ():
290+ return - 1
291+
292+ return cur_brightness .to_int ()
293+
294+ func get_max_brightness_value (backlight : String = "" ) -> int :
295+ var info := self ._get_info (backlight )
296+ if info .size () < 5 :
297+ return - 1
132298
299+ # Example Output: amdgpu_bl1,backlight,128,50%,255
300+ var max_brightness := info [4 ]
301+ if not max_brightness .is_valid_int ():
302+ return - 1
133303
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 )])
304+ return max_brightness .to_int ()
0 commit comments