summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/default_config.cfg3
-rw-r--r--doc/en/configure.txt5
-rw-r--r--src/common.py37
-rw-r--r--src/connection.py1
-rw-r--r--src/contact.py1
-rw-r--r--src/core.py24
-rw-r--r--src/tabs.py6
-rw-r--r--src/theming.py3
-rw-r--r--src/windows.py25
9 files changed, 98 insertions, 7 deletions
diff --git a/data/default_config.cfg b/data/default_config.cfg
index abafe4ae..48871906 100644
--- a/data/default_config.cfg
+++ b/data/default_config.cfg
@@ -340,6 +340,9 @@ user_list_sort = desc
# be displayed using their nick color if true.
display_user_color_in_join_part = false
+# Display user tune notifications as information messages or not
+display_tune_notifications = false
+
# if true, chat states will be sent to the people you are talking to.
# Chat states are, for example, messages informing that you are composing
# a message or that you closed the tab, etc
diff --git a/doc/en/configure.txt b/doc/en/configure.txt
index 6eff81a5..1bf43af7 100644
--- a/doc/en/configure.txt
+++ b/doc/en/configure.txt
@@ -113,6 +113,11 @@ section of this documentation.
the nick you will use when joining a room with no associated nick
If this is empty, the $USER environnement variable will be used
+*display_tune_notifications*:: false
+
+ If set to true, notifications about the music your contacts listen to
+ will be displayed in the info buffer as 'Tune' messages.
+
*display_user_color_in_join_part*:: false
If set to true, the color of the nick will be used in MUCs information
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):
"""