Mercurial > libervia-desktop-kivy
view cagou/plugins/plugin_wid_remote.py @ 294:a8518a091766
Added tag 0.7.0b1 for changeset 5c28cf881531
author | Goffi <goffi@goffi.org> |
---|---|
date | Sun, 05 May 2019 21:35:38 +0200 |
parents | 1b835bcfa663 |
children | b2727877bad4 |
line wrap: on
line source
#!/usr/bin/env python2 # -*- coding: utf-8 -*- # Cagou: desktop/mobile frontend for Salut à Toi XMPP client # Copyright (C) 2016-2019 Jérôme Poisson (goffi@goffi.org) # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. from sat.core import log as logging log = logging.getLogger(__name__) from sat.core.i18n import _ from sat_frontends.quick_frontend import quick_widgets from cagou.core import cagou_widget from cagou.core.constants import Const as C from cagou.core.menu import TouchMenuBehaviour from cagou.core.utils import FilterBehavior from cagou.core.common_widgets import (Identities, ItemWidget, DeviceWidget, CategorySeparator) from sat.tools.common import template_xmlui from cagou.core import xmlui from sat_frontends.tools import jid from kivy import properties from kivy.uix.label import Label from kivy.uix.boxlayout import BoxLayout from kivy.core.window import Window from cagou import G from functools import partial PLUGIN_INFO = { "name": _(u"remote control"), "main": "RemoteControl", "description": _(u"universal remote control"), "icon_symbol": u"signal", } NOTE_TITLE = _(u"Media Player Remote Control") class RemoteItemWidget(ItemWidget): def __init__(self, device_jid, node, name, main_wid, **kw): self.device_jid = device_jid self.node = node super(RemoteItemWidget, self).__init__(name=name, main_wid=main_wid, **kw) def do_item_action(self, touch): self.main_wid.layout.clear_widgets() player_wid = MediaPlayerControlWidget(main_wid=self.main_wid, remote_item=self) self.main_wid.layout.add_widget(player_wid) class MediaPlayerControlWidget(BoxLayout): main_wid = properties.ObjectProperty() remote_item = properties.ObjectProperty() status = properties.OptionProperty(u"play", options=(u"play", u"pause", u"stop")) title = properties.StringProperty() identity = properties.StringProperty() command = properties.DictProperty() ui_tpl = properties.ObjectProperty() @property def profile(self): return self.main_wid.profile def updateUI(self, action_data): xmlui_raw = action_data['xmlui'] ui_tpl = template_xmlui.create(G.host, xmlui_raw) self.ui_tpl = ui_tpl for prop in ('Title', 'Identity'): try: setattr(self, prop.lower(), ui_tpl.widgets[prop].value) except KeyError: log.warning(_(u"Missing field: {name}").format(name=prop)) playback_status = self.ui_tpl.widgets['PlaybackStatus'].value if playback_status == u"Playing": self.status = u"pause" elif playback_status == u"Paused": self.status = u"play" elif playback_status == u"Stopped": self.status = u"play" else: G.host.addNote( title=NOTE_TITLE, message=_(u"Unknown playback status: playback_status") .format(playback_status=playback_status), level=C.XMLUI_DATA_LVL_WARNING) self.commands = {v:k for k,v in ui_tpl.widgets['command'].options} def adHocRunCb(self, xmlui_raw): ui_tpl = template_xmlui.create(G.host, xmlui_raw) data = {xmlui.XMLUIPanel.escape(u"media_player"): self.remote_item.node, u"session_id": ui_tpl.session_id} G.host.bridge.launchAction( ui_tpl.submit_id, data, self.profile, callback=self.updateUI, errback=self.main_wid.errback) def on_remote_item(self, __, remote): NS_MEDIA_PLAYER = G.host.ns_map[u"mediaplayer"] G.host.bridge.adHocRun(remote.device_jid, NS_MEDIA_PLAYER, self.profile, callback=self.adHocRunCb, errback=self.main_wid.errback) def do_cmd(self, command): try: cmd_value = self.commands[command] except KeyError: G.host.addNote( title=NOTE_TITLE, message=_(u"{command} command is not managed").format(command=command), level=C.XMLUI_DATA_LVL_WARNING) else: data = {xmlui.XMLUIPanel.escape(u"command"): cmd_value, u"session_id": self.ui_tpl.session_id} # hidden values are normally transparently managed by XMLUIPanel # but here we have to add them by hand hidden = {xmlui.XMLUIPanel.escape(k):v for k,v in self.ui_tpl.hidden.iteritems()} data.update(hidden) G.host.bridge.launchAction( self.ui_tpl.submit_id, data, self.profile, callback=self.updateUI, errback=self.main_wid.errback) class RemoteDeviceWidget(DeviceWidget): def xmluiCb(self, data, cb_id, profile): if u'xmlui' in data: xml_ui = xmlui.create( G.host, data[u'xmlui'], callback=self.xmluiCb, profile=profile) if isinstance(xml_ui, xmlui.XMLUIDialog): self.main_wid.showRootWidget() xml_ui.show() else: xml_ui.size_hint_y = None self.main_wid.layout.clear_widgets() self.main_wid.layout.add_widget(xml_ui) else: if data: log.warning(_(u"Unhandled data: {data}").format(data=data)) self.main_wid.showRootWidget() def adHocRunCb(self, data): xml_ui = xmlui.create(G.host, data, callback=self.xmluiCb, profile=self.profile) xml_ui.size_hint_y = None self.main_wid.layout.add_widget(xml_ui) def do_item_action(self, touch): self.main_wid.layout.clear_widgets() G.host.bridge.adHocRun(self.entity_jid, u'', self.profile, callback=self.adHocRunCb, errback=self.main_wid.errback) class RemoteControl(quick_widgets.QuickWidget, cagou_widget.CagouWidget, FilterBehavior, TouchMenuBehaviour): SINGLE=False layout = properties.ObjectProperty() def __init__(self, host, target, profiles): quick_widgets.QuickWidget.__init__(self, host, target, profiles) cagou_widget.CagouWidget.__init__(self) FilterBehavior.__init__(self) TouchMenuBehaviour.__init__(self) Window.bind(on_keyboard=self.key_input) self.showRootWidget() def errback(self, failure_): """Generic errback which add a warning note and go back to root widget""" G.host.addNote( title=NOTE_TITLE, message=_(u"Can't use remote control: {reason}").format(reason=failure_), level=C.XMLUI_DATA_LVL_WARNING) self.showRootWidget() def key_input(self, window, key, scancode, codepoint, modifier): if key == 27: self.showRootWidget() return True def showRootWidget(self): self.layout.clear_widgets() found = [] self.get_remotes(found) self.discover_devices(found) def adHocRemotesGetCb(self, remotes_data, found): found.insert(0, remotes_data) if len(found) == 2: self.show_devices(found) def adHocRemotesGetEb(self, failure_, found): G.host.errback(failure_, title=_(u"discovery error"), message=_(u"can't check remote controllers: {msg}")) found.insert(0, []) if len(found) == 2: self.show_devices(found) def get_remotes(self, found): self.host.bridge.adHocRemotesGet( self.profile, callback=partial(self.adHocRemotesGetCb, found=found), errback=partial(self.adHocRemotesGetEb,found=found)) def _discoFindByFeaturesCb(self, data, found): found.append(data) if len(found) == 2: self.show_devices(found) def _discoFindByFeaturesEb(self, failure_, found): G.host.errback(failure_, title=_(u"discovery error"), message=_(u"can't check devices: {msg}")) found.append(({}, {}, {})) if len(found) == 2: self.show_devices(found) def discover_devices(self, found): """Looks for devices handling file "File Information Sharing" and display them""" try: namespace = self.host.ns_map['commands'] except KeyError: msg = _(u"can't find ad-hoc commands namespace, is the plugin running?") log.warning(msg) G.host.addNote(_(u"missing plugin"), msg, C.XMLUI_DATA_LVL_ERROR) return self.host.bridge.discoFindByFeatures( [namespace], [], False, True, True, True, False, self.profile, callback=partial(self._discoFindByFeaturesCb, found=found), errback=partial(self._discoFindByFeaturesEb, found=found)) def show_devices(self, found): remotes_data, (entities_services, entities_own, entities_roster) = found if remotes_data: title = _(u"media players remote controls") self.layout.add_widget(CategorySeparator(text=title)) for remote_data in remotes_data: device_jid, node, name = remote_data wid = RemoteItemWidget(device_jid, node, name, self) self.layout.add_widget(wid) for entities_map, title in ((entities_services, _(u'services')), (entities_own, _(u'your devices')), (entities_roster, _(u'your contacts devices'))): if entities_map: self.layout.add_widget(CategorySeparator(text=title)) for entity_str, entity_ids in entities_map.iteritems(): entity_jid = jid.JID(entity_str) item = RemoteDeviceWidget( self, entity_jid, Identities(entity_ids)) self.layout.add_widget(item) if (not remotes_data and not entities_services and not entities_own and not entities_roster): self.layout.add_widget(Label( size_hint=(1, 1), halign='center', text_size=self.size, text=_(u"No sharing device found")))