- Added birdy
- Decode dbus byte data into images for notifications
This commit is contained in:
parent
08faa46354
commit
822865e909
5 changed files with 65637 additions and 33 deletions
65574
discover_overlay/craig_birdy.py
Normal file
65574
discover_overlay/craig_birdy.py
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -420,15 +420,6 @@ class DiscordConnector:
|
|||
"""
|
||||
Called when connection is finalised
|
||||
"""
|
||||
for guild in self.guilds.values():
|
||||
channels = ""
|
||||
if "channels" in guild:
|
||||
for channel in guild["channels"]:
|
||||
channels = channels + " " + channel["name"]
|
||||
else:
|
||||
channels = "Opted out"
|
||||
logging.info(
|
||||
u"%s: %s", guild["name"], channels)
|
||||
self.voice_settings.set_guild_list(self.guilds)
|
||||
self.sub_server()
|
||||
self.find_user()
|
||||
|
|
|
|||
|
|
@ -124,6 +124,12 @@ class Discover:
|
|||
logging.warning(args)
|
||||
noti = {"title": "%s" % (args[3]), "body": "%s" % (args[4]),
|
||||
"icon": "%s" % (args[2]), "cmd": "%s" % (args[0]), "time": time.time()}
|
||||
if len(args) > 6:
|
||||
dictionary = args[6]
|
||||
if 'image-data' in dictionary:
|
||||
noti['icon_raw'] = dictionary['image-data']
|
||||
elif 'image_data' in dictionary:
|
||||
noti['icon_raw'] = dictionary['image_data']
|
||||
self.notification_messages.append(noti)
|
||||
self.notification_overlay.set_content(self.notification_messages, True)
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import cairo
|
|||
import PIL
|
||||
import PIL.Image as Image
|
||||
import os
|
||||
import io
|
||||
gi.require_version('GdkPixbuf', '2.0')
|
||||
# pylint: disable=wrong-import-position
|
||||
from gi.repository import Gio, GdkPixbuf # nopep8
|
||||
|
|
@ -78,7 +79,7 @@ class SurfaceGetter():
|
|||
)
|
||||
raw = resp.raw
|
||||
image = Image.open(raw)
|
||||
surface = self.from_pil(image)
|
||||
surface = from_pil(image)
|
||||
|
||||
self.func(self.identifier, surface)
|
||||
except requests.HTTPError:
|
||||
|
|
@ -111,23 +112,24 @@ class SurfaceGetter():
|
|||
logging.error("Unknown image type: %s", mixpath)
|
||||
except FileNotFoundError:
|
||||
logging.error("File not found: %s", mixpath)
|
||||
surface = self.from_pil(image)
|
||||
surface = from_pil(image)
|
||||
if surface:
|
||||
self.func(self.identifier, surface)
|
||||
return
|
||||
|
||||
def from_pil(self, image, alpha=1.0):
|
||||
"""
|
||||
:param im: Pillow Image
|
||||
:param alpha: 0..1 alpha to add to non-alpha images
|
||||
:param format: Pixel format for output surface
|
||||
"""
|
||||
if 'A' not in image.getbands():
|
||||
image.putalpha(int(alpha * 256.))
|
||||
arr = bytearray(image.tobytes('raw', 'BGRa'))
|
||||
surface = cairo.ImageSurface.create_for_data(
|
||||
arr, cairo.FORMAT_ARGB32, image.width, image.height)
|
||||
return surface
|
||||
|
||||
def from_pil(image, alpha=1.0):
|
||||
"""
|
||||
:param im: Pillow Image
|
||||
:param alpha: 0..1 alpha to add to non-alpha images
|
||||
:param format: Pixel format for output surface
|
||||
"""
|
||||
if 'A' not in image.getbands():
|
||||
image.putalpha(int(alpha * 256.))
|
||||
arr = bytearray(image.tobytes('raw', 'BGRa'))
|
||||
surface = cairo.ImageSurface.create_for_data(
|
||||
arr, cairo.FORMAT_ARGB32, image.width, image.height)
|
||||
return surface
|
||||
|
||||
|
||||
def get_image(func, identifier, ava, size):
|
||||
|
|
@ -148,6 +150,25 @@ def get_surface(func, identifier, ava, size):
|
|||
thread.start()
|
||||
|
||||
|
||||
def make_surface_from_raw(raw, size):
|
||||
"""Create surface from raw notification data"""
|
||||
width = raw[0]
|
||||
height = raw[1]
|
||||
rowstride = raw[2]
|
||||
hasalpha = raw[3]
|
||||
bitspersample = raw[4]
|
||||
channels = raw[5]
|
||||
image_raw_dbus = raw[6]
|
||||
image_raw = bytes(image_raw_dbus)
|
||||
image = None
|
||||
if hasalpha:
|
||||
image = Image.frombytes('RGBA', [width, height], image_raw, 'raw')
|
||||
else:
|
||||
image = Image.frombytes('RGB', [width, height], image_raw, 'raw')
|
||||
surface = from_pil(image)
|
||||
return surface
|
||||
|
||||
|
||||
def get_aspected_size(img, width, height, anchor=0, hanchor=0):
|
||||
"""Get dimensions of image keeping current aspect ratio"""
|
||||
pic_width = img.get_width()
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@ import time
|
|||
import re
|
||||
import cairo
|
||||
import gi
|
||||
from .image_getter import get_surface, draw_img_to_rect, get_aspected_size
|
||||
from .image_getter import get_surface, draw_img_to_rect, get_aspected_size, make_surface_from_raw
|
||||
from .overlay import OverlayWindow
|
||||
from .craig_birdy import birdy
|
||||
gi.require_version("Gtk", "3.0")
|
||||
gi.require_version('PangoCairo', '1.0')
|
||||
# pylint: disable=wrong-import-position,wrong-import-order
|
||||
|
|
@ -34,7 +35,8 @@ class NotificationOverlayWindow(OverlayWindow):
|
|||
self.test_content = [{"icon": "next", "title": "Title1"},
|
||||
{"title": "Title2", "body": "Body", "icon": None},
|
||||
{"icon": "discord", "title": "Title 3", "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."},
|
||||
{"icon": None, "title": "Title 3", "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."}]
|
||||
{"icon": None, "title": "Title 3", "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."},
|
||||
{"icon": None, "title": "PM", "body": "Birdy test", "icon_raw": birdy}]
|
||||
self.text_font = None
|
||||
self.text_size = 13
|
||||
self.text_time = None
|
||||
|
|
@ -122,6 +124,11 @@ class NotificationOverlayWindow(OverlayWindow):
|
|||
the_list = self.test_content
|
||||
for line in the_list:
|
||||
icon = line["icon"]
|
||||
if "icon_raw" in line:
|
||||
if "icon_surface" not in line:
|
||||
line["icon_surface"] = make_surface_from_raw(
|
||||
line["icon_raw"], self.icon_size)
|
||||
|
||||
if icon and icon not in self.image_list:
|
||||
icon_theme = Gtk.IconTheme.get_default()
|
||||
icon_info = icon_theme.lookup_icon(
|
||||
|
|
@ -277,7 +284,15 @@ class NotificationOverlayWindow(OverlayWindow):
|
|||
m_with_body = "<span foreground='%s'>%s</span>"
|
||||
message = m_with_body % (self.sanitize_string(col),
|
||||
self.sanitize_string(line["title"]))
|
||||
current_y = self.draw_text(current_y, message, line["icon"])
|
||||
|
||||
# If we've got an embedded image
|
||||
if "icon_surface" in line and line["icon_surface"]:
|
||||
icon = line["icon_surface"]
|
||||
# If we're given an icon name, it's in the list of icons, and it's not none
|
||||
elif line["icon"] and line["icon"] in self.image_list and self.image_list[line["icon"]]:
|
||||
icon = self.image_list[line["icon"]]
|
||||
|
||||
current_y = self.draw_text(current_y, message, icon)
|
||||
if current_y <= 0:
|
||||
# We've done enough
|
||||
break
|
||||
|
|
@ -289,14 +304,11 @@ class NotificationOverlayWindow(OverlayWindow):
|
|||
Draw a text message, returning the Y position of the next message
|
||||
"""
|
||||
|
||||
icon_width = 0
|
||||
icon_pad = 0
|
||||
if self.show_icon and icon and icon in self.image_list and self.image_list[icon]:
|
||||
icon = self.image_list[icon]
|
||||
icon_width = self.icon_size
|
||||
icon_pad = self.icon_pad
|
||||
else:
|
||||
icon_width = self.icon_size
|
||||
icon_pad = self.icon_pad
|
||||
if not self.show_icon:
|
||||
icon = None
|
||||
icon_pad = 0
|
||||
|
||||
layout = self.create_pango_layout(text)
|
||||
layout.set_auto_dir(True)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue