From 71c35eb279b2271b89896dcff551ba762f66b3a5 Mon Sep 17 00:00:00 2001 From: mathieui Date: Mon, 11 Mar 2013 02:04:20 +0100 Subject: Implement XEP-0118 (Fix #1840) - Add new theming options - Show the tune in the roster (both in contact line and infowin) - add an option to show tunes as info messages --- src/common.py | 37 +++++++++++++++++++++++++++++++++++++ src/connection.py | 1 + src/contact.py | 1 + src/core.py | 24 ++++++++++++++++++++++++ src/tabs.py | 6 ++++-- src/theming.py | 3 +++ src/windows.py | 25 ++++++++++++++++++++----- 7 files changed, 90 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/common.py b/src/common.py index 1a3027e7..5b62732c 100644 --- a/src/common.py +++ b/src/common.py @@ -278,6 +278,43 @@ def parse_secs_to_str(duration=0): result = '0s' return result +def format_tune_string(infos): + """ + Contruct a string from a dict created from an "User tune" event. + + :param dict infos: The informations + :return: The formatted string + :rtype: :py:class:`str` + """ + elems = [] + track = infos.get('track') + if track: + elems.append(track) + title = infos.get('title') + if title: + elems.append(title) + else: + elems.append('Unknown title') + elems.append('-') + artist = infos.get('artist') + if artist: + elems.append(artist) + else: + elems.append('Unknown artist') + + rating = infos.get('rating') + if rating: + elems.append('[ ' + rating + '/10' + ' ]') + length = infos.get('length') + if length: + length = int(length) + secs = length % 60 + mins = length // 60 + secs = str(secs).zfill(2) + mins = str(mins).zfill(2) + elems.append('[' + mins + ':' + secs + ']') + return ' '.join(elems) + def safeJID(*args, **kwargs): """ Construct a :py:class:`sleekxmpp.JID` object from a string. diff --git a/src/connection.py b/src/connection.py index 8073d198..5b5ecba2 100644 --- a/src/connection.py +++ b/src/connection.py @@ -70,6 +70,7 @@ class Connection(sleekxmpp.ClientXMPP): self.register_plugin('xep_0071') self.register_plugin('xep_0085') self.register_plugin('xep_0115') + self.register_plugin('xep_0118') self.register_plugin('xep_0191') if config.get('send_poezio_info', 'true') == 'true': info = {'name':'poezio', diff --git a/src/contact.py b/src/contact.py index 4c570a54..27a0c701 100644 --- a/src/contact.py +++ b/src/contact.py @@ -66,6 +66,7 @@ class Contact(object): self.__item = item self.folded_states = defaultdict(lambda: True) self.error = None + self.tune = {} @property def groups(self): diff --git a/src/core.py b/src/core.py index a37788e7..8a5408d2 100644 --- a/src/core.py +++ b/src/core.py @@ -230,6 +230,7 @@ class Core(object): self.key_func.update(key_func) # Add handlers + self.xmpp.add_event_handler("user_tune_publish", self.on_tune_event) self.xmpp.add_event_handler('connected', self.on_connected) self.xmpp.add_event_handler('disconnected', self.on_disconnected) self.xmpp.add_event_handler('no_auth', self.on_failed_auth) @@ -2598,6 +2599,29 @@ class Core(object): else: self.refresh_window() + def on_tune_event(self, message): + contact = roster[message['from'].bare] + if not contact: + return + item = message['pubsub_event']['items']['item'] + if item.find('{http://jabber.org/protocol/tune}tune'): + item = item['tune'] + contact.tune = { + 'artist': item['artist'], + 'length': item['length'], + 'rating': item['rating'], + 'source': item['source'], + 'title': item['title'], + 'track': item['track'], + 'uri': item['uri'] + } + else: + contact.tune = {} + if config.get('display_tune_notifications', 'false') == 'true' and contact.tune: + self.information( + 'Tune from '+ message['from'].bare + ': ' + common.format_tune_string(contact.tune), + 'Tune') + def on_groupchat_message(self, message): """ Triggered whenever a message is received from a multi-user chat room. diff --git a/src/tabs.py b/src/tabs.py index 7f879aab..b0ad9569 100644 --- a/src/tabs.py +++ b/src/tabs.py @@ -2845,12 +2845,14 @@ class RosterInfoTab(Tab): if isinstance(selected_row, Contact): cont = selected_row res = selected_row.get_highest_priority_resource() - msg = 'Contact: %s (%s)\n%s connected resource%s\nCurrent status: %s' % ( + msg = 'Contact: %s (%s)\n%s connected resource%s\nCurrent status: %s\nCurrent tune: %s' % ( cont.bare_jid, res.presence if res else 'unavailable', len(cont), '' if len(cont) == 1 else 's', - res.status if res else '',) + res.status if res else '', + common.format_tune_string(cont.tune), + ) elif isinstance(selected_row, Resource): res = selected_row msg = 'Resource: %s (%s)\nCurrent status: %s\nPriority: %s' % ( diff --git a/src/theming.py b/src/theming.py index 3f9df2e2..b95596c2 100644 --- a/src/theming.py +++ b/src/theming.py @@ -200,8 +200,10 @@ class Theme(object): CHAR_COLUMN_ASC = ' ▲' CHAR_COLUMN_DESC =' ▼' CHAR_ROSTER_ERROR = '✖' + CHAR_ROSTER_TUNE = '♪' CHAR_ROSTER_ASKED = '?' + COLOR_ROSTER_TUNE = (6, -1) COLOR_ROSTER_ERROR = (1, -1) COLOR_JOIN_CHAR = (4, -1) COLOR_QUIT_CHAR = (1, -1) @@ -218,6 +220,7 @@ class Theme(object): 'roster': (2, -1), 'help': (10, -1), 'headline': (11, -1, 'b'), + 'tune': (6, -1), 'default': (7, -1), } diff --git a/src/windows.py b/src/windows.py index 6aa458ba..78b3c5e5 100644 --- a/src/windows.py +++ b/src/windows.py @@ -31,6 +31,7 @@ from poopt import cut_text from sleekxmpp import JID from common import safeJID +import common import core import wcwidth @@ -1935,6 +1936,8 @@ class RosterWin(Win): added += len(get_theme().CHAR_ROSTER_ASKED) if config.get('show_s2s_errors', 'true').lower() == 'true' and contact.error: added += len(get_theme().CHAR_ROSTER_ERROR) + if contact.tune: + added += len(get_theme().CHAR_ROSTER_TUNE) if config.getl('show_roster_jids', 'true') == 'false' and contact.name: display_name = '%s' % contact.name @@ -1953,6 +1956,8 @@ class RosterWin(Win): self.addstr(get_theme().CHAR_ROSTER_ASKED, to_curses_attr(get_theme().COLOR_IMPORTANT_TEXT)) if config.get('show_s2s_errors', 'true').lower() == 'true' and contact.error: self.addstr(get_theme().CHAR_ROSTER_ERROR, to_curses_attr(get_theme().COLOR_ROSTER_ERROR)) + if contact.tune: + self.addstr(get_theme().CHAR_ROSTER_TUNE, to_curses_attr(get_theme().COLOR_ROSTER_TUNE)) self.finish_line() @@ -1995,23 +2000,33 @@ class ContactInfoWin(Win): presence = resource.presence else: presence = 'unavailable' + i = 0 self.addstr(0, 0, '%s (%s)'%(jid, presence,), to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) self.finish_line(get_theme().COLOR_INFORMATION_BAR) - self.addstr(1, 0, 'Subscription: %s' % (contact.subscription,)) + i += 1 + self.addstr(i, 0, 'Subscription: %s' % (contact.subscription,)) self.finish_line() + i += 1 if contact.ask: if contact.ask == 'asked': - self.addstr('Ask: %s' % (contact.ask,), to_curses_attr(get_theme().COLOR_IMPORTANT_TEXT)) + self.addstr(i, 0, 'Ask: %s' % (contact.ask,), to_curses_attr(get_theme().COLOR_IMPORTANT_TEXT)) else: - self.addstr('Ask: %s' % (contact.ask,)) + self.addstr(i, 0, 'Ask: %s' % (contact.ask,)) self.finish_line() + i += 1 if resource: - self.addstr(2, 0, 'Status: %s' % (resource.status)) + self.addstr(i, 0, 'Status: %s' % (resource.status)) self.finish_line() + i += 1 if contact.error: - self.addstr('Error: %s' % contact.error, to_curses_attr(get_theme().COLOR_ROSTER_ERROR)) + self.addstr(i, 0, 'Error: %s' % contact.error, to_curses_attr(get_theme().COLOR_ROSTER_ERROR)) + self.finish_line() + i += 1 + if contact.tune: + self.addstr(i, 0, 'Current Tune: %s' % common.format_tune_string(contact.tune), to_curses_attr(get_theme().COLOR_NORMAL_TEXT)) + i += 1 def draw_group_info(self, group): """ -- cgit v1.2.3