Commit d37b95e4 authored by Philipp Hörist's avatar Philipp Hörist

Refactor UserTune

- Simplify modules because nbxmpp handles more stuff
parent 18c422d8
...@@ -61,6 +61,7 @@ from gajim.gtk.util import get_cursor ...@@ -61,6 +61,7 @@ from gajim.gtk.util import get_cursor
from gajim.gtk.util import ensure_proper_control from gajim.gtk.util import ensure_proper_control
from gajim.gtk.util import format_mood from gajim.gtk.util import format_mood
from gajim.gtk.util import format_activity from gajim.gtk.util import format_activity
from gajim.gtk.util import format_tune
from gajim.gtk.util import get_activity_icon_name from gajim.gtk.util import get_activity_icon_name
from gajim.command_system.implementation.hosts import ChatCommands from gajim.command_system.implementation.hosts import ChatCommands
...@@ -133,7 +134,6 @@ class ChatControl(ChatControlBase): ...@@ -133,7 +134,6 @@ class ChatControl(ChatControlBase):
self.update_toolbar() self.update_toolbar()
self._pep_images = {} self._pep_images = {}
self._pep_images['tune'] = self.xml.get_object('tune_image')
self._pep_images['geoloc'] = self.xml.get_object('location_image') self._pep_images['geoloc'] = self.xml.get_object('location_image')
self.update_all_pep_types() self.update_all_pep_types()
...@@ -236,6 +236,8 @@ class ChatControl(ChatControlBase): ...@@ -236,6 +236,8 @@ class ChatControl(ChatControlBase):
self._on_mood_received) self._on_mood_received)
app.ged.register_event_handler('activity-received', ged.GUI1, app.ged.register_event_handler('activity-received', ged.GUI1,
self._on_activity_received) self._on_activity_received)
app.ged.register_event_handler('tune-received', ged.GUI1,
self._on_tune_received)
if self.TYPE_ID == message_control.TYPE_CHAT: if self.TYPE_ID == message_control.TYPE_CHAT:
# Dont connect this when PrivateChatControl is used # Dont connect this when PrivateChatControl is used
app.ged.register_event_handler('update-roster-avatar', ged.GUI1, app.ged.register_event_handler('update-roster-avatar', ged.GUI1,
...@@ -420,6 +422,7 @@ class ChatControl(ChatControlBase): ...@@ -420,6 +422,7 @@ class ChatControl(ChatControlBase):
self.update_pep(pep_type) self.update_pep(pep_type)
self._update_pep(PEPEventType.MOOD) self._update_pep(PEPEventType.MOOD)
self._update_pep(PEPEventType.ACTIVITY) self._update_pep(PEPEventType.ACTIVITY)
self._update_pep(PEPEventType.TUNE)
def update_pep(self, pep_type): def update_pep(self, pep_type):
if isinstance(self.contact, GC_Contact): if isinstance(self.contact, GC_Contact):
...@@ -460,6 +463,9 @@ class ChatControl(ChatControlBase): ...@@ -460,6 +463,9 @@ class ChatControl(ChatControlBase):
elif type_ == PEPEventType.ACTIVITY: elif type_ == PEPEventType.ACTIVITY:
icon = get_activity_icon_name(data.activity, data.subactivity) icon = get_activity_icon_name(data.activity, data.subactivity)
formated_text = format_activity(*data) formated_text = format_activity(*data)
elif type_ == PEPEventType.TUNE:
icon = 'audio-x-generic'
formated_text = format_tune(*data)
image.set_from_icon_name(icon, Gtk.IconSize.MENU) image.set_from_icon_name(icon, Gtk.IconSize.MENU)
image.set_tooltip_markup(formated_text) image.set_tooltip_markup(formated_text)
...@@ -470,6 +476,8 @@ class ChatControl(ChatControlBase): ...@@ -470,6 +476,8 @@ class ChatControl(ChatControlBase):
return self.xml.get_object('mood_image') return self.xml.get_object('mood_image')
if type_ == PEPEventType.ACTIVITY: if type_ == PEPEventType.ACTIVITY:
return self.xml.get_object('activity_image') return self.xml.get_object('activity_image')
if type_ == PEPEventType.TUNE:
return self.xml.get_object('tune_image')
@ensure_proper_control @ensure_proper_control
def _on_mood_received(self, _event): def _on_mood_received(self, _event):
...@@ -479,6 +487,10 @@ class ChatControl(ChatControlBase): ...@@ -479,6 +487,10 @@ class ChatControl(ChatControlBase):
def _on_activity_received(self, _event): def _on_activity_received(self, _event):
self._update_pep(PEPEventType.ACTIVITY) self._update_pep(PEPEventType.ACTIVITY)
@ensure_proper_control
def _on_tune_received(self, _event):
self._update_pep(PEPEventType.TUNE)
@ensure_proper_control @ensure_proper_control
def _on_nickname_received(self, _event): def _on_nickname_received(self, _event):
self.update_ui() self.update_ui()
...@@ -1101,6 +1113,8 @@ class ChatControl(ChatControlBase): ...@@ -1101,6 +1113,8 @@ class ChatControl(ChatControlBase):
self._on_mood_received) self._on_mood_received)
app.ged.remove_event_handler('activity-received', ged.GUI1, app.ged.remove_event_handler('activity-received', ged.GUI1,
self._on_activity_received) self._on_activity_received)
app.ged.remove_event_handler('tune-received', ged.GUI1,
self._on_tune_received)
if self.TYPE_ID == message_control.TYPE_CHAT: if self.TYPE_ID == message_control.TYPE_CHAT:
app.ged.remove_event_handler('update-roster-avatar', ged.GUI1, app.ged.remove_event_handler('update-roster-avatar', ged.GUI1,
self._nec_update_avatar) self._nec_update_avatar)
......
...@@ -15,90 +15,62 @@ ...@@ -15,90 +15,62 @@
# XEP-0118: User Tune # XEP-0118: User Tune
from typing import Any from typing import Any
from typing import List # pylint: disable=unused-import
from typing import Dict
from typing import Optional
from typing import Tuple from typing import Tuple
import logging import logging
import nbxmpp import nbxmpp
from gi.repository import GLib
from gajim.common.i18n import _ from gajim.common import app
from gajim.common.nec import NetworkEvent
from gajim.common.modules.base import BaseModule
from gajim.common.modules.util import event_node
from gajim.common.modules.util import store_publish
from gajim.common.const import PEPEventType from gajim.common.const import PEPEventType
from gajim.common.exceptions import StanzaMalformed
from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData
from gajim.common.types import UserTuneDataT
log = logging.getLogger('gajim.c.m.user_tune') log = logging.getLogger('gajim.c.m.user_tune')
class UserTuneData(AbstractPEPData): class UserTune(BaseModule):
type_ = PEPEventType.TUNE _nbxmpp_extends = 'Tune'
_nbxmpp_methods = [
def as_markup_text(self) -> str: 'set_tune',
if self.data is None: ]
return ''
def __init__(self, con):
tune = self.data BaseModule.__init__(self, con)
self._register_pubsub_handler(self._tune_received)
artist = tune.get('artist', _('Unknown Artist'))
artist = GLib.markup_escape_text(artist) @event_node(nbxmpp.NS_TUNE)
def _tune_received(self, _con, _stanza, properties):
title = tune.get('title', _('Unknown Title')) data = properties.pubsub_event.data
title = GLib.markup_escape_text(title) empty = properties.pubsub_event.empty
source = tune.get('source', _('Unknown Source')) for contact in app.contacts.get_contacts(self._account,
source = GLib.markup_escape_text(source) str(properties.jid)):
if not empty:
tune_string = _('<b>"%(title)s"</b> by <i>%(artist)s</i>\n' contact.pep[PEPEventType.TUNE] = data
'from <i>%(source)s</i>') % {'title': title, else:
'artist': artist, contact.pep.pop(PEPEventType.TUNE, None)
'source': source}
return tune_string if properties.is_self_message:
if not empty:
self._con.pep[PEPEventType.TUNE] = data
class UserTune(AbstractPEPModule): else:
self._con.pep.pop(PEPEventType.TUNE, None)
name = 'tune'
namespace = nbxmpp.NS_TUNE app.nec.push_incoming_event(
pep_class = UserTuneData NetworkEvent('tune-received',
store_publish = True account=self._account,
_log = log jid=properties.jid.getBare(),
tune=data,
def _extract_info(self, item: nbxmpp.Node) -> Optional[Dict[str, str]]: is_self_message=properties.is_self_message))
tune_dict = {}
tune_tag = item.getTag('tune', namespace=self.namespace) @store_publish
if tune_tag is None: def set_tune(self, tune):
raise StanzaMalformed('No tune node') log.info('Send %s', tune)
self._nbxmpp('Tune').set_tune(tune)
for child in tune_tag.getChildren():
name = child.getName().strip()
data = child.getData().strip()
if child.getName() in ['artist', 'title', 'source',
'track', 'length']:
tune_dict[name] = data
return tune_dict or None
def _build_node(self, data: UserTuneDataT) -> nbxmpp.Node:
item = nbxmpp.Node('tune', {'xmlns': nbxmpp.NS_TUNE})
if data is None:
return item
artist, title, source, track, length = data
if artist:
item.addChild('artist', payload=artist)
if title:
item.addChild('title', payload=title)
if source:
item.addChild('source', payload=source)
if track:
item.addChild('track', payload=track)
if length:
item.addChild('length', payload=length)
return item
def get_instance(*args: Any, **kwargs: Any) -> Tuple[UserTune, str]: def get_instance(*args: Any, **kwargs: Any) -> Tuple[UserTune, str]:
......
...@@ -47,8 +47,6 @@ ConnectionT = Union['Connection', 'ConnectionZeroconf'] ...@@ -47,8 +47,6 @@ ConnectionT = Union['Connection', 'ConnectionZeroconf']
ContactsT = Union['Contact', 'GC_Contact'] ContactsT = Union['Contact', 'GC_Contact']
ContactT = Union['Contact'] ContactT = Union['Contact']
UserTuneDataT = Optional[Tuple[str, str, str, str, str]]
# PEP # PEP
PEPNotifyCallback = Callable[[nbxmpp.JID, nbxmpp.Node], None] PEPNotifyCallback = Callable[[nbxmpp.JID, nbxmpp.Node], None]
PEPHandlersDict = Dict[str, List[PEPNotifyCallback]] PEPHandlersDict = Dict[str, List[PEPNotifyCallback]]
......
...@@ -44,6 +44,7 @@ from gajim.gtk.util import get_builder ...@@ -44,6 +44,7 @@ from gajim.gtk.util import get_builder
from gajim.gtk.util import get_icon_name from gajim.gtk.util import get_icon_name
from gajim.gtk.util import format_mood from gajim.gtk.util import format_mood
from gajim.gtk.util import format_activity from gajim.gtk.util import format_activity
from gajim.gtk.util import format_tune
log = logging.getLogger('gajim.gtk.tooltips') log = logging.getLogger('gajim.gtk.tooltips')
...@@ -487,8 +488,8 @@ class RosterTooltip(StatusTable): ...@@ -487,8 +488,8 @@ class RosterTooltip(StatusTable):
self._ui.activity.show() self._ui.activity.show()
self._ui.activity_label.show() self._ui.activity_label.show()
if 'tune' in contact.pep: if PEPEventType.TUNE in contact.pep:
tune = contact.pep['tune'].as_markup_text() tune = format_tune(*contact.pep[PEPEventType.TUNE])
self._ui.tune.set_markup(tune) self._ui.tune.set_markup(tune)
self._ui.tune.show() self._ui.tune.show()
self._ui.tune_label.show() self._ui.tune_label.show()
......
...@@ -546,3 +546,17 @@ def get_activity_icon_name(activity, subactivity=None): ...@@ -546,3 +546,17 @@ def get_activity_icon_name(activity, subactivity=None):
if subactivity is not None: if subactivity is not None:
icon_name += '-%s' % subactivity.replace('_', '-') icon_name += '-%s' % subactivity.replace('_', '-')
return icon_name return icon_name
def format_tune(artist, length, rating, source, title, track, uri):
if artist is None and title is None and source is None:
return
artist = GLib.markup_escape_text(artist or _('Unknown Artist'))
title = GLib.markup_escape_text(title or _('Unknown Title'))
source = GLib.markup_escape_text(source or _('Unknown Source'))
tune_string = _('<b>"%(title)s"</b> by <i>%(artist)s</i>\n'
'from <i>%(source)s</i>') % {'title': title,
'artist': artist,
'source': source}
return tune_string
...@@ -265,9 +265,6 @@ def create_list_multi(value_list, selected_values=None): ...@@ -265,9 +265,6 @@ def create_list_multi(value_list, selected_values=None):
return treeview return treeview
def get_pep_icon(pep_class): def get_pep_icon(pep_class):
if pep_class == PEPEventType.TUNE:
return 'audio-x-generic'
if pep_class == PEPEventType.LOCATION: if pep_class == PEPEventType.LOCATION:
return 'applications-internet' return 'applications-internet'
......
...@@ -47,6 +47,7 @@ from gi.repository import Gio ...@@ -47,6 +47,7 @@ from gi.repository import Gio
from gi.repository import Gdk from gi.repository import Gdk
from nbxmpp import idlequeue from nbxmpp import idlequeue
from nbxmpp import Hashes2 from nbxmpp import Hashes2
from nbxmpp.structs import TuneData
import OpenSSL import OpenSSL
try: try:
...@@ -1942,8 +1943,8 @@ class Interface: ...@@ -1942,8 +1943,8 @@ class Interface:
continue continue
if app.connections[acct].music_track_info == music_track_info: if app.connections[acct].music_track_info == music_track_info:
continue continue
app.connections[acct].get_module('UserTune').send( app.connections[acct].get_module('UserTune').set_tune(
(artist, title, source, '', '')) TuneData(artist=artist, title=title, source=source))
app.connections[acct].music_track_info = music_track_info app.connections[acct].music_track_info = music_track_info
def read_sleepy(self): def read_sleepy(self):
......
...@@ -1058,9 +1058,8 @@ class RosterWindow: ...@@ -1058,9 +1058,8 @@ class RosterWindow:
else: else:
self.model[child_iter][Column.ACTIVITY_PIXBUF] = None self.model[child_iter][Column.ACTIVITY_PIXBUF] = None
if app.config.get('show_tunes_in_roster') and 'tune' in pep_dict: if app.config.get('show_tunes_in_roster') and PEPEventType.TUNE in pep_dict:
self.model[child_iter][Column.TUNE_ICON] = \ self.model[child_iter][Column.TUNE_ICON] = 'audio-x-generic'
gtkgui_helpers.get_pep_icon(pep_dict['tune'])
else: else:
self.model[child_iter][Column.TUNE_ICON] = None self.model[child_iter][Column.TUNE_ICON] = None
...@@ -1319,7 +1318,7 @@ class RosterWindow: ...@@ -1319,7 +1318,7 @@ class RosterWindow:
if pep_type == PEPEventType.ACTIVITY: if pep_type == PEPEventType.ACTIVITY:
return app.config.get('show_activity_in_roster') return app.config.get('show_activity_in_roster')
if pep_type == 'tune': if pep_type == PEPEventType.TUNE:
return app.config.get('show_tunes_in_roster') return app.config.get('show_tunes_in_roster')
if pep_type == 'geoloc': if pep_type == 'geoloc':
...@@ -1332,6 +1331,7 @@ class RosterWindow: ...@@ -1332,6 +1331,7 @@ class RosterWindow:
self.draw_pep(jid, account, pep_type, contact=contact) self.draw_pep(jid, account, pep_type, contact=contact)
self._draw_pep(account, jid, PEPEventType.MOOD) self._draw_pep(account, jid, PEPEventType.MOOD)
self._draw_pep(account, jid, PEPEventType.ACTIVITY) self._draw_pep(account, jid, PEPEventType.ACTIVITY)
self._draw_pep(account, jid, PEPEventType.TUNE)
def draw_pep(self, jid, account, pep_type, contact=None): def draw_pep(self, jid, account, pep_type, contact=None):
if pep_type not in self._pep_type_to_model_column: if pep_type not in self._pep_type_to_model_column:
...@@ -1373,6 +1373,10 @@ class RosterWindow: ...@@ -1373,6 +1373,10 @@ class RosterWindow:
column = Column.ACTIVITY_PIXBUF column = Column.ACTIVITY_PIXBUF
if data is not None: if data is not None:
icon = get_activity_icon_name(data.activity, data.subactivity) icon = get_activity_icon_name(data.activity, data.subactivity)
elif type_ == PEPEventType.TUNE:
column = Column.TUNE_ICON
if data is not None:
icon = 'audio-x-generic'
for child_iter in iters: for child_iter in iters:
self.model[child_iter][column] = icon self.model[child_iter][column] = icon
...@@ -2636,8 +2640,7 @@ class RosterWindow: ...@@ -2636,8 +2640,7 @@ class RosterWindow:
self.remove_contact(jid, obj.conn.name, backend=True) self.remove_contact(jid, obj.conn.name, backend=True)
def _nec_pep_received(self, obj): def _nec_pep_received(self, obj):
if obj.user_pep.type_ not in (PEPEventType.TUNE, if obj.user_pep.type_ != PEPEventType.LOCATION:
PEPEventType.LOCATION):
return return
if obj.jid == app.get_jid_from_account(obj.conn.name): if obj.jid == app.get_jid_from_account(obj.conn.name):
...@@ -2655,6 +2658,11 @@ class RosterWindow: ...@@ -2655,6 +2658,11 @@ class RosterWindow:
self.draw_account(event.account) self.draw_account(event.account)
self._draw_pep(event.account, event.jid, PEPEventType.ACTIVITY) self._draw_pep(event.account, event.jid, PEPEventType.ACTIVITY)
def _on_tune_received(self, event):
if event.is_self_message:
self.draw_account(event.account)
self._draw_pep(event.account, event.jid, PEPEventType.TUNE)
def _on_nickname_received(self, event): def _on_nickname_received(self, event):
self.draw_contact(event.jid, event.account) self.draw_contact(event.jid, event.account)
...@@ -3595,7 +3603,7 @@ class RosterWindow: ...@@ -3595,7 +3603,7 @@ class RosterWindow:
if active: if active:
app.interface.enable_music_listener() app.interface.enable_music_listener()
else: else:
app.connections[account].get_module('UserTune').send(None) app.connections[account].get_module('UserTune').set_tune(None)
# disable music listener only if no other account uses it # disable music listener only if no other account uses it
for acc in app.connections: for acc in app.connections:
if app.config.get_per('accounts', acc, 'publish_tune'): if app.config.get_per('accounts', acc, 'publish_tune'):
...@@ -5591,9 +5599,8 @@ class RosterWindow: ...@@ -5591,9 +5599,8 @@ class RosterWindow:
# [icon, name, type, jid, account, editable, mood_pixbuf, # [icon, name, type, jid, account, editable, mood_pixbuf,
# activity_pixbuf, TUNE_ICON, LOCATION_ICON, avatar_img, # activity_pixbuf, TUNE_ICON, LOCATION_ICON, avatar_img,
# padlock_pixbuf, visible] # padlock_pixbuf, visible]
self.columns = [str, str, str, str, str, self.columns = [str, str, str, str, str, str, str, str, str,
str, str, str, str, Gtk.Image, str, bool]
Gtk.Image, str, bool]
self.xml = get_builder('roster_window.ui') self.xml = get_builder('roster_window.ui')
self.window = self.xml.get_object('roster_window') self.window = self.xml.get_object('roster_window')
...@@ -5692,8 +5699,7 @@ class RosterWindow: ...@@ -5692,8 +5699,7 @@ class RosterWindow:
# cell_data_func, func_arg) # cell_data_func, func_arg)
self.renderers_list = [] self.renderers_list = []
self.renderers_propertys = {} self.renderers_propertys = {}
self._pep_type_to_model_column = {'tune': Column.TUNE_ICON, self._pep_type_to_model_column = {'geoloc': Column.LOCATION_ICON}
'geoloc': Column.LOCATION_ICON}
renderer_text = Gtk.CellRendererText() renderer_text = Gtk.CellRendererText()
self.renderers_propertys[renderer_text] = ('ellipsize', self.renderers_propertys[renderer_text] = ('ellipsize',
...@@ -5847,6 +5853,8 @@ class RosterWindow: ...@@ -5847,6 +5853,8 @@ class RosterWindow:
self._on_mood_received) self._on_mood_received)
app.ged.register_event_handler('activity-received', ged.GUI1, app.ged.register_event_handler('activity-received', ged.GUI1,
self._on_activity_received) self._on_activity_received)
app.ged.register_event_handler('tune-received', ged.GUI1,
self._on_tune_received)
app.ged.register_event_handler('update-roster-avatar', ged.GUI1, app.ged.register_event_handler('update-roster-avatar', ged.GUI1,
self._nec_update_avatar) self._nec_update_avatar)
app.ged.register_event_handler('update-room-avatar', ged.GUI1, app.ged.register_event_handler('update-room-avatar', ged.GUI1,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment