From e2a2758f6d4771868df341a7bbd0ba0e751911c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Cort=C3=A9z?= Date: Sun, 25 Sep 2016 14:24:40 -0500 Subject: [PATCH] Added support for playing voice messages in VK --- src/controller/buffers.py | 69 +++++++++++++++++++++++++++++++++++++++ src/controller/player.py | 12 ++++--- src/controller/posts.py | 9 +++-- src/wxUI/tabs/home.py | 19 +++++++++++ 4 files changed, 103 insertions(+), 6 deletions(-) diff --git a/src/controller/buffers.py b/src/controller/buffers.py index fb6a45e..6d11578 100644 --- a/src/controller/buffers.py +++ b/src/controller/buffers.py @@ -11,6 +11,7 @@ import output import logging import selector import webbrowser +import posts from wxUI.tabs import home from pubsub import pub from sessionmanager import session @@ -575,9 +576,18 @@ class chatBuffer(baseBuffer): if msg.has_key("read_state") and msg["read_state"] == 0 and msg["id"] not in self.reads: self.reads.append(msg["id"]) self.session.db[self.name]["items"][-1]["read_state"] = 1 + msg = self.get_post() + if msg.has_key("attachments") and len(msg["attachments"]) > 0: + self.tab.attachments.list.Enable(True) + self.attachments = list() + self.parse_attachments(msg) + else: + self.tab.attachments.list.Enable(False) + self.tab.attachments.clear() def create_tab(self, parent): self.tab = home.chatTab(parent) + self.attachments = list() def connect_events(self): widgetUtils.connect_event(self.tab.send, widgetUtils.BUTTON_PRESSED, self.send_chat_to_user) @@ -623,6 +633,65 @@ class chatBuffer(baseBuffer): super(chatBuffer, self).__init__(*args, **kwargs) self.reads = [] + def parse_attachments(self, post): + attachments = [] + from posts import add_attachment + if post.has_key("attachments"): + for i in post["attachments"]: + # We don't need the photos_list attachment, so skip it. + if i["type"] == "photos_list": + continue + attachments.append(add_attachment(i)) + self.attachments.append(i) + self.tab.attachments.list.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.open_attachment) + self.tab.insert_attachments(attachments) + + def open_attachment(self, *args, **kwargs): + index = self.tab.attachments.get_selected() + attachment = self.attachments[index] + if attachment["type"] == "audio": + a = posts.audio(session=self.session, postObject=[attachment["audio"]]) + a.dialog.get_response() + a.dialog.Destroy() + if attachment["type"] == "link": + output.speak(_(u"Opening URL..."), True) + webbrowser.open_new_tab(attachment["link"]["url"]) + elif attachment["type"] == "doc": + if attachment["doc"].has_key("preview") and attachment["doc"]["preview"].has_key("audio_msg"): + link = attachment["doc"]["preview"]["audio_msg"]["link_mp3"] + output.speak(_(u"Playing...")) + player.player.play(url=dict(url=link), set_info=False) + else: + output.speak(_(u"Opening document in web browser...")) + webbrowser.open(attachment["doc"]["url"]) + elif attachment["type"] == "video": + # it seems VK doesn't like to attach video links as normal URLS, so we'll have to + # get the full video object and use its "player" key which will open a webbrowser in their site with a player for the video. + # see https://vk.com/dev/attachments_w and and https://vk.com/dev/video.get + # However, the flash player isn't good for visually impaired people (when you press play you won't be able to close the window with alt+f4), so it could be good to use the HTML5 player. + # For firefox, see https://addons.mozilla.org/ru/firefox/addon/force-html5-video-player-at-vk/ + # May be I could use a dialogue here for inviting people to use this addon in firefox. It seems it isn't possible to use this html5 player from the player URL. + object_id = "{0}_{1}".format(attachment["video"]["owner_id"], attachment["video"]["id"]) + video_object = self.session.vk.client.video.get(owner_id=attachment["video"]["owner_id"], videos=object_id) + video_object = video_object["items"][0] + output.speak(_(u"Opening video in web browser..."), True) + webbrowser.open_new_tab(video_object["player"]) + elif attachment["type"] == "photo": + output.speak(_(u"Opening photo in web browser..."), True) + # Possible photo sizes for looking in the attachment information. Try to use the biggest photo available. + possible_sizes = [1280, 604, 130, 75] + url = "" + for i in possible_sizes: + if attachment["photo"].has_key("photo_{0}".format(i,)): + url = attachment["photo"]["photo_{0}".format(i,)] + break + if url != "": + webbrowser.open_new_tab(url) + else: + print attachment["photo"].keys() + else: + log.debug("Unhandled attachment: %r" % (attachment,)) + class peopleBuffer(feedBuffer): def create_tab(self, parent): diff --git a/src/controller/player.py b/src/controller/player.py index 6c8f5aa..a128ace 100644 --- a/src/controller/player.py +++ b/src/controller/player.py @@ -1,12 +1,15 @@ # -*- coding: utf-8 -*- import output import sound_lib +import logging + from sound_lib.stream import URLStream from sound_lib.main import BassError from mysc.repeating_timer import RepeatingTimer from pubsub import pub player = None +log = logging.getLogger("player") def setup(): global player @@ -23,7 +26,7 @@ class audioPlayer(object): self.queue = [] self.stopped = True - def play(self, url): + def play(self, url, set_info=True): if self.stream != None and self.stream.is_playing == True: try: self.stream.stop() @@ -41,11 +44,12 @@ class audioPlayer(object): try: self.stream = URLStream(url=url["url"]) except BassError: - log.debug("Error when playing the file %s") % (url,) + log.debug("Error when playing the file %r") % (url,) return # Translators: {0} will be replaced with a song's title and {1} with the artist. - msg = _(u"Playing {0} by {1}").format(url["title"], url["artist"]) - pub.sendMessage("update-status-bar", status=msg) + if set_info: + msg = _(u"Playing {0} by {1}").format(url["title"], url["artist"]) + pub.sendMessage("update-status-bar", status=msg) self.stream.volume = self.vol/100.0 self.stream.play() self.stopped = False diff --git a/src/controller/posts.py b/src/controller/posts.py index 24f1427..1d95768 100644 --- a/src/controller/posts.py +++ b/src/controller/posts.py @@ -14,6 +14,7 @@ import webbrowser import utils import logging from sessionmanager import session # We'll use some functions from there +from sessionmanager.session import utils from pubsub import pub from wxUI.dialogs import postDialogs, urlList from extra import SpellChecker, translator @@ -48,8 +49,12 @@ def add_attachment(attachment): msg = u"{0}".format(" ".join(session.compose_audio(attachment["audio"]))) tpe = _(u"Audio") elif attachment["type"] == "doc": - msg = u"{0}".format(attachment["doc"]["title"]) - tpe = _(u"{0} file").format(attachment["doc"]["ext"]) + if attachment["doc"].has_key("preview") and attachment["doc"]["preview"].has_key("audio_msg"): + tpe = _(u"Voice message") + msg = utils.seconds_to_string(attachment["doc"]["preview"]["audio_msg"]["duration"]) + else: + msg = u"{0}".format(attachment["doc"]["title"]) + tpe = _(u"{0} file").format(attachment["doc"]["ext"]) return [tpe, msg] def get_message(status): diff --git a/src/wxUI/tabs/home.py b/src/wxUI/tabs/home.py index 3a81f79..6821812 100644 --- a/src/wxUI/tabs/home.py +++ b/src/wxUI/tabs/home.py @@ -133,10 +133,16 @@ class empty(wx.Panel): class chatTab(wx.Panel): + def insert_attachments(self, attachments): + for i in attachments: + self.attachments.insert_item(False, *i) + def __init__(self, parent): super(chatTab, self).__init__(parent=parent) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.create_controls()) + sizer.Add(self.create_attachments(), 0, wx.ALL, 5) + sizer.Add(self.create_chat(), 0, wx.ALL, 5) self.send = wx.Button(self, -1, _(u"Send")) self.send.SetDefault() sizer.Add(self.send, 0, wx.ALL, 5) @@ -150,8 +156,21 @@ class chatTab(wx.Panel): box = wx.BoxSizer(wx.HORIZONTAL) box.Add(lbl1, 0, wx.ALL, 5) box.Add(self.list.list, 0, wx.ALL, 5) + return box + + def create_attachments(self): + lbl = wx.StaticText(self, -1, _(u"Attachments")) + self.attachments = widgetUtils.list(self, _(u"Type"), _(u"Title"), style=wx.LC_REPORT) + box = wx.BoxSizer(wx.HORIZONTAL) + box.Add(lbl, 0, wx.ALL, 5) + box.Add(self.attachments.list, 0, wx.ALL, 5) + self.attachments.list.Enable(False) + return box + + def create_chat(self): lbl2 = wx.StaticText(self, -1, _(u"Write a message")) self.text = wx.TextCtrl(self, -1) + box = wx.BoxSizer(wx.HORIZONTAL) box.Add(lbl2, 0, wx.ALL, 20) box.Add(self.text, 0, wx.ALL, 5) return box