fix(services/spotlight): improve MPRIS artwork handling and scope keyword searches to single plugin
- mpris: native MediaArt cache lookup, dedupe play/pause emission, safe cleanup, artwork polling for already-playing browser players, drop os.system seek fallback - spotlight: scope plugin keyword and detect() matches to a single plugin via search_single instead of global search; register clipboard keywords (clip/clipboard)
This commit is contained in:
43 files changed
+1227
-637
No files matched your search
@@ -0,0 +1,110 @@
|
||||
from fabric.core.service import Property, Service, Signal
|
||||
from fabric.utils import Gio, GLib, logger
|
||||
|
||||
_BUS_NAME = "org.freedesktop.ScreenSaver"
|
||||
_OBJECT_PATH = "/org/freedesktop/ScreenSaver"
|
||||
_INTERFACE = "org.freedesktop.ScreenSaver"
|
||||
|
||||
|
||||
class InhibitService(Service):
|
||||
"""Service for managing idle inhibition via org.freedesktop.ScreenSaver D-Bus."""
|
||||
|
||||
_instance = None
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
if cls._instance is None:
|
||||
cls._instance = super().__new__(cls)
|
||||
return cls._instance
|
||||
|
||||
@Signal
|
||||
def inhibit_changed(self, active: bool) -> None:
|
||||
"""Signal emitted when inhibit state changes."""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
if getattr(self, "_initialized", False):
|
||||
return
|
||||
self._initialized = True
|
||||
super().__init__(**kwargs)
|
||||
self._cookie: int | None = None
|
||||
self._proxy: Gio.DBusProxy | None = None
|
||||
|
||||
@Property(bool, "readable", default_value=False)
|
||||
def active(self) -> bool:
|
||||
return self._cookie is not None
|
||||
|
||||
def _get_proxy(self) -> Gio.DBusProxy | None:
|
||||
if self._proxy is not None:
|
||||
return self._proxy
|
||||
try:
|
||||
bus = Gio.bus_get_sync(Gio.BusType.SESSION, None)
|
||||
if bus is None:
|
||||
return None
|
||||
self._proxy = Gio.DBusProxy.new_sync(
|
||||
bus,
|
||||
Gio.DBusProxyFlags.NONE,
|
||||
None,
|
||||
_BUS_NAME,
|
||||
_OBJECT_PATH,
|
||||
_INTERFACE,
|
||||
None,
|
||||
)
|
||||
return self._proxy
|
||||
except Exception as e:
|
||||
logger.error(f"[InhibitService] Failed to create D-Bus proxy: {e}")
|
||||
return None
|
||||
|
||||
def enable(self) -> bool:
|
||||
if self.active:
|
||||
return True
|
||||
proxy = self._get_proxy()
|
||||
if proxy is None:
|
||||
return False
|
||||
try:
|
||||
result = proxy.call_sync(
|
||||
"Inhibit",
|
||||
GLib.Variant("(ss)", ("Modus", "Caffeine mode")),
|
||||
Gio.DBusCallFlags.NONE,
|
||||
-1,
|
||||
None,
|
||||
)
|
||||
if result is not None:
|
||||
self._cookie = result.unpack()[0]
|
||||
self.emit("inhibit_changed", True)
|
||||
return True
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error(f"[InhibitService] Failed to inhibit: {e}")
|
||||
return False
|
||||
|
||||
def disable(self) -> bool:
|
||||
if not self.active:
|
||||
return True
|
||||
proxy = self._get_proxy()
|
||||
if proxy is None or self._cookie is None:
|
||||
return False
|
||||
try:
|
||||
proxy.call_sync(
|
||||
"Uninhibit",
|
||||
GLib.Variant("(u)", (self._cookie,)),
|
||||
Gio.DBusCallFlags.NONE,
|
||||
-1,
|
||||
None,
|
||||
)
|
||||
self._cookie = None
|
||||
self.emit("inhibit_changed", False)
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"[InhibitService] Failed to uninhibit: {e}")
|
||||
return False
|
||||
|
||||
def toggle(self) -> bool:
|
||||
if self.active:
|
||||
self.disable()
|
||||
return False
|
||||
else:
|
||||
self.enable()
|
||||
return True
|
||||
|
||||
|
||||
def get_inhibit_service() -> InhibitService:
|
||||
return InhibitService()
|
||||
Reference in new issue
Block a user