Skip to content

Commit

Permalink
bluez.Base: Don't subclass from Gio.DBusProxy
Browse files Browse the repository at this point in the history
So we can get to the invalidated properties.
  • Loading branch information
infirit committed Jan 27, 2023
1 parent ac6d546 commit 760511d
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 35 deletions.
4 changes: 2 additions & 2 deletions blueman/bluez/AnyBase.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ def on_signal(
) -> None:
iface_name, changed, invalidated = param.unpack()
if iface_name == interface_name and this is not None:
for name, value in changed.items():
this.emit('property-changed', name, value, object_path)
for key in list(changed) + invalidated:
this.emit('property-changed', key, changed.get(key, None), object_path)

weakref.finalize(
self,
Expand Down
81 changes: 48 additions & 33 deletions blueman/bluez/Base.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,10 @@ def __call__(cls, *args: object, **kwargs: str) -> "Base":
return instance


class Base(Gio.DBusProxy, metaclass=BaseMeta):
connect_signal = GObject.GObject.connect
disconnect_signal = GObject.GObject.disconnect

class Base(GObject.Object, metaclass=BaseMeta):
__name = 'org.bluez'
__bus_type = Gio.BusType.SYSTEM
__proxy: Gio.DBusProxy

__gsignals__: GSignals = {
'property-changed': (GObject.SignalFlags.NO_HOOKS, None, (str, object, str))
Expand All @@ -40,26 +38,36 @@ class Base(Gio.DBusProxy, metaclass=BaseMeta):

_interface_name: str

connect_signal = GObject.GObject.connect
disconnect_signal = GObject.GObject.disconnect

def __init__(self, *, obj_path: str):
super().__init__(
g_name=self.__name,
g_interface_name=self._interface_name,
g_object_path=obj_path,
g_bus_type=self.__bus_type,
# FIXME See issue 620
g_flags=Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES)

self.init()
super().__init__()

self.__proxy = Gio.DBusProxy.new_for_bus_sync(
self.__bus_type,
Gio.DBusProxyFlags.NONE,
None,
self.__name,
obj_path,
self._interface_name,
None
)

self.__proxy.connect("g-properties-changed", self.__properties_changed)

self.__fallback = {'Icon': 'blueman', 'Class': 0, 'Appearance': 0}

self.__variant_map = {str: 's', int: 'u', bool: 'b'}

def do_g_properties_changed(self, changed_properties: GLib.Variant, _invalidated_properties: List[str]) -> None:
def __properties_changed(self, _proxy: Gio.DBusProxy, changed_properties: GLib.Variant,
invalidated_properties: List[str]) -> None:
changed = changed_properties.unpack()
object_path = self.get_object_path()
logging.debug(f"{object_path} {changed}")
for key, value in changed.items():
self.emit("property-changed", key, value, object_path)
logging.debug(f"{object_path} {changed} {invalidated_properties} {self}")

for key in list(changed) + invalidated_properties:
self.emit("property-changed", key, changed.get(key, None), object_path)

def _call(
self,
Expand All @@ -69,7 +77,7 @@ def _call(
error_handler: Optional[Callable[[BluezDBusException], None]] = None,
) -> None:
def callback(
proxy: Base,
proxy: Gio.DBusProxy,
result: Gio.AsyncResult,
reply: Optional[Callable[..., None]],
error: Optional[Callable[[BluezDBusException], None]],
Expand All @@ -82,22 +90,22 @@ def callback(
if error:
error(parse_dbus_error(e))
else:
logging.error(f"Unhandled error for {self.get_interface_name()}.{method}", exc_info=True)
logging.error(f"Unhandled error for {self.__proxy.get_interface_name()}.{method}", exc_info=True)

self.call(method, param, Gio.DBusCallFlags.NONE, GLib.MAXINT, None,
callback, reply_handler, error_handler)
self.__proxy.call(method, param, Gio.DBusCallFlags.NONE, GLib.MAXINT, None,
callback, reply_handler, error_handler)

def get(self, name: str) -> Any:
try:
prop = self.call_sync(
prop = self.__proxy.call_sync(
'org.freedesktop.DBus.Properties.Get',
GLib.Variant('(ss)', (self._interface_name, name)),
Gio.DBusCallFlags.NONE,
GLib.MAXINT,
None)
return prop.unpack()[0]
except GLib.Error as e:
property = self.get_cached_property(name)
property = self.__proxy.get_cached_property(name)
if property is not None:
return property.unpack()
elif name in self.__fallback:
Expand All @@ -108,19 +116,22 @@ def get(self, name: str) -> Any:
def set(self, name: str, value: Union[str, int, bool]) -> None:
v = GLib.Variant(self.__variant_map[type(value)], value)
param = GLib.Variant('(ssv)', (self._interface_name, name, v))
self.call('org.freedesktop.DBus.Properties.Set',
param,
Gio.DBusCallFlags.NONE,
GLib.MAXINT,
None)
self.__proxy.call('org.freedesktop.DBus.Properties.Set',
param,
Gio.DBusCallFlags.NONE,
GLib.MAXINT,
None)

def get_object_path(self) -> str:
return self.__proxy.get_object_path()

def get_properties(self) -> Dict[str, Any]:
param = GLib.Variant('(s)', (self._interface_name,))
res = self.call_sync('org.freedesktop.DBus.Properties.GetAll',
param,
Gio.DBusCallFlags.NONE,
GLib.MAXINT,
None)
res = self.__proxy.call_sync('org.freedesktop.DBus.Properties.GetAll',
param,
Gio.DBusCallFlags.NONE,
GLib.MAXINT,
None)

props: Dict[str, Any] = res.unpack()[0]
for k, v in self.__fallback.items():
Expand All @@ -131,6 +142,10 @@ def get_properties(self) -> Dict[str, Any]:

return props

def destroy(self) -> None:
if self.__proxy:
del self.__proxy

def __getitem__(self, key: str) -> Any:
return self.get(key)

Expand Down

0 comments on commit 760511d

Please sign in to comment.