Mercurial > libervia-backend
comparison libervia/backend/plugins/plugin_adhoc_dbus.py @ 4167:319a0e47dc8b
plugin ad-hoc D-Bus: fix deprecated use of python-dbus:
the plugin was using python-dbus which is deprecated in the backend in the favor of
TxDBus. Methods calls have been updated, and the plugin works again, but there seems to be
still some issues (warnings in the logs). Those will be fixed later.
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 01 Dec 2023 15:22:55 +0100 |
parents | 4b842c1fb686 |
children | 50c919dfe61b |
comparison
equal
deleted
inserted
replaced
4166:a1f7040b5a15 | 4167:319a0e47dc8b |
---|---|
15 # GNU Affero General Public License for more details. | 15 # GNU Affero General Public License for more details. |
16 | 16 |
17 # You should have received a copy of the GNU Affero General Public License | 17 # You should have received a copy of the GNU Affero General Public License |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | 19 |
20 from libervia.backend.core.i18n import D_, _ | 20 from collections import OrderedDict |
21 from libervia.backend.core.constants import Const as C | 21 import os.path |
22 from libervia.backend.core.log import getLogger | 22 import uuid |
23 | 23 |
24 log = getLogger(__name__) | |
25 from twisted.internet import defer | 24 from twisted.internet import defer |
25 from twisted.internet import reactor | |
26 from twisted.words.protocols.jabber import jid | 26 from twisted.words.protocols.jabber import jid |
27 from wokkel import data_form | 27 from wokkel import data_form |
28 | |
29 from libervia.backend.core.constants import Const as C | |
30 from libervia.backend.core.i18n import D_, _ | |
31 from libervia.backend.core.log import getLogger | |
32 | |
33 log = getLogger(__name__) | |
34 | |
28 | 35 |
29 try: | 36 try: |
30 from lxml import etree | 37 from lxml import etree |
31 except ImportError: | 38 except ImportError: |
32 etree = None | 39 etree = None |
33 log.warning("Missing module lxml, please download/install it from http://lxml.de/ ." | 40 log.warning("Missing module lxml, please download/install it from http://lxml.de/ ." |
34 "Auto D-Bus discovery will be disabled") | 41 "Auto D-Bus discovery will be disabled") |
35 from collections import OrderedDict | 42 |
36 import os.path | |
37 import uuid | |
38 try: | 43 try: |
39 import dbus | 44 import txdbus |
40 from dbus.mainloop.glib import DBusGMainLoop | 45 from txdbus import client as dbus_client |
41 except ImportError: | 46 except ImportError: |
42 dbus = None | 47 txdbus = None |
43 log.warning("Missing module dbus, please download/install it, " | 48 log.warning( |
44 "auto D-Bus discovery will be disabled") | 49 "Missing module txdbus, please download/install it, auto D-Bus discovery will be " |
45 | 50 "disabled" |
46 else: | 51 ) |
47 DBusGMainLoop(set_as_default=True) | 52 |
48 | 53 |
49 NS_MEDIA_PLAYER = "org.libervia.mediaplayer" | 54 NS_MEDIA_PLAYER = "org.libervia.mediaplayer" |
50 FD_NAME = "org.freedesktop.DBus" | 55 FD_NAME = "org.freedesktop.DBus" |
51 FD_PATH = "/org/freedekstop/DBus" | 56 FD_PATH = "/org/freedekstop/DBus" |
52 INTROSPECT_IFACE = "org.freedesktop.DBus.Introspectable" | 57 INTROSPECT_IFACE = "org.freedesktop.DBus.Introspectable" |
90 C.PI_HANDLER: "no", | 95 C.PI_HANDLER: "no", |
91 C.PI_DESCRIPTION: _("""Add D-Bus management to Ad-Hoc commands"""), | 96 C.PI_DESCRIPTION: _("""Add D-Bus management to Ad-Hoc commands"""), |
92 } | 97 } |
93 | 98 |
94 | 99 |
95 class AdHocDBus(object): | 100 class AdHocDBus: |
96 | 101 |
97 def __init__(self, host): | 102 def __init__(self, host): |
98 log.info(_("plugin Ad-Hoc D-Bus initialization")) | 103 log.info(f"plugin {PLUGIN_INFO[C.PI_NAME]!r} initialization") |
99 self.host = host | 104 self.host = host |
100 if etree is not None: | 105 if etree is not None: |
101 host.bridge.add_method( | 106 host.bridge.add_method( |
102 "ad_hoc_dbus_add_auto", | 107 "ad_hoc_dbus_add_auto", |
103 ".plugin", | 108 ".plugin", |
114 method=self._ad_hoc_remotes_get, | 119 method=self._ad_hoc_remotes_get, |
115 async_=True, | 120 async_=True, |
116 ) | 121 ) |
117 self._c = host.plugins["XEP-0050"] | 122 self._c = host.plugins["XEP-0050"] |
118 host.register_namespace("mediaplayer", NS_MEDIA_PLAYER) | 123 host.register_namespace("mediaplayer", NS_MEDIA_PLAYER) |
119 if dbus is not None: | 124 self.session_con = None |
120 self.session_bus = dbus.SessionBus() | 125 |
121 self.fd_object = self.session_bus.get_object( | 126 async def profile_connected(self, client): |
122 FD_NAME, FD_PATH, introspect=False) | 127 if txdbus is not None: |
123 | 128 if self.session_con is None: |
124 def profile_connected(self, client): | 129 self.session_con = await dbus_client.connect(reactor, 'session') |
125 if dbus is not None: | 130 self.fd_object = await self.session_con.getRemoteObject(FD_NAME, FD_PATH) |
131 | |
126 self._c.add_ad_hoc_command( | 132 self._c.add_ad_hoc_command( |
127 client, self.local_media_cb, D_("Media Players"), | 133 client, self.local_media_cb, D_("Media Players"), |
128 node=NS_MEDIA_PLAYER, | 134 node=NS_MEDIA_PLAYER, |
129 timeout=60*60*6 # 6 hours timeout, to avoid breaking remote | 135 timeout=60*60*6 # 6 hours timeout, to avoid breaking remote |
130 # in the middle of a movie | 136 # in the middle of a movie |
131 ) | 137 ) |
132 | 138 |
133 def _dbus_async_call(self, proxy, method, *args, **kwargs): | 139 async def _dbus_async_call(self, proxy, method, *args, **kwargs): |
134 """ Call a DBus method asynchronously and return a deferred | 140 """ Call a DBus method asynchronously and return a deferred |
135 | 141 |
136 @param proxy: DBus object proxy, as returner by get_object | 142 @param proxy: DBus object proxy, as returner by get_object |
137 @param method: name of the method to call | 143 @param method: name of the method to call |
138 @param args: will be transmitted to the method | 144 @param args: will be transmitted to the method |
140 values: | 146 values: |
141 - interface: name of the interface to use | 147 - interface: name of the interface to use |
142 @return: a deferred | 148 @return: a deferred |
143 | 149 |
144 """ | 150 """ |
145 d = defer.Deferred() | 151 return await proxy.callRemote(method, *args, **kwargs) |
146 interface = kwargs.pop("interface", None) | 152 |
147 kwargs["reply_handler"] = lambda ret=None: d.callback(ret) | 153 async def _dbus_get_property(self, proxy, interface, name): |
148 kwargs["error_handler"] = d.errback | 154 return await self._dbus_async_call( |
149 proxy.get_dbus_method(method, dbus_interface=interface)(*args, **kwargs) | |
150 return d | |
151 | |
152 def _dbus_get_property(self, proxy, interface, name): | |
153 return self._dbus_async_call( | |
154 proxy, "Get", interface, name, interface="org.freedesktop.DBus.Properties") | 155 proxy, "Get", interface, name, interface="org.freedesktop.DBus.Properties") |
155 | 156 |
156 | 157 |
157 def _dbus_list_names(self): | 158 async def _dbus_list_names(self): |
158 return self._dbus_async_call(self.fd_object, "ListNames") | 159 return await self.fd_object.callRemote("ListNames") |
159 | 160 |
160 def _dbus_introspect(self, proxy): | 161 async def _dbus_introspect(self, proxy): |
161 return self._dbus_async_call(proxy, INTROSPECT_METHOD, interface=INTROSPECT_IFACE) | 162 return await self._dbus_async_call(proxy, INTROSPECT_METHOD, interface=INTROSPECT_IFACE) |
162 | 163 |
163 def _accept_method(self, method): | 164 def _accept_method(self, method): |
164 """ Return True if we accept the method for a command | 165 """ Return True if we accept the method for a command |
165 @param method: etree.Element | 166 @param method: etree.Element |
166 @return: True if the method is acceptable | 167 @return: True if the method is acceptable |
170 "arg[@direction='in']" | 171 "arg[@direction='in']" |
171 ): # we don't accept method with argument for the moment | 172 ): # we don't accept method with argument for the moment |
172 return False | 173 return False |
173 return True | 174 return True |
174 | 175 |
175 @defer.inlineCallbacks | 176 async def _introspect(self, methods, bus_name, proxy): |
176 def _introspect(self, methods, bus_name, proxy): | |
177 log.debug("introspecting path [%s]" % proxy.object_path) | 177 log.debug("introspecting path [%s]" % proxy.object_path) |
178 introspect_xml = yield self._dbus_introspect(proxy) | 178 assert etree is not None |
179 introspect_xml = await self._dbus_introspect(proxy) | |
179 el = etree.fromstring(introspect_xml) | 180 el = etree.fromstring(introspect_xml) |
180 for node in el.iterchildren("node", "interface"): | 181 for node in el.iterchildren("node", "interface"): |
181 if node.tag == "node": | 182 if node.tag == "node": |
182 new_path = os.path.join(proxy.object_path, node.get("name")) | 183 new_path = os.path.join(proxy.object_path, node.get("name")) |
183 new_proxy = self.session_bus.get_object( | 184 new_proxy = await self.session_con.getRemoteObject( |
184 bus_name, new_path, introspect=False | 185 bus_name, new_path |
185 ) | 186 ) |
186 yield self._introspect(methods, bus_name, new_proxy) | 187 await self._introspect(methods, bus_name, new_proxy) |
187 elif node.tag == "interface": | 188 elif node.tag == "interface": |
188 name = node.get("name") | 189 name = node.get("name") |
189 if any(name.startswith(ignored) for ignored in IGNORED_IFACES_START): | 190 if any(name.startswith(ignored) for ignored in IGNORED_IFACES_START): |
190 log.debug("interface [%s] is ignored" % name) | 191 log.debug("interface [%s] is ignored" % name) |
191 continue | 192 continue |
201 client = self.host.get_client(profile_key) | 202 client = self.host.get_client(profile_key) |
202 return self.ad_hoc_dbus_add_auto( | 203 return self.ad_hoc_dbus_add_auto( |
203 client, prog_name, allowed_jids, allowed_groups, allowed_magics, | 204 client, prog_name, allowed_jids, allowed_groups, allowed_magics, |
204 forbidden_jids, forbidden_groups, flags) | 205 forbidden_jids, forbidden_groups, flags) |
205 | 206 |
206 @defer.inlineCallbacks | 207 async def ad_hoc_dbus_add_auto(self, client, prog_name, allowed_jids=None, allowed_groups=None, |
207 def ad_hoc_dbus_add_auto(self, client, prog_name, allowed_jids=None, allowed_groups=None, | |
208 allowed_magics=None, forbidden_jids=None, forbidden_groups=None, | 208 allowed_magics=None, forbidden_jids=None, forbidden_groups=None, |
209 flags=None): | 209 flags=None): |
210 bus_names = yield self._dbus_list_names() | 210 bus_names = await self._dbus_list_names() |
211 bus_names = [bus_name for bus_name in bus_names if "." + prog_name in bus_name] | 211 bus_names = [bus_name for bus_name in bus_names if "." + prog_name in bus_name] |
212 if not bus_names: | 212 if not bus_names: |
213 log.info("Can't find any bus for [%s]" % prog_name) | 213 log.info("Can't find any bus for [%s]" % prog_name) |
214 defer.returnValue(("", [])) | 214 return ("", []) |
215 bus_names.sort() | 215 bus_names.sort() |
216 for bus_name in bus_names: | 216 for bus_name in bus_names: |
217 if bus_name.endswith(prog_name): | 217 if bus_name.endswith(prog_name): |
218 break | 218 break |
219 log.info("bus name found: [%s]" % bus_name) | 219 else: |
220 proxy = self.session_bus.get_object(bus_name, "/", introspect=False) | 220 log.info(f"Can't find any command for {prog_name}") |
221 return ("", []) | |
222 log.info(f"bus name found: {bus_name}") | |
223 proxy = await self.session_con.getRemoteObject(bus_name, "/") | |
221 methods = set() | 224 methods = set() |
222 | 225 |
223 yield self._introspect(methods, bus_name, proxy) | 226 await self._introspect(methods, bus_name, proxy) |
224 | 227 |
225 if methods: | 228 if methods: |
226 self._add_command( | 229 self._add_command( |
227 client, | 230 client, |
228 prog_name, | 231 prog_name, |
234 forbidden_jids=forbidden_jids, | 237 forbidden_jids=forbidden_jids, |
235 forbidden_groups=forbidden_groups, | 238 forbidden_groups=forbidden_groups, |
236 flags=flags, | 239 flags=flags, |
237 ) | 240 ) |
238 | 241 |
239 defer.returnValue((str(bus_name), methods)) | 242 return (str(bus_name), methods) |
240 | 243 |
241 def _add_command(self, client, adhoc_name, bus_name, methods, allowed_jids=None, | 244 def _add_command(self, client, adhoc_name, bus_name, methods, allowed_jids=None, |
242 allowed_groups=None, allowed_magics=None, forbidden_jids=None, | 245 allowed_groups=None, allowed_magics=None, forbidden_jids=None, |
243 forbidden_groups=None, flags=None): | 246 forbidden_groups=None, flags=None): |
244 if flags is None: | 247 if flags is None: |
245 flags = set() | 248 flags = set() |
246 | 249 |
247 def d_bus_callback(client, command_elt, session_data, action, node): | 250 async def d_bus_callback(client, command_elt, session_data, action, node): |
248 actions = session_data.setdefault("actions", []) | 251 actions = session_data.setdefault("actions", []) |
249 names_map = session_data.setdefault("names_map", {}) | 252 names_map = session_data.setdefault("names_map", {}) |
250 actions.append(action) | 253 actions.append(action) |
251 | 254 |
252 if len(actions) == 1: | 255 if len(actions) == 1: |
279 | 282 |
280 if command not in names_map: | 283 if command not in names_map: |
281 raise self._c.AdHocError(self._c.ERROR.BAD_PAYLOAD) | 284 raise self._c.AdHocError(self._c.ERROR.BAD_PAYLOAD) |
282 | 285 |
283 path, iface, command = names_map[command] | 286 path, iface, command = names_map[command] |
284 proxy = self.session_bus.get_object(bus_name, path) | 287 proxy = await self.session_con.getRemoteObject(bus_name, path) |
285 | 288 |
286 self._dbus_async_call(proxy, command, interface=iface) | 289 await self._dbus_async_call(proxy, command, interface=iface) |
287 | 290 |
288 # job done, we can end the session, except if we have FLAG_LOOP | 291 # job done, we can end the session, except if we have FLAG_LOOP |
289 if FLAG_LOOP in flags: | 292 if FLAG_LOOP in flags: |
290 # We have a loop, so we clear everything and we execute again the | 293 # We have a loop, so we clear everything and we execute again the |
291 # command as we had a first call (command_elt is not used, so None | 294 # command as we had a first call (command_elt is not used, so None |
292 # is OK) | 295 # is OK) |
293 del actions[:] | 296 del actions[:] |
294 names_map.clear() | 297 names_map.clear() |
295 return d_bus_callback( | 298 return await d_bus_callback( |
296 client, None, session_data, self._c.ACTION.EXECUTE, node | 299 client, None, session_data, self._c.ACTION.EXECUTE, node |
297 ) | 300 ) |
298 form = data_form.Form("form", title=_("Updated")) | 301 form = data_form.Form("form", title=_("Updated")) |
299 form.addField(data_form.Field("fixed", "Command sent")) | 302 form.addField(data_form.Field("fixed", "Command sent")) |
300 status = self._c.STATUS.COMPLETED | 303 status = self._c.STATUS.COMPLETED |
319 ## Local media ## | 322 ## Local media ## |
320 | 323 |
321 def _ad_hoc_remotes_get(self, profile): | 324 def _ad_hoc_remotes_get(self, profile): |
322 return self.ad_hoc_remotes_get(self.host.get_client(profile)) | 325 return self.ad_hoc_remotes_get(self.host.get_client(profile)) |
323 | 326 |
324 @defer.inlineCallbacks | 327 async def ad_hoc_remotes_get(self, client): |
325 def ad_hoc_remotes_get(self, client): | |
326 """Retrieve available remote media controlers in our devices | 328 """Retrieve available remote media controlers in our devices |
327 @return (list[tuple[unicode, unicode, unicode]]): list of devices with: | 329 @return (list[tuple[unicode, unicode, unicode]]): list of devices with: |
328 - entity full jid | 330 - entity full jid |
329 - device name | 331 - device name |
330 - device label | 332 - device label |
331 """ | 333 """ |
332 found_data = yield defer.ensureDeferred(self.host.find_by_features( | 334 found_data = await defer.ensureDeferred(self.host.find_by_features( |
333 client, [self.host.ns_map['commands']], service=False, roster=False, | 335 client, [self.host.ns_map['commands']], service=False, roster=False, |
334 own_jid=True, local_device=True)) | 336 own_jid=True, local_device=True)) |
335 | 337 |
336 remotes = [] | 338 remotes = [] |
337 | 339 |
338 for found in found_data: | 340 for found in found_data: |
339 for device_jid_s in found: | 341 for device_jid_s in found: |
340 device_jid = jid.JID(device_jid_s) | 342 device_jid = jid.JID(device_jid_s) |
341 cmd_list = yield self._c.list(client, device_jid) | 343 cmd_list = await self._c.list(client, device_jid) |
342 for cmd in cmd_list: | 344 for cmd in cmd_list: |
343 if cmd.nodeIdentifier == NS_MEDIA_PLAYER: | 345 if cmd.nodeIdentifier == NS_MEDIA_PLAYER: |
344 try: | 346 try: |
345 result_elt = yield self._c.do(client, device_jid, | 347 result_elt = await self._c.do(client, device_jid, |
346 NS_MEDIA_PLAYER, timeout=5) | 348 NS_MEDIA_PLAYER, timeout=5) |
347 command_elt = self._c.get_command_elt(result_elt) | 349 command_elt = self._c.get_command_elt(result_elt) |
348 form = data_form.findForm(command_elt, NS_MEDIA_PLAYER) | 350 form = data_form.findForm(command_elt, NS_MEDIA_PLAYER) |
349 if form is None: | 351 if form is None: |
350 continue | 352 continue |
364 except Exception as e: | 366 except Exception as e: |
365 log.warning(_( | 367 log.warning(_( |
366 "Can't retrieve remote controllers on {device_jid}: " | 368 "Can't retrieve remote controllers on {device_jid}: " |
367 "{reason}".format(device_jid=device_jid, reason=e))) | 369 "{reason}".format(device_jid=device_jid, reason=e))) |
368 break | 370 break |
369 defer.returnValue(remotes) | 371 return remotes |
370 | 372 |
371 def do_mpris_command(self, proxy, command): | 373 async def do_mpris_command(self, proxy, command): |
372 iface, command = command.rsplit(".", 1) | 374 iface, command = command.rsplit(".", 1) |
373 if command == CMD_GO_BACK: | 375 if command == CMD_GO_BACK: |
374 command = 'Seek' | 376 command = 'Seek' |
375 args = [-SEEK_OFFSET] | 377 args = [-SEEK_OFFSET] |
376 elif command == CMD_GO_FWD: | 378 elif command == CMD_GO_FWD: |
377 command = 'Seek' | 379 command = 'Seek' |
378 args = [SEEK_OFFSET] | 380 args = [SEEK_OFFSET] |
379 else: | 381 else: |
380 args = [] | 382 args = [] |
381 return self._dbus_async_call(proxy, command, *args, interface=iface) | 383 return await self._dbus_async_call(proxy, command, *args, interface=iface) |
382 | 384 |
383 def add_mpris_metadata(self, form, metadata): | 385 def add_mpris_metadata(self, form, metadata): |
384 """Serialise MRPIS Metadata according to MPRIS_METADATA_MAP""" | 386 """Serialise MRPIS Metadata according to MPRIS_METADATA_MAP""" |
385 for mpris_key, name in MPRIS_METADATA_MAP.items(): | 387 for mpris_key, name in MPRIS_METADATA_MAP.items(): |
386 if mpris_key in metadata: | 388 if mpris_key in metadata: |
387 value = str(metadata[mpris_key]) | 389 value = str(metadata[mpris_key]) |
388 form.addField(data_form.Field(fieldType="fixed", | 390 form.addField(data_form.Field(fieldType="fixed", |
389 var=name, | 391 var=name, |
390 value=value)) | 392 value=value)) |
391 | 393 |
392 @defer.inlineCallbacks | 394 async def local_media_cb(self, client, command_elt, session_data, action, node): |
393 def local_media_cb(self, client, command_elt, session_data, action, node): | 395 assert txdbus is not None |
394 try: | 396 try: |
395 x_elt = next(command_elt.elements(data_form.NS_X_DATA, "x")) | 397 x_elt = next(command_elt.elements(data_form.NS_X_DATA, "x")) |
396 command_form = data_form.Form.fromElement(x_elt) | 398 command_form = data_form.Form.fromElement(x_elt) |
397 except StopIteration: | 399 except StopIteration: |
398 command_form = None | 400 command_form = None |
399 | 401 |
400 if command_form is None or len(command_form.fields) == 0: | 402 if command_form is None or len(command_form.fields) == 0: |
401 # root request, we looks for media players | 403 # root request, we looks for media players |
402 bus_names = yield self._dbus_list_names() | 404 bus_names = await self._dbus_list_names() |
403 bus_names = [b for b in bus_names if b.startswith(MPRIS_PREFIX)] | 405 bus_names = [b for b in bus_names if b.startswith(MPRIS_PREFIX)] |
404 if len(bus_names) == 0: | 406 if len(bus_names) == 0: |
405 note = (self._c.NOTE.INFO, D_("No media player found.")) | 407 note = (self._c.NOTE.INFO, D_("No media player found.")) |
406 defer.returnValue((None, self._c.STATUS.COMPLETED, None, note)) | 408 return (None, self._c.STATUS.COMPLETED, None, note) |
407 options = [] | 409 options = [] |
408 status = self._c.STATUS.EXECUTING | 410 status = self._c.STATUS.EXECUTING |
409 form = data_form.Form("form", title=D_("Media Player Selection"), | 411 form = data_form.Form("form", title=D_("Media Player Selection"), |
410 formNamespace=NS_MEDIA_PLAYER) | 412 formNamespace=NS_MEDIA_PLAYER) |
411 for bus in bus_names: | 413 for bus in bus_names: |
417 field = data_form.Field( | 419 field = data_form.Field( |
418 "list-single", "media_player", options=options, required=True | 420 "list-single", "media_player", options=options, required=True |
419 ) | 421 ) |
420 form.addField(field) | 422 form.addField(field) |
421 payload = form.toElement() | 423 payload = form.toElement() |
422 defer.returnValue((payload, status, None, None)) | 424 return (payload, status, None, None) |
423 else: | 425 else: |
424 # player request | 426 # player request |
425 try: | 427 try: |
426 bus_name = command_form["media_player"] | 428 bus_name = command_form["media_player"] |
427 except KeyError: | 429 except KeyError: |
430 if not bus_name.startswith(MPRIS_PREFIX): | 432 if not bus_name.startswith(MPRIS_PREFIX): |
431 log.warning(_("Media player ad-hoc command trying to use non MPRIS bus. " | 433 log.warning(_("Media player ad-hoc command trying to use non MPRIS bus. " |
432 "Hack attempt? Refused bus: {bus_name}").format( | 434 "Hack attempt? Refused bus: {bus_name}").format( |
433 bus_name=bus_name)) | 435 bus_name=bus_name)) |
434 note = (self._c.NOTE.ERROR, D_("Invalid player name.")) | 436 note = (self._c.NOTE.ERROR, D_("Invalid player name.")) |
435 defer.returnValue((None, self._c.STATUS.COMPLETED, None, note)) | 437 return (None, self._c.STATUS.COMPLETED, None, note) |
436 | 438 |
437 try: | 439 try: |
438 proxy = self.session_bus.get_object(bus_name, MPRIS_PATH) | 440 proxy = await self.session_con.getRemoteObject( |
439 except dbus.exceptions.DBusException as e: | 441 bus_name, MPRIS_PATH, "org.mpris.MediaPlayer2.Player" |
442 ) | |
443 except Exception as e: | |
440 log.warning(_("Can't get D-Bus proxy: {reason}").format(reason=e)) | 444 log.warning(_("Can't get D-Bus proxy: {reason}").format(reason=e)) |
441 note = (self._c.NOTE.ERROR, D_("Media player is not available anymore")) | 445 note = (self._c.NOTE.ERROR, D_("Media player is not available anymore")) |
442 defer.returnValue((None, self._c.STATUS.COMPLETED, None, note)) | 446 return (None, self._c.STATUS.COMPLETED, None, note) |
443 try: | 447 try: |
444 command = command_form["command"] | 448 command = command_form["command"] |
445 except KeyError: | 449 except KeyError: |
446 pass | 450 pass |
447 else: | 451 else: |
448 yield self.do_mpris_command(proxy, command) | 452 await self.do_mpris_command(proxy, command) |
449 | 453 |
450 # we construct the remote control form | 454 # we construct the remote control form |
451 form = data_form.Form("form", title=D_("Media Player Selection")) | 455 form = data_form.Form("form", title=D_("Media Player Selection")) |
452 form.addField(data_form.Field(fieldType="hidden", | 456 form.addField(data_form.Field(fieldType="hidden", |
453 var="media_player", | 457 var="media_player", |
454 value=bus_name)) | 458 value=bus_name)) |
455 for iface, properties_names in MPRIS_PROPERTIES.items(): | 459 for iface, properties_names in MPRIS_PROPERTIES.items(): |
456 for name in properties_names: | 460 for name in properties_names: |
457 try: | 461 try: |
458 value = yield self._dbus_get_property(proxy, iface, name) | 462 value = await self._dbus_get_property(proxy, iface, name) |
459 except Exception as e: | 463 except Exception as e: |
460 log.warning(_("Can't retrieve attribute {name}: {reason}") | 464 log.warning(_("Can't retrieve attribute {name}: {reason}") |
461 .format(name=name, reason=e)) | 465 .format(name=name, reason=e)) |
462 continue | 466 continue |
463 if name == MPRIS_METADATA_KEY: | 467 if name == MPRIS_METADATA_KEY: |
473 options=commands, | 477 options=commands, |
474 required=True)) | 478 required=True)) |
475 | 479 |
476 payload = form.toElement() | 480 payload = form.toElement() |
477 status = self._c.STATUS.EXECUTING | 481 status = self._c.STATUS.EXECUTING |
478 defer.returnValue((payload, status, None, None)) | 482 return (payload, status, None, None) |