- Added birdy

- Decode dbus byte data into images for notifications
This commit is contained in:
Trigg 2022-03-30 13:18:06 +00:00
parent 08faa46354
commit 822865e909
5 changed files with 65637 additions and 33 deletions

File diff suppressed because it is too large Load diff

View file

@ -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()

View file

@ -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)

View file

@ -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()

View file

@ -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)