Power management inhibition does not work properly
Environment
- Lollypop version: most recent (
master
branch) - GTK+ version:
3.24.33-1ubuntu2
(but irrelevant) - Operating system:
Linux Mint 21.1
(but irrelevant)
Bug
The issue described in #2801 (closed) did also occur on my system. I did some investigation, the result is that the Inhibitor has various problems. By the way, the shutdown
flag in systemd-inhibit
is set by Gtk.Application.inhibit
when the suspend
flag is set. This may be intended, because the flags for the gtk call do only match those of org.gnome.SessionManager
, but not those of org.login1.Manager
. But this affects gtk
and gnome-session
and I don't know the details. However, here are the problems with the inhibition:
- On startup, the inhibition lock is applied right away. The problem is the line https://gitlab.gnome.org/World/lollypop/-/blob/master/lollypop/inhibitor.py#L50. I guess this line was added because of the misleading name
__update_flags_settings
. - Changing
/org/gnome/Lollypop/power-management
tonone
and back to some other value> 0
leads to persistent inhibition. This is becauseself.__status_handler_id
isn't reset toNone
in__disable_react_to_playback
. - Stopping the playback in fullscreen mode and exiting fullscreen mode will leave the inhibition because of https://gitlab.gnome.org/World/lollypop/-/blob/master/lollypop/inhibitor.py#L134.
I tried to tidy up the file inhibitor.py
and am proposing the following changes:
diff --git a/lollypop/fullscreen.py b/lollypop/fullscreen.py
index 2dc4cf247..285567a86 100644
--- a/lollypop/fullscreen.py
+++ b/lollypop/fullscreen.py
@@ -175,7 +175,7 @@ class FullScreen(Gtk.Window, SignalsHelper):
monitor = screen.get_monitor_at_window(App().main_window.get_window())
self.fullscreen_on_monitor(screen, monitor)
# Disable screensaver (idle)
- App().inhibitor.manual_inhibit(
+ App().inhibitor.override_inhibit(
Gtk.ApplicationInhibitFlags.IDLE |
Gtk.ApplicationInhibitFlags.SUSPEND)
@@ -187,7 +187,7 @@ class FullScreen(Gtk.Window, SignalsHelper):
if self.__timeout_id is not None:
GLib.source_remove(self.__timeout_id)
self.__timeout_id = None
- App().inhibitor.manual_uninhibit()
+ App().inhibitor.unoverride_inhibit()
@property
def miniplayer(self):
diff --git a/lollypop/inhibitor.py b/lollypop/inhibitor.py
index c04fb05e5..b3eb57d9b 100644
--- a/lollypop/inhibitor.py
+++ b/lollypop/inhibitor.py
@@ -21,12 +21,15 @@ from lollypop.define import App, PowerManagement
class Inhibitor:
+ """
+ Register to playback status changes so that standby/idle is only
+ inhibited while playing
+ """
def __init__(self):
self.__cookie = 0
self.__status_handler_id = None # The playback listener
- self.__current_player_state = None
- self.__manual_inhibit = False
+ self.__override_inhibit = False
# Load and apply the inhibit settings
self.__on_powermanagement_setting_changed(App().settings)
@@ -37,64 +40,61 @@ class Inhibitor:
)
def __on_powermanagement_setting_changed(self, settings, name=None):
- """
- Register to playback status changes so that standby/idle is only
- inhibited while playing
- """
if settings.get_enum("power-management") > 0:
self.__enable_react_to_playback()
else:
self.__disable_react_to_playback()
- self.__uninhibit()
- # Update the flags according to the settings.
- self.__update_flags_settings()
+ self.__uninhibit()
+ self.__on_status_changed()
def __disable_react_to_playback(self):
if self.__status_handler_id is not None:
App().player.disconnect(self.__status_handler_id)
+ self.__status_handler_id = None
def __enable_react_to_playback(self):
- self.__on_status_changed(App().player)
if self.__status_handler_id is None:
self.__status_handler_id = App().player.connect(
"status-changed",
self.__on_status_changed,
)
- def __on_status_changed(self, player):
+ def __on_status_changed(self, player=None):
"""
React to a change of playback state
"""
- new_state = player.get_status()
- if self.__current_player_state != new_state:
- self.__current_player_state = new_state
- if self.__current_player_state == Gst.State.PLAYING:
- self.__update_flags_settings()
- else:
- self.__uninhibit()
-
- def __update_flags_settings(self):
+ if not player:
+ player = App().player
+ if player.get_status() == Gst.State.PLAYING:
+ self.__inhibit()
+ else:
+ self.__uninhibit()
+
+ def __get_flags_settings(self):
"""
- Update the inhibit flags according to the settings in dconf
+ Get the inhibit flags according to the settings in dconf
"""
power_management = App().settings.get_enum("power-management")
if power_management == PowerManagement.BOTH:
- self.__inhibit(Gtk.ApplicationInhibitFlags.IDLE |
- Gtk.ApplicationInhibitFlags.SUSPEND)
+ return Gtk.ApplicationInhibitFlags.IDLE | \
+ Gtk.ApplicationInhibitFlags.SUSPEND
elif power_management == PowerManagement.SUSPEND:
- self.__inhibit(Gtk.ApplicationInhibitFlags.SUSPEND)
+ return Gtk.ApplicationInhibitFlags.SUSPEND
elif power_management == PowerManagement.IDLE:
- self.__inhibit(Gtk.ApplicationInhibitFlags.IDLE)
+ return Gtk.ApplicationInhibitFlags.IDLE
+ else:
+ return None
- def __inhibit(self, flags):
+ def __inhibit(self, flags=None):
"""
Disable flags
@param flags as Gtk.ApplicationInhibitFlags
"""
- if self.__manual_inhibit:
- # temporary blocked inhibit changes
+ if self.__override_inhibit:
return
- if not self.__cookie:
+ if not flags:
+ flags = self.__get_flags_settings()
+ if not self.__cookie and flags:
self.__cookie = App().inhibit(
App().window,
flags,
@@ -104,31 +104,29 @@ class Inhibitor:
"""
Remove all the powermanagement settings
"""
- if self.__manual_inhibit:
- # temporary blocked inhibit changes
+ if self.__override_inhibit:
return
if self.__cookie:
App().uninhibit(self.__cookie)
self.__cookie = 0
- self.__current_player_state = None
- def manual_inhibit(self, flags):
+ def override_inhibit(self, flags):
"""
Inhibit suspend or idle manually.
The settings values from dconf are not applied while a
- manual_inhibit() call is active.
- Disable the manual override with manual_uninhibit().
+ override_inhibit() call is active.
+ Disable the manual override with unoverride_inhibit().
@param flags as Gtk.ApplicationInhibitFlags
"""
self.__uninhibit()
self.__inhibit(flags)
- self.__manual_inhibit = True
+ self.__override_inhibit = True
- def manual_uninhibit(self):
+ def unoverride_inhibit(self):
"""
- removing the manual inhibited state and restore the settings from
+ Remove the manual inhibit state and restore the settings from
dconf
"""
- self.__manual_inhibit = False
+ self.__override_inhibit = False
self.__uninhibit()
- self.__update_flags_settings()
+ self.__on_status_changed()