From f09a6c131421925aa1628a1433efcaab9fcb44e6 Mon Sep 17 00:00:00 2001 From: trigg Date: Fri, 2 Oct 2020 14:08:15 +0100 Subject: [PATCH 01/77] - Regex out microtime in timestamps. --- discover_overlay/discord_connector.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/discover_overlay/discord_connector.py b/discover_overlay/discord_connector.py index b54f4c6..20d9131 100644 --- a/discover_overlay/discord_connector.py +++ b/discover_overlay/discord_connector.py @@ -2,6 +2,7 @@ import websocket import select import time import json +import re import requests import logging import calendar @@ -33,6 +34,7 @@ class DiscordConnector: self.last_connection = "" self.text = [] self.authed = False + self.timeregex = re.compile(r"\.\d+") def get_access_token_stage1(self): global oauth_token @@ -85,8 +87,12 @@ class DiscordConnector: self.in_room.remove(userid) def add_text(self, message): + # Remove micro time + time_input = message["timestamp"] + time_input = self.timeregex.sub("", time_input) + print(time_input) utc_time = time.strptime( - message["timestamp"], "%Y-%m-%dT%H:%M:%S.%f%z") + time_input, "%Y-%m-%dT%H:%M:%S%z") t = time.time() epoch_time = calendar.timegm(utc_time) un = message["author"]["username"] From de2b43d163f998fc52b869738324287a9a2f7880 Mon Sep 17 00:00:00 2001 From: mastercooker Date: Fri, 2 Oct 2020 19:13:22 +0100 Subject: [PATCH 02/77] Added option to only display users that are speaking --- discover_overlay/voice_overlay.py | 25 +++++++++++++++++++++---- discover_overlay/voice_settings.py | 16 ++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/discover_overlay/voice_overlay.py b/discover_overlay/voice_overlay.py index dc8e610..7a96972 100644 --- a/discover_overlay/voice_overlay.py +++ b/discover_overlay/voice_overlay.py @@ -12,6 +12,8 @@ import logging class VoiceOverlayWindow(OverlayWindow): + + def __init__(self): OverlayWindow.__init__(self) @@ -32,6 +34,7 @@ class VoiceOverlayWindow(OverlayWindow): self.wind_col = [0.0, 0.0, 0.0, 0.0] self.mute_col = [0.7, 0.0, 0.0, 1.0] self.userlist = [] + self.users_to_draw = [] self.connected = False self.force_location() self.def_avatar = get_image(self.recv_avatar, @@ -81,6 +84,9 @@ class VoiceOverlayWindow(OverlayWindow): self.round_avatar = not i self.redraw() + def set_only_speaking(self, only_speaking): + self.only_speaking = only_speaking + def set_wind_col(self): self.col(self.wind_col) @@ -136,11 +142,22 @@ class VoiceOverlayWindow(OverlayWindow): if not self.connected: return + # Gather which users to draw + if self.only_speaking: + self.users_to_draw = self.userlist[:] + # Remove users that arent speaking + for user in self.userlist: + speaking = "speaking" in user and user["speaking"] + if not speaking: + self.users_to_draw.remove(user) + else: + self.users_to_draw = self.userlist + # Get size of window (w, h) = self.get_size() # Calculate height needed to show overlay - height = (len(self.userlist) * self.avatar_size) + \ - (len(self.userlist) + 1) * self.icon_spacing + height = (len(self.users_to_draw) * self.avatar_size) + \ + (len(self.users_to_draw) + 1) * self.icon_spacing # Choose where to start drawing rh = 0 + self.vert_edge_padding @@ -149,8 +166,8 @@ class VoiceOverlayWindow(OverlayWindow): rh = (h / 2) - (height / 2) elif self.align_vert == 2: rh = h - height - self.vert_edge_padding - # Iterate users in room. - for user in self.userlist: + + for user in self.users_to_draw: self.draw_avatar(context, user, rh) # Shift the relative position down to next location rh += self.avatar_size + self.icon_spacing diff --git a/discover_overlay/voice_settings.py b/discover_overlay/voice_settings.py index 6825fbb..655aaa5 100644 --- a/discover_overlay/voice_settings.py +++ b/discover_overlay/voice_settings.py @@ -55,6 +55,7 @@ class VoiceSettingsWindow(SettingsWindow): self.font = config.get("main", "font", fallback=None) self.square_avatar = config.getboolean( "main", "square_avatar", fallback=False) + self.only_speaking = config.getboolean("main", "only_speaking", fallback=True) self.monitor = config.get("main", "monitor", fallback="None") self.vert_edge_padding = config.getint( "main", "vert_edge_padding", fallback=0) @@ -77,6 +78,7 @@ class VoiceSettingsWindow(SettingsWindow): self.overlay.set_icon_spacing(self.icon_spacing) self.overlay.set_text_padding(self.text_padding) self.overlay.set_square_avatar(self.square_avatar) + self.overlay.set_only_speaking(self.only_speaking) self.overlay.set_monitor(self.get_monitor_index(self.monitor)) self.overlay.set_vert_edge_padding(self.vert_edge_padding) self.overlay.set_horz_edge_padding(self.horz_edge_padding) @@ -109,6 +111,7 @@ class VoiceSettingsWindow(SettingsWindow): if self.font: config.set("main", "font", self.font) config.set("main", "square_avatar", "%d" % (int(self.square_avatar))) + config.set("main", "only_speaking", "%d" % (int(self.only_speaking))) config.set("main", "monitor", self.monitor) config.set("main", "vert_edge_padding", "%d" % (self.vert_edge_padding)) @@ -256,6 +259,11 @@ class VoiceSettingsWindow(SettingsWindow): square_avatar.set_active(self.square_avatar) square_avatar.connect("toggled", self.change_square_avatar) + only_speaking_label = Gtk.Label.new("Only Speaking") + only_speaking = Gtk.CheckButton.new() + only_speaking.set_active(self.only_speaking) + only_speaking.connect("toggled", self.change_only_speaking) + box.attach(font_label, 0, 0, 1, 1) box.attach(font, 1, 0, 1, 1) box.attach(bg_col_label, 0, 1, 1, 1) @@ -284,6 +292,8 @@ class VoiceSettingsWindow(SettingsWindow): box.attach(horz_edge_padding, 1, 14, 1, 1) box.attach(square_avatar_label, 0, 15, 1, 1) box.attach(square_avatar, 1, 15, 1, 1) + box.attach(only_speaking_label, 0, 16, 1, 1) + box.attach(only_speaking, 1, 16, 1, 1) self.add(box) @@ -436,3 +446,9 @@ class VoiceSettingsWindow(SettingsWindow): self.square_avatar = button.get_active() self.save_config() + + def change_only_speaking(self, button): + self.overlay.set_only_speaking(button.get_active()) + + self.only_speaking = button.get_active() + self.save_config() From ed8ebf3fbee7042d3fedb540c8dd3d85f393164e Mon Sep 17 00:00:00 2001 From: mastercooker Date: Fri, 2 Oct 2020 20:42:32 +0100 Subject: [PATCH 03/77] Draw deaf icon --- discover_overlay/voice_overlay.py | 59 +++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/discover_overlay/voice_overlay.py b/discover_overlay/voice_overlay.py index 7a96972..13d1f66 100644 --- a/discover_overlay/voice_overlay.py +++ b/discover_overlay/voice_overlay.py @@ -199,12 +199,14 @@ class VoiceOverlayWindow(OverlayWindow): (w, h) = self.get_size() c = None mute = False + deaf = False alpha = 1.0 if "speaking" in user and user["speaking"]: c = self.talk_col if "mute" in user and user["mute"]: mute = True if "deaf" in user and user["deaf"]: + deaf = True alpha = 0.5 pix = None if user["id"] in self.avatars: @@ -214,7 +216,10 @@ class VoiceOverlayWindow(OverlayWindow): context, user["username"], w - self.avatar_size - self.horz_edge_padding, y) self.draw_avatar_pix( context, pix, w - self.avatar_size - self.horz_edge_padding, y, c, alpha) - if mute: + if deaf: + self.draw_deaf(context, w - self.avatar_size - + self.horz_edge_padding, y, 1.0) + elif mute: self.draw_mute(context, w - self.avatar_size - self.horz_edge_padding, y, alpha) else: @@ -222,7 +227,9 @@ class VoiceOverlayWindow(OverlayWindow): context, user["username"], self.avatar_size + self.horz_edge_padding, y) self.draw_avatar_pix( context, pix, self.horz_edge_padding, y, c, alpha) - if mute: + if deaf: + self.draw_deaf(context, self.horz_edge_padding, y, 1.0) + elif mute: self.draw_mute(context, self.horz_edge_padding, y, alpha) def draw_text(self, context, string, x, y): @@ -339,3 +346,51 @@ class VoiceOverlayWindow(OverlayWindow): context.fill() context.restore() + + def draw_deaf(self, context, x, y, a): + context.save() + context.translate(x, y) + context.scale(self.avatar_size, self.avatar_size) + self.set_mute_col(a) + context.save() + + # Clip Strike-through + context.set_fill_rule(cairo.FILL_RULE_EVEN_ODD) + context.set_line_width(0.1) + context.move_to(0.0, 0.0) + context.line_to(1.0, 0.0) + context.line_to(1.0, 1.0) + context.line_to(0.0, 1.0) + context.line_to(0.0, 0.0) + context.close_path() + context.new_sub_path() + context.arc(0.9, 0.1, 0.05, 1.25 * math.pi, 2.25 * math.pi) + context.arc(0.1, 0.9, 0.05, .25 * math.pi, 1.25 * math.pi) + context.close_path() + context.clip() + + + # Top band + context.arc(0.5, 0.5, 0.2, 1.0 * math.pi, 0) + context.stroke() + + # Left band + context.arc(0.28, 0.65, 0.075, 1.5 * math.pi, 0.5 * math.pi) + context.move_to(0.3, 0.5) + context.line_to(0.3, 0.75) + context.stroke() + + # Right band + context.arc(0.72, 0.65, 0.075, 0.5 * math.pi, 1.5 * math.pi) + context.move_to(0.7, 0.5) + context.line_to(0.7, 0.75) + context.stroke() + + context.restore() + # Strike through + context.arc(0.7, 0.3, 0.035, 1.25 * math.pi, 2.25 * math.pi) + context.arc(0.3, 0.7, 0.035, .25 * math.pi, 1.25 * math.pi) + context.close_path() + context.fill() + + context.restore() From 645fc7e9c79b1d4432af9a4b4a658c08eaabb78e Mon Sep 17 00:00:00 2001 From: trigg Date: Fri, 2 Oct 2020 22:51:08 +0100 Subject: [PATCH 04/77] - Added rich text (bold/italic/underline) fixes #59 - Added option to show attachments fixes #57 - Include in-line custom emoji (why god why) --- discover_overlay/discord_connector.py | 23 +-- discover_overlay/image_getter.py | 63 +++++++- discover_overlay/text_overlay.py | 207 ++++++++++++++++++++++---- discover_overlay/text_settings.py | 18 +++ discover_overlay/voice_overlay.py | 8 +- 5 files changed, 271 insertions(+), 48 deletions(-) diff --git a/discover_overlay/discord_connector.py b/discover_overlay/discord_connector.py index 20d9131..6cba8a2 100644 --- a/discover_overlay/discord_connector.py +++ b/discover_overlay/discord_connector.py @@ -34,7 +34,6 @@ class DiscordConnector: self.last_connection = "" self.text = [] self.authed = False - self.timeregex = re.compile(r"\.\d+") def get_access_token_stage1(self): global oauth_token @@ -87,12 +86,8 @@ class DiscordConnector: self.in_room.remove(userid) def add_text(self, message): - # Remove micro time - time_input = message["timestamp"] - time_input = self.timeregex.sub("", time_input) - print(time_input) utc_time = time.strptime( - time_input, "%Y-%m-%dT%H:%M:%S%z") + message["timestamp"], "%Y-%m-%dT%H:%M:%S.%f%z") t = time.time() epoch_time = calendar.timegm(utc_time) un = message["author"]["username"] @@ -107,6 +102,7 @@ class DiscordConnector: 'nick': un, 'nick_col': ac, 'time': epoch_time, + 'attach': self.get_attachment_from_message(message), }) self.text_altered = True @@ -118,7 +114,8 @@ class DiscordConnector: 'content': self.get_message_from_message(message_in), 'nick': message['nick'], 'nick_col': message['nick_col'], - 'time': message['time']} + 'time': message['time'], + 'attach': message['attach']} self.text[idx] = new_message self.text_altered = True return @@ -133,7 +130,9 @@ class DiscordConnector: return def get_message_from_message(self, message): - if "content" in message and len(message["content"]) > 0: + if "content_parsed" in message: + return message["content_parsed"] + elif "content" in message and len(message["content"]) > 0: return message["content"] elif len(message["embeds"]) == 1: if "rawDescription" in message["embeds"][0]: @@ -141,10 +140,14 @@ class DiscordConnector: if "author" in message["embeds"][0]: return message["embeds"][0]["author"]["name"] elif len(message["attachments"]) == 1: - # Need to care - return "-- attachment --" + return "" return "" + def get_attachment_from_message(self, message): + if len(message["attachments"]) == 1: + return message["attachments"] + return None + def update_user(self, user): if user["id"] in self.userlist: if not "mute" in user and "mute" in self.userlist[user["id"]]: diff --git a/discover_overlay/image_getter.py b/discover_overlay/image_getter.py index a9a11ae..674c7b8 100644 --- a/discover_overlay/image_getter.py +++ b/discover_overlay/image_getter.py @@ -3,10 +3,14 @@ gi.require_version("Gtk", "3.0") gi.require_version('PangoCairo', '1.0') gi.require_version('GdkPixbuf', '2.0') import urllib +import requests import threading from gi.repository.GdkPixbuf import Pixbuf from gi.repository import Gtk, GLib, Gio, GdkPixbuf, Gdk, Pango, PangoCairo +import cairo import logging +import PIL.Image as Image +from io import BytesIO class Image_Getter(): @@ -26,16 +30,69 @@ class Image_Getter(): input_stream = Gio.MemoryInputStream.new_from_data( response.read(), None) pixbuf = Pixbuf.new_from_stream(input_stream, None) - pixbuf = pixbuf.scale_simple(self.size, self.size, - GdkPixbuf.InterpType.BILINEAR) + if self.size: + pixbuf = pixbuf.scale_simple(self.size, self.size, + GdkPixbuf.InterpType.BILINEAR) + # elif self.limit_x or self.limit_y: + # px = pixbuf.width() + # py = pixbuf.height() + # aspect = px / py + # scale = 1.0 + # if self.limit_x and self.limit_y: + # scale = min(self.limit_x / px, self.limit_y / py, 1.0) + # elif self.limit_x: + # scale = min(self.limit_x / px, 1.0) + # elif self.limit_y: + # scale = min(self.limit_y / py, 1.0)## +# +# pixbuf = pixbuf.scale_simple(int(px * scale), int(py * scale), +# GdkPixbuf.InterpType.BILINEAR) + self.func(self.id, pixbuf) except Exception as e: logging.error( - "Could not access : %s" % (url)) + "Could not access : %s" % (self.url)) logging.error(e) +class Surface_Getter(): + def __init__(self, func, url, id, size): + self.func = func + self.id = id + self.url = url + self.size = size + + def get_url(self): + + im = Image.open(requests.get(self.url, stream=True, headers={ + 'Referer': 'https://streamkit.discord.com/overlay/voice', 'User-Agent': 'Mozilla/5.0'}).raw) + surf = self.from_pil(im) + + self.func(self.id, surf) + + def from_pil(self, im, alpha=1.0, format=cairo.FORMAT_ARGB32): + """ + :param im: Pillow Image + :param alpha: 0..1 alpha to add to non-alpha images + :param format: Pixel format for output surface + """ + assert format in ( + cairo.FORMAT_RGB24, cairo.FORMAT_ARGB32), "Unsupported pixel format: %s" % format + if 'A' not in im.getbands(): + im.putalpha(int(alpha * 256.)) + arr = bytearray(im.tobytes('raw', 'BGRa')) + surface = cairo.ImageSurface.create_for_data( + arr, format, im.width, im.height) + return surface + + def get_image(func, id, ava, size): image_getter = Image_Getter(func, id, ava, size) t = threading.Thread(target=image_getter.get_url, args=()) t.start() + + +def get_surface(func, id, ava, size): + image_getter = Surface_Getter(func, id, ava, size) + t = threading.Thread(target=image_getter.get_url, args=()) + t.start() diff --git a/discover_overlay/text_overlay.py b/discover_overlay/text_overlay.py index 77af430..3b40616 100644 --- a/discover_overlay/text_overlay.py +++ b/discover_overlay/text_overlay.py @@ -9,6 +9,9 @@ from gi.repository import Gtk, GLib, Gio, GdkPixbuf, Gdk, Pango, PangoCairo import cairo import logging import time +import sys +import re +from .image_getter import get_surface class TextOverlayWindow(OverlayWindow): @@ -18,10 +21,18 @@ class TextOverlayWindow(OverlayWindow): self.content = [] self.text_font = None self.text_size = 13 + # 0, 0, self.text_size, self.text_size) + self.pango_rect = Pango.Rectangle() + self.pango_rect.width = self.text_size * Pango.SCALE + self.pango_rect.height = self.text_size * Pango.SCALE + self.connected = True self.bg_col = [0.0, 0.6, 0.0, 0.1] self.fg_col = [1.0, 1.0, 1.0, 1.0] - #self.text_time = 30 + self.attachment = {} + + self.imgList = [] + self.imgFinder = re.compile(r"`") def set_text_time(self, t): self.text_time = t @@ -45,40 +56,128 @@ class TextOverlayWindow(OverlayWindow): self.bg_col = bg_col self.redraw() + def set_show_attach(self, att): + self.show_attach = att + self.redraw() + def set_popup_style(self, b): self.popup_style = b + def set_font(self, name, size): + self.text_font = name + self.text_size = size + self.pango_rect = Pango.Rectangle() + self.pango_rect.width = self.text_size * Pango.SCALE + self.pango_rect.height = self.text_size * Pango.SCALE + self.redraw() + + def make_line(self, msg): + ret = "" + if isinstance(msg, list): + for a in msg: + ret = "%s%s" % (ret, self.make_line(a)) + elif isinstance(msg, str): + ret = msg + elif msg['type'] == 'strong': + ret = "%s" % (self.make_line(msg['content'])) + elif msg['type'] == 'text': + ret = self.santize_string(msg['content']) + elif msg['type'] == 'link': + ret = "%s" % (self.make_line(msg['content'])) + elif msg['type'] == 'emoji': + if 'surrogate' in msg: + # ['src'] is SVG URL + ret = msg + # ret = msg['surrogate'] + else: + ### Add Image ### + url = ("https://cdn.discordapp.com/emojis/%s.png?v=1" % + (msg['emojiId'])) + img = {"url": url} + self.imgList.append(img) + ret = "`" + elif msg['type'] == 'inlineCode' or msg['type'] == 'codeBlock' or msg['type'] == 'blockQuote': + ret = "%s" % ( + msg['content']) + elif msg['type'] == 'u': + ret = "%s" % (self.make_line(msg['content'])) + elif msg['type'] == 'em': + ret = "%s" % (self.make_line(msg['content'])) + elif msg['type'] == 's': + ret = "%s" % (self.make_line(msg['content'])) + elif msg['type'] == 'channel': + ret = self.make_line(msg['content']) + elif msg['type'] == 'mention': + ret = self.make_line(msg['content']) + elif msg['type'] == 'br': + ret = '\n' + else: + logging.warning("Unknown text type : %s" % (msg["type"])) + return ret + + def recv_attach(self, id, pix): + self.attachment[id] = pix + self.redraw() + def do_draw(self, context): self.context = context - context.set_antialias(self.compositing) + context.set_antialias(cairo.ANTIALIAS_GOOD) (w, h) = self.get_size() # Make background transparent context.set_source_rgba(0.0, 0.0, 0.0, 0.0) context.paint() - if not self.connected: - return - long_string = "" - sep = "" - tnow = time.time() - for line in self.content: - if not self.popup_style or tnow - line['time'] < self.text_time: - col = "#fff" - if 'nick_col' in line and line['nick_col']: - col = line['nick_col'] - long_string = "%s%s%s: %s" % ( - long_string, - sep, - self.santize_string(col), - self.santize_string(line["nick"]), - self.santize_string(line["content"])) - sep = '\n' - if len(long_string) == 0: - return - layout = self.create_pango_layout(long_string) - layout.set_markup(long_string, -1) - attr = Pango.AttrList() + cy = h + for line in reversed(self.content): + out_line = "" + self.imgList = [] + + col = "#fff" + if 'nick_col' in line and line['nick_col']: + col = line['nick_col'] + for in_line in line['content']: + out_line = "%s%s" % (out_line, self.make_line(in_line)) + if line['attach'] and self.show_attach: + at = line['attach'][0] + url = at['url'] + if url in self.attachment: + cy = self.draw_attach(cy, url) + else: + get_surface(self.recv_attach, + url, + url, None) + # cy = self.draw_text(cy, "%s" % (line['attach'])) + cy = self.draw_text(cy, "%s: %s" % (self.santize_string(col), + self.santize_string(line["nick"]), out_line)) + if cy <= 0: + # We've done enough + break + + def draw_attach(self, y, url): + (w, h) = self.get_size() + if self.attachment[url]: + pix = self.attachment[url] + h = pix.get_height() + self.col(self.bg_col) + self.context.rectangle(0, y - h, w, h) + self.context.fill() + self.context.set_operator(cairo.OPERATOR_OVER) + self.col([1, 1, 1, 1]) + self.context.set_source_surface(pix, 0, y - h) + self.context.rectangle(0, y - h, w, h) + self.context.fill() + # Gdk.cairo_set_source_pixbuf(self.context, pix, 0, y - h) + # self.context.paint() + return y - h + return y + + def draw_text(self, y, text): + (w, h) = self.get_size() + + layout = self.create_pango_layout(text) + layout.set_markup(text, -1) + attr = layout.get_attributes() layout.set_width(Pango.SCALE * w) layout.set_spacing(Pango.SCALE * 3) @@ -87,16 +186,62 @@ class TextOverlayWindow(OverlayWindow): "%s %s" % (self.text_font, self.text_size)) layout.set_font_description(font) tw, th = layout.get_pixel_size() - - # Don't layer drawing over each other, always replace self.col(self.bg_col) - context.rectangle(0, -th + h, w, th) - context.fill() - context.set_operator(cairo.OPERATOR_OVER) + self.context.rectangle(0, y - th, w, th) + self.context.fill() + self.context.set_operator(cairo.OPERATOR_OVER) self.col(self.fg_col) - context.move_to(0, -th + h) - PangoCairo.show_layout(context, layout) + self.context.move_to(0, y - th) + PangoCairo.context_set_shape_renderer( + self.get_pango_context(), self.render_custom, None) + + text = layout.get_text() + count = 0 + + for loc in self.imgFinder.finditer(text): + idx = loc.start() + + if len(self.imgList) <= count: + break # We fucked up. Who types ` anyway + url = self.imgList[count] + + at = Pango.attr_shape_new_with_data( + self.pango_rect, self.pango_rect, count, None) + at.start_index = idx + at.end_index = idx + 1 + attr.insert(at) + count += 1 + layout.set_attributes(attr) + + PangoCairo.show_layout(self.context, layout) + return y - th + + def render_custom(self, ctx, shape, path, data): + key = self.imgList[shape.data]['url'] + if key not in self.attachment: + get_surface(self.recv_attach, + key, + key, None) + return + pix = self.attachment[key] + (x, y) = ctx.get_current_point() + px = pix.get_width() + py = pix.get_height() + ctx.save() + ctx.translate(x, y - self.text_size) + ctx.scale(self.text_size, self.text_size) + ctx.scale(1 / px, 1 / py) + ctx.set_source_surface(pix, 0, 0) + + ctx.rectangle(0, 0, px, py) + if not path: + ctx.fill() + ctx.restore() + + ctx.move_to(x + self.text_size, y) + + return True def santize_string(self, string): # I hate that Pango has nothing for this. diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 7df0a5f..157f8ab 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -109,6 +109,8 @@ class TextSettingsWindow(SettingsWindow): self.popup_style = config.getboolean( "text", "popup_style", fallback=False) self.text_time = config.getint("text", "text_time", fallback=30) + self.show_attach = config.getboolean( + "text", "show_attach", fallback=True) logging.info( "Loading saved channel %s" % (self.channel)) @@ -124,6 +126,7 @@ class TextSettingsWindow(SettingsWindow): self.overlay.set_fg(self.fg_col) self.overlay.set_popup_style(self.popup_style) self.overlay.set_text_time(self.text_time) + self.overlay.set_show_attach(self.show_attach) def save_config(self): config = ConfigParser(interpolation=None) @@ -145,6 +148,7 @@ class TextSettingsWindow(SettingsWindow): config.set("text", "fg_col", json.dumps(self.fg_col)) config.set("text", "popup_style", "%s" % (int(self.popup_style))) config.set("text", "text_time", "%s" % (int(self.text_time))) + config.set("text", "show_attach", "%s" % (int(self.show_attach))) if self.font: config.set("text", "font", self.font) @@ -255,6 +259,12 @@ class TextSettingsWindow(SettingsWindow): channel.add_attribute(rt, "text", 0) channel.add_attribute(rt, 'sensitive', 1) + # Show Attachments + show_attach_label = Gtk.Label.new("Show Attachments") + show_attach = Gtk.CheckButton.new() + show_attach.set_active(self.show_attach) + show_attach.connect("toggled", self.change_show_attach) + self.align_x_widget = align_x self.align_y_widget = align_y self.align_monitor_widget = monitor @@ -283,6 +293,8 @@ class TextSettingsWindow(SettingsWindow): box.attach(align_x, 1, 9, 1, 1) box.attach(align_y, 1, 10, 1, 1) box.attach(align_placement_button, 1, 11, 1, 1) + box.attach(show_attach_label, 0, 12, 1, 1) + box.attach(show_attach, 1, 12, 1, 1) self.add(box) @@ -413,3 +425,9 @@ class TextSettingsWindow(SettingsWindow): self.fg_col = c self.save_config() + + def change_show_attach(self, button): + self.overlay.set_show_attach(button.get_active()) + + self.show_attach = button.get_active() + self.save_config() diff --git a/discover_overlay/voice_overlay.py b/discover_overlay/voice_overlay.py index 13d1f66..8591965 100644 --- a/discover_overlay/voice_overlay.py +++ b/discover_overlay/voice_overlay.py @@ -104,9 +104,9 @@ class VoiceOverlayWindow(OverlayWindow): def reset_avatar(self): self.avatars = {} - self.def_avatar = get_image(self.recv_avatar, - "https://cdn.discordapp.com/embed/avatars/3.png", - 'def', self.avatar_size) + get_image(self.recv_avatar, + "https://cdn.discordapp.com/embed/avatars/3.png", + 'def', self.avatar_size) def set_user_list(self, userlist, alt): self.userlist = userlist @@ -263,7 +263,7 @@ class VoiceOverlayWindow(OverlayWindow): def draw_avatar_pix(self, context, pixbuf, x, y, c, alpha): if not pixbuf: pixbuf = self.def_avatar - + if not pixbuf: return context.move_to(x, y) From bfcd40169d11644889bc43dfb2144e890c80217e Mon Sep 17 00:00:00 2001 From: trigg Date: Fri, 2 Oct 2020 22:52:36 +0100 Subject: [PATCH 05/77] - Default should ideally match old behaviour --- discover_overlay/voice_settings.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/discover_overlay/voice_settings.py b/discover_overlay/voice_settings.py index 655aaa5..3b2af8d 100644 --- a/discover_overlay/voice_settings.py +++ b/discover_overlay/voice_settings.py @@ -55,7 +55,8 @@ class VoiceSettingsWindow(SettingsWindow): self.font = config.get("main", "font", fallback=None) self.square_avatar = config.getboolean( "main", "square_avatar", fallback=False) - self.only_speaking = config.getboolean("main", "only_speaking", fallback=True) + self.only_speaking = config.getboolean( + "main", "only_speaking", fallback=False) self.monitor = config.get("main", "monitor", fallback="None") self.vert_edge_padding = config.getint( "main", "vert_edge_padding", fallback=0) From d8c99c4673a6622196f0ed3724c94af23575bed0 Mon Sep 17 00:00:00 2001 From: trigg Date: Fri, 2 Oct 2020 22:55:09 +0100 Subject: [PATCH 06/77] - Undo debugging edit in emoji --- discover_overlay/text_overlay.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/discover_overlay/text_overlay.py b/discover_overlay/text_overlay.py index 3b40616..6e55df6 100644 --- a/discover_overlay/text_overlay.py +++ b/discover_overlay/text_overlay.py @@ -87,8 +87,8 @@ class TextOverlayWindow(OverlayWindow): elif msg['type'] == 'emoji': if 'surrogate' in msg: # ['src'] is SVG URL - ret = msg - # ret = msg['surrogate'] + #ret = msg + ret = msg['surrogate'] else: ### Add Image ### url = ("https://cdn.discordapp.com/emojis/%s.png?v=1" % From 03835616ae645b9cfea06ef6a6608f32ce7d4d24 Mon Sep 17 00:00:00 2001 From: trigg Date: Fri, 2 Oct 2020 23:08:04 +0100 Subject: [PATCH 07/77] Update README.md --- README.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/README.md b/README.md index 708935f..3dbe6d5 100644 --- a/README.md +++ b/README.md @@ -33,15 +33,6 @@ run `discover-overlay` if this fails it is most likely in `~/.local/bin/discover Comes with sane-enough defaults but has a system tray icon & settings window if needed. -## Still in progress - -Not all features are at the level I would like. - -To do list: - -- Text channels -- Text notifications (different from above) -- Open to suggestions ## Why do you keep making Discord Overlays? From 2f341254b45ae3d263fa3b7da9d16ac4bd5fc45a Mon Sep 17 00:00:00 2001 From: midget3111 Date: Fri, 2 Oct 2020 23:44:05 +0100 Subject: [PATCH 08/77] Changed "Only Speaking" to "Display Speakers Only" --- discover_overlay/voice_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discover_overlay/voice_settings.py b/discover_overlay/voice_settings.py index 3b2af8d..ad400b2 100644 --- a/discover_overlay/voice_settings.py +++ b/discover_overlay/voice_settings.py @@ -260,7 +260,7 @@ class VoiceSettingsWindow(SettingsWindow): square_avatar.set_active(self.square_avatar) square_avatar.connect("toggled", self.change_square_avatar) - only_speaking_label = Gtk.Label.new("Only Speaking") + only_speaking_label = Gtk.Label.new("Display Speakers Only") only_speaking = Gtk.CheckButton.new() only_speaking.set_active(self.only_speaking) only_speaking.connect("toggled", self.change_only_speaking) From b46d398a8187e634950b2e5888a73c979bb9635b Mon Sep 17 00:00:00 2001 From: trigg Date: Fri, 2 Oct 2020 23:58:36 +0100 Subject: [PATCH 09/77] - Fixed popup mode text --- discover_overlay/text_overlay.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/discover_overlay/text_overlay.py b/discover_overlay/text_overlay.py index 6e55df6..adeafcf 100644 --- a/discover_overlay/text_overlay.py +++ b/discover_overlay/text_overlay.py @@ -129,7 +129,10 @@ class TextOverlayWindow(OverlayWindow): context.paint() cy = h + tnow = time.time() for line in reversed(self.content): + if self.popup_style and tnow - line['time'] > self.text_time: + break out_line = "" self.imgList = [] From bd2be2b98cdb4bbe7a8bd52caac35cf4d2eb7c05 Mon Sep 17 00:00:00 2001 From: mastercooker Date: Sat, 3 Oct 2020 11:28:17 +0100 Subject: [PATCH 10/77] Add "Higlight Self" option --- discover_overlay/discover_overlay.py | 34 ++++++++++++---------------- discover_overlay/text_overlay.py | 3 ++- discover_overlay/voice_overlay.py | 31 ++++++++++++++++++------- discover_overlay/voice_settings.py | 17 ++++++++++++++ 4 files changed, 57 insertions(+), 28 deletions(-) diff --git a/discover_overlay/discover_overlay.py b/discover_overlay/discover_overlay.py index 9c50c31..362a9f2 100755 --- a/discover_overlay/discover_overlay.py +++ b/discover_overlay/discover_overlay.py @@ -38,11 +38,23 @@ import logging class Discover: def __init__(self): - pass + self.a = Autostart("discover_overlay") + # a.set_autostart(True) + self.create_gui() + self.connection = DiscordConnector( + self.text_settings, self.voice_settings, + self.text_overlay, self.voice_overlay) + self.connection.connect() + GLib.timeout_add((1000 / 60), self.connection.do_read) + + try: + Gtk.main() + except: + pass def create_gui(self): - self.voice_overlay = VoiceOverlayWindow() - self.text_overlay = TextOverlayWindow() + self.voice_overlay = VoiceOverlayWindow(self) + self.text_overlay = TextOverlayWindow(self) self.menu = self.make_menu() self.make_sys_tray_icon(self.menu) self.voice_settings = VoiceSettingsWindow(self.voice_overlay) @@ -103,23 +115,7 @@ class Discover: def close(self, a=None, b=None, c=None): Gtk.main_quit() - def main(self): - self.a = Autostart("discover_overlay") - # a.set_autostart(True) - self.create_gui() - self.connection = DiscordConnector( - self.text_settings, self.voice_settings, - self.text_overlay, self.voice_overlay) - self.connection.connect() - GLib.timeout_add((1000 / 60), self.connection.do_read) - - try: - Gtk.main() - except: - pass - def entrypoint(): logging.getLogger().setLevel(logging.INFO) discover = Discover() - discover.main() diff --git a/discover_overlay/text_overlay.py b/discover_overlay/text_overlay.py index adeafcf..f1dd23b 100644 --- a/discover_overlay/text_overlay.py +++ b/discover_overlay/text_overlay.py @@ -15,8 +15,9 @@ from .image_getter import get_surface class TextOverlayWindow(OverlayWindow): - def __init__(self): + def __init__(self, discover): OverlayWindow.__init__(self) + self.discover = discover self.text_spacing = 4 self.content = [] self.text_font = None diff --git a/discover_overlay/voice_overlay.py b/discover_overlay/voice_overlay.py index 8591965..b29d35c 100644 --- a/discover_overlay/voice_overlay.py +++ b/discover_overlay/voice_overlay.py @@ -1,4 +1,5 @@ import gi + gi.require_version("Gtk", "3.0") gi.require_version('PangoCairo', '1.0') gi.require_version('GdkPixbuf', '2.0') @@ -13,10 +14,10 @@ import logging class VoiceOverlayWindow(OverlayWindow): - - def __init__(self): + def __init__(self, discover): OverlayWindow.__init__(self) + self.discover = discover self.avatars = {} self.avatar_size = 48 @@ -87,6 +88,9 @@ class VoiceOverlayWindow(OverlayWindow): def set_only_speaking(self, only_speaking): self.only_speaking = only_speaking + def set_highlight_self(self, highlight_self): + self.highlight_self = highlight_self + def set_wind_col(self): self.col(self.wind_col) @@ -142,16 +146,28 @@ class VoiceOverlayWindow(OverlayWindow): if not self.connected: return + connection = self.discover.connection + self_user = connection.user + # Gather which users to draw - if self.only_speaking: - self.users_to_draw = self.userlist[:] + self.users_to_draw = self.userlist[:] + for user in self.userlist: + # Bad object equality here, so we need to reassign + if user["id"] == self_user["id"]: + self_user = user + # Remove users that arent speaking - for user in self.userlist: + if self.only_speaking: speaking = "speaking" in user and user["speaking"] if not speaking: self.users_to_draw.remove(user) - else: - self.users_to_draw = self.userlist + + if self.highlight_self: + try: + self.users_to_draw.remove(self_user) + except ValueError: + pass # Not in list + self.users_to_draw.insert(0, self_user) # Get size of window (w, h) = self.get_size() @@ -369,7 +385,6 @@ class VoiceOverlayWindow(OverlayWindow): context.close_path() context.clip() - # Top band context.arc(0.5, 0.5, 0.2, 1.0 * math.pi, 0) context.stroke() diff --git a/discover_overlay/voice_settings.py b/discover_overlay/voice_settings.py index ad400b2..de39dc8 100644 --- a/discover_overlay/voice_settings.py +++ b/discover_overlay/voice_settings.py @@ -57,6 +57,8 @@ class VoiceSettingsWindow(SettingsWindow): "main", "square_avatar", fallback=False) self.only_speaking = config.getboolean( "main", "only_speaking", fallback=False) + self.highlight_self = config.getboolean( + "main", "highlight_self", fallback=False) self.monitor = config.get("main", "monitor", fallback="None") self.vert_edge_padding = config.getint( "main", "vert_edge_padding", fallback=0) @@ -80,6 +82,7 @@ class VoiceSettingsWindow(SettingsWindow): self.overlay.set_text_padding(self.text_padding) self.overlay.set_square_avatar(self.square_avatar) self.overlay.set_only_speaking(self.only_speaking) + self.overlay.set_highlight_self(self.highlight_self) self.overlay.set_monitor(self.get_monitor_index(self.monitor)) self.overlay.set_vert_edge_padding(self.vert_edge_padding) self.overlay.set_horz_edge_padding(self.horz_edge_padding) @@ -113,6 +116,7 @@ class VoiceSettingsWindow(SettingsWindow): config.set("main", "font", self.font) config.set("main", "square_avatar", "%d" % (int(self.square_avatar))) config.set("main", "only_speaking", "%d" % (int(self.only_speaking))) + config.set("main", "highlight_self", "%d" % (int(self.highlight_self))) config.set("main", "monitor", self.monitor) config.set("main", "vert_edge_padding", "%d" % (self.vert_edge_padding)) @@ -265,6 +269,11 @@ class VoiceSettingsWindow(SettingsWindow): only_speaking.set_active(self.only_speaking) only_speaking.connect("toggled", self.change_only_speaking) + highlight_self_label = Gtk.Label.new("Highlight Self") + highlight_self = Gtk.CheckButton.new() + highlight_self.set_active(self.highlight_self) + highlight_self.connect("toggled", self.change_highlight_self) + box.attach(font_label, 0, 0, 1, 1) box.attach(font, 1, 0, 1, 1) box.attach(bg_col_label, 0, 1, 1, 1) @@ -295,6 +304,8 @@ class VoiceSettingsWindow(SettingsWindow): box.attach(square_avatar, 1, 15, 1, 1) box.attach(only_speaking_label, 0, 16, 1, 1) box.attach(only_speaking, 1, 16, 1, 1) + box.attach(highlight_self_label, 0, 17, 1, 1) + box.attach(highlight_self, 1, 17, 1, 1) self.add(box) @@ -453,3 +464,9 @@ class VoiceSettingsWindow(SettingsWindow): self.only_speaking = button.get_active() self.save_config() + + def change_highlight_self(self, button): + self.overlay.set_highlight_self(button.get_active()) + + self.highlight_self = button.get_active() + self.save_config() From 42f832c1c5cea948ee380bf79fb57c40230561d1 Mon Sep 17 00:00:00 2001 From: trigg Date: Sat, 3 Oct 2020 13:01:01 +0100 Subject: [PATCH 11/77] - Clean imports --- discover_overlay/discord_connector.py | 1 + discover_overlay/discover_overlay.py | 15 +-------------- discover_overlay/draggable_window.py | 5 +---- discover_overlay/image_getter.py | 3 +-- discover_overlay/overlay.py | 5 +---- discover_overlay/settings.py | 5 +---- discover_overlay/text_overlay.py | 7 +------ discover_overlay/text_settings.py | 5 +---- discover_overlay/voice_overlay.py | 5 +---- discover_overlay/voice_settings.py | 5 +---- 10 files changed, 10 insertions(+), 46 deletions(-) diff --git a/discover_overlay/discord_connector.py b/discover_overlay/discord_connector.py index 6cba8a2..6424e1c 100644 --- a/discover_overlay/discord_connector.py +++ b/discover_overlay/discord_connector.py @@ -3,6 +3,7 @@ import select import time import json import re +import sys import requests import logging import calendar diff --git a/discover_overlay/discover_overlay.py b/discover_overlay/discover_overlay.py index 362a9f2..60ddaef 100755 --- a/discover_overlay/discover_overlay.py +++ b/discover_overlay/discover_overlay.py @@ -12,21 +12,8 @@ # along with this program. If not, see . import gi gi.require_version("Gtk", "3.0") -gi.require_version('PangoCairo', '1.0') -gi.require_version('GdkPixbuf', '2.0') -from gi.repository.GdkPixbuf import Pixbuf -from gi.repository import Gtk, GLib, Gio, GdkPixbuf, Gdk, Pango, PangoCairo -import os -import sys -import json -import math -import time -import cairo -import base64 +from gi.repository import Gtk, GLib import select -import urllib -import requests -import websocket from .voice_settings import VoiceSettingsWindow from .text_settings import TextSettingsWindow from .voice_overlay import VoiceOverlayWindow diff --git a/discover_overlay/draggable_window.py b/discover_overlay/draggable_window.py index f2da1b9..e277dcc 100644 --- a/discover_overlay/draggable_window.py +++ b/discover_overlay/draggable_window.py @@ -1,10 +1,7 @@ import gi gi.require_version("Gtk", "3.0") -gi.require_version('PangoCairo', '1.0') -gi.require_version('GdkPixbuf', '2.0') import cairo -from gi.repository.GdkPixbuf import Pixbuf -from gi.repository import Gtk, GLib, Gio, GdkPixbuf, Gdk, Pango, PangoCairo +from gi.repository import Gtk, Gdk import logging diff --git a/discover_overlay/image_getter.py b/discover_overlay/image_getter.py index 674c7b8..16d3ffb 100644 --- a/discover_overlay/image_getter.py +++ b/discover_overlay/image_getter.py @@ -1,12 +1,11 @@ import gi gi.require_version("Gtk", "3.0") -gi.require_version('PangoCairo', '1.0') gi.require_version('GdkPixbuf', '2.0') import urllib import requests import threading from gi.repository.GdkPixbuf import Pixbuf -from gi.repository import Gtk, GLib, Gio, GdkPixbuf, Gdk, Pango, PangoCairo +from gi.repository import Gtk, Gio, GdkPixbuf, Gdk import cairo import logging import PIL.Image as Image diff --git a/discover_overlay/overlay.py b/discover_overlay/overlay.py index c7b8953..4df097b 100644 --- a/discover_overlay/overlay.py +++ b/discover_overlay/overlay.py @@ -1,9 +1,6 @@ import gi gi.require_version("Gtk", "3.0") -gi.require_version('PangoCairo', '1.0') -gi.require_version('GdkPixbuf', '2.0') -from gi.repository.GdkPixbuf import Pixbuf -from gi.repository import Gtk, GLib, Gio, GdkPixbuf, Gdk, Pango, PangoCairo +from gi.repository import Gtk, Gdk import cairo import logging diff --git a/discover_overlay/settings.py b/discover_overlay/settings.py index 0443a76..a839f0c 100644 --- a/discover_overlay/settings.py +++ b/discover_overlay/settings.py @@ -1,11 +1,8 @@ import gi gi.require_version("Gtk", "3.0") -gi.require_version('PangoCairo', '1.0') -gi.require_version('GdkPixbuf', '2.0') import sys import os -from gi.repository.GdkPixbuf import Pixbuf -from gi.repository import Gtk, GLib, Gio, GdkPixbuf, Gdk, Pango, PangoCairo +from gi.repository import Gtk, Gdk import logging diff --git a/discover_overlay/text_overlay.py b/discover_overlay/text_overlay.py index f1dd23b..4e2a917 100644 --- a/discover_overlay/text_overlay.py +++ b/discover_overlay/text_overlay.py @@ -1,15 +1,12 @@ import gi gi.require_version("Gtk", "3.0") gi.require_version('PangoCairo', '1.0') -gi.require_version('GdkPixbuf', '2.0') import math from .overlay import OverlayWindow -from gi.repository.GdkPixbuf import Pixbuf -from gi.repository import Gtk, GLib, Gio, GdkPixbuf, Gdk, Pango, PangoCairo +from gi.repository import Gtk, Gdk, Pango, PangoCairo import cairo import logging import time -import sys import re from .image_getter import get_surface @@ -171,8 +168,6 @@ class TextOverlayWindow(OverlayWindow): self.context.set_source_surface(pix, 0, y - h) self.context.rectangle(0, y - h, w, h) self.context.fill() - # Gdk.cairo_set_source_pixbuf(self.context, pix, 0, y - h) - # self.context.paint() return y - h return y diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 157f8ab..b1df793 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -1,13 +1,10 @@ import gi gi.require_version("Gtk", "3.0") -gi.require_version('PangoCairo', '1.0') -gi.require_version('GdkPixbuf', '2.0') import json from configparser import ConfigParser from .draggable_window import DraggableWindow from .settings import SettingsWindow -from gi.repository.GdkPixbuf import Pixbuf -from gi.repository import Gtk, GLib, Gio, GdkPixbuf, Gdk, Pango, PangoCairo +from gi.repository import Gtk, Gdk import logging diff --git a/discover_overlay/voice_overlay.py b/discover_overlay/voice_overlay.py index b29d35c..f98740e 100644 --- a/discover_overlay/voice_overlay.py +++ b/discover_overlay/voice_overlay.py @@ -1,13 +1,10 @@ import gi gi.require_version("Gtk", "3.0") -gi.require_version('PangoCairo', '1.0') -gi.require_version('GdkPixbuf', '2.0') import math from .overlay import OverlayWindow from .image_getter import get_image -from gi.repository.GdkPixbuf import Pixbuf -from gi.repository import Gtk, GLib, Gio, GdkPixbuf, Gdk, Pango, PangoCairo +from gi.repository import Gtk, Gdk import cairo import logging diff --git a/discover_overlay/voice_settings.py b/discover_overlay/voice_settings.py index de39dc8..9550aed 100644 --- a/discover_overlay/voice_settings.py +++ b/discover_overlay/voice_settings.py @@ -1,13 +1,10 @@ import gi gi.require_version("Gtk", "3.0") -gi.require_version('PangoCairo', '1.0') -gi.require_version('GdkPixbuf', '2.0') import json from configparser import ConfigParser from .draggable_window import DraggableWindow from .settings import SettingsWindow -from gi.repository.GdkPixbuf import Pixbuf -from gi.repository import Gtk, GLib, Gio, GdkPixbuf, Gdk, Pango, PangoCairo +from gi.repository import Gtk, Gdk import logging From 7a61f9d00bc6b448f493c4e9ee4cf899cde73e65 Mon Sep 17 00:00:00 2001 From: trigg Date: Sat, 3 Oct 2020 13:01:42 +0100 Subject: [PATCH 12/77] -Version push --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 6ef1a51..5e38049 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setup( name='discover-overlay', author='trigg', author_email='', - version='0.2', + version='0.2.2', description='Voice chat overlay', long_description=readme(), long_description_content_type='text/markdown', From 9143799bedf8f4714584a17186db11b3719cd739 Mon Sep 17 00:00:00 2001 From: mastercooker Date: Sat, 3 Oct 2020 14:46:38 +0100 Subject: [PATCH 13/77] Fix import error --- discover_overlay/voice_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discover_overlay/voice_settings.py b/discover_overlay/voice_settings.py index 9550aed..c7b2e18 100644 --- a/discover_overlay/voice_settings.py +++ b/discover_overlay/voice_settings.py @@ -4,7 +4,7 @@ import json from configparser import ConfigParser from .draggable_window import DraggableWindow from .settings import SettingsWindow -from gi.repository import Gtk, Gdk +from gi.repository import Gtk, Gdk, Pango import logging From 029c4a3ad1b47ceccbdec8c622771c0cf5ba1171 Mon Sep 17 00:00:00 2001 From: trigg Date: Sat, 3 Oct 2020 15:02:11 +0100 Subject: [PATCH 14/77] - Overzelous cleanup --- discover_overlay/text_settings.py | 2 +- discover_overlay/voice_settings.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index b1df793..b3b3fd8 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -4,7 +4,7 @@ import json from configparser import ConfigParser from .draggable_window import DraggableWindow from .settings import SettingsWindow -from gi.repository import Gtk, Gdk +from gi.repository import Gtk, Gdk, Pango import logging diff --git a/discover_overlay/voice_settings.py b/discover_overlay/voice_settings.py index 9550aed..c7b2e18 100644 --- a/discover_overlay/voice_settings.py +++ b/discover_overlay/voice_settings.py @@ -4,7 +4,7 @@ import json from configparser import ConfigParser from .draggable_window import DraggableWindow from .settings import SettingsWindow -from gi.repository import Gtk, Gdk +from gi.repository import Gtk, Gdk, Pango import logging From 2fd5d18604f38606dc77f3ee545758e4d28feb42 Mon Sep 17 00:00:00 2001 From: mastercooker Date: Sat, 3 Oct 2020 14:51:49 +0100 Subject: [PATCH 15/77] Use nicknames --- discover_overlay/discord_connector.py | 29 ++++++++++++++++----------- discover_overlay/voice_overlay.py | 17 +++++++++++++--- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/discover_overlay/discord_connector.py b/discover_overlay/discord_connector.py index 6424e1c..e0fed32 100644 --- a/discover_overlay/discord_connector.py +++ b/discover_overlay/discord_connector.py @@ -151,13 +151,16 @@ class DiscordConnector: def update_user(self, user): if user["id"] in self.userlist: - if not "mute" in user and "mute" in self.userlist[user["id"]]: - user["mute"] = self.userlist[user["id"]]["mute"] - if not "deaf" in user and "deaf" in self.userlist[user["id"]]: - user["deaf"] = self.userlist[user["id"]]["deaf"] - if not "speaking" in user and "speaking" in self.userlist[user["id"]]: - user["speaking"] = self.userlist[user["id"]]["speaking"] - if self.userlist[user["id"]]["avatar"] != user["avatar"]: + olduser = self.userlist[user["id"]] + if "mute" not in user and "mute" in olduser: + user["mute"] = olduser["mute"] + if "deaf" not in user and "deaf" in olduser: + user["deaf"] = olduser["deaf"] + if "speaking" not in user and "speaking" in olduser: + user["speaking"] = olduser["speaking"] + if "nick" not in user and "nick" in olduser: + user["nick"] = olduser["nick"] + if olduser["avatar"] != user["avatar"]: self.voice_overlay.delete_avatar(user["id"]) self.userlist[user["id"]] = user @@ -172,7 +175,6 @@ class DiscordConnector: elif j["evt"] == "VOICE_STATE_UPDATE": self.list_altered = True thisuser = j["data"]["user"] - un = j["data"]["user"]["username"] mute = j["data"]["voice_state"]["mute"] or j["data"]["voice_state"]["self_mute"] or j["data"]["voice_state"]["suppress"] deaf = j["data"]["voice_state"]["deaf"] or j["data"]["voice_state"]["self_deaf"] thisuser["mute"] = mute @@ -180,10 +182,12 @@ class DiscordConnector: self.update_user(thisuser) elif j["evt"] == "VOICE_STATE_CREATE": self.list_altered = True - self.update_user(j["data"]["user"]) + thisuser = j["data"]["user"] + nick = j["data"]["nick"] + thisuser["nick"] = nick + self.update_user(thisuser) # If someone joins any voice room grab it fresh from server self.req_channel_details(self.current_voice) - un = j["data"]["user"]["username"] if j["data"]["user"]["id"] == self.user["id"]: self.find_user() elif j["evt"] == "VOICE_STATE_DELETE": @@ -268,8 +272,9 @@ class DiscordConnector: self.list_altered = True self.in_room = [] for voice in j["data"]["voice_states"]: - self.update_user(voice["user"]) - self.set_in_room(voice["user"]["id"], True) + thisuser = voice["user"] + self.update_user(thisuser) + self.set_in_room(thisuser["id"], True) if self.current_text == j["data"]["id"]: self.text = [] for message in j["data"]["messages"]: diff --git a/discover_overlay/voice_overlay.py b/discover_overlay/voice_overlay.py index f98740e..5a81322 100644 --- a/discover_overlay/voice_overlay.py +++ b/discover_overlay/voice_overlay.py @@ -111,7 +111,12 @@ class VoiceOverlayWindow(OverlayWindow): def set_user_list(self, userlist, alt): self.userlist = userlist - self.userlist.sort(key=lambda x: x["username"]) + for user in userlist: + if "nick" in user: + user["friendlyname"] = user["nick"] + else: + user["friendlyname"] = user["username"] + self.userlist.sort(key=lambda x: x["friendlyname"]) screen = self.get_screen() c = screen.is_composited() if not self.compositing == c: @@ -153,6 +158,12 @@ class VoiceOverlayWindow(OverlayWindow): if user["id"] == self_user["id"]: self_user = user + # Update friendly name with nick if possible + if "nick" in user: + user["friendlyname"] = user["nick"] + else: + user["friendlyname"] = user["username"] + # Remove users that arent speaking if self.only_speaking: speaking = "speaking" in user and user["speaking"] @@ -226,7 +237,7 @@ class VoiceOverlayWindow(OverlayWindow): pix = self.avatars[user["id"]] if self.align_right: self.draw_text( - context, user["username"], w - self.avatar_size - self.horz_edge_padding, y) + context, user["friendlyname"], w - self.avatar_size - self.horz_edge_padding, y) self.draw_avatar_pix( context, pix, w - self.avatar_size - self.horz_edge_padding, y, c, alpha) if deaf: @@ -237,7 +248,7 @@ class VoiceOverlayWindow(OverlayWindow): self.horz_edge_padding, y, alpha) else: self.draw_text( - context, user["username"], self.avatar_size + self.horz_edge_padding, y) + context, user["friendlyname"], self.avatar_size + self.horz_edge_padding, y) self.draw_avatar_pix( context, pix, self.horz_edge_padding, y, c, alpha) if deaf: From 0407a59fcb8734d56fe32f9f17d558c96fb930a9 Mon Sep 17 00:00:00 2001 From: mastercooker Date: Sat, 3 Oct 2020 15:13:09 +0100 Subject: [PATCH 16/77] Fix nicknames --- discover_overlay/discord_connector.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/discover_overlay/discord_connector.py b/discover_overlay/discord_connector.py index e0fed32..e7cfc35 100644 --- a/discover_overlay/discord_connector.py +++ b/discover_overlay/discord_connector.py @@ -175,6 +175,8 @@ class DiscordConnector: elif j["evt"] == "VOICE_STATE_UPDATE": self.list_altered = True thisuser = j["data"]["user"] + nick = j["data"]["nick"] + thisuser["nick"] = nick mute = j["data"]["voice_state"]["mute"] or j["data"]["voice_state"]["self_mute"] or j["data"]["voice_state"]["suppress"] deaf = j["data"]["voice_state"]["deaf"] or j["data"]["voice_state"]["self_deaf"] thisuser["mute"] = mute @@ -273,6 +275,8 @@ class DiscordConnector: self.in_room = [] for voice in j["data"]["voice_states"]: thisuser = voice["user"] + if "nick" in j["data"]: + thisuser["nick"] = j["data"]["nick"] self.update_user(thisuser) self.set_in_room(thisuser["id"], True) if self.current_text == j["data"]["id"]: From 6888081bcd60c7f8cf1ddd776e3a1b8be42a8dab Mon Sep 17 00:00:00 2001 From: Alex Carter Date: Sun, 4 Oct 2020 15:42:42 +1100 Subject: [PATCH 17/77] Added option to display icons only --- discover_overlay/voice_overlay.py | 15 +++++++++++---- discover_overlay/voice_settings.py | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/discover_overlay/voice_overlay.py b/discover_overlay/voice_overlay.py index 5a81322..82fe9c9 100644 --- a/discover_overlay/voice_overlay.py +++ b/discover_overlay/voice_overlay.py @@ -26,6 +26,7 @@ class VoiceOverlayWindow(OverlayWindow): self.horz_edge_padding = 0 self.round_avatar = True + self.icon_only = True self.talk_col = [0.0, 0.6, 0.0, 0.1] self.text_col = [1.0, 1.0, 1.0, 1.0] self.norm_col = [0.0, 0.0, 0.0, 0.5] @@ -87,6 +88,10 @@ class VoiceOverlayWindow(OverlayWindow): def set_highlight_self(self, highlight_self): self.highlight_self = highlight_self + + def set_icon_only(self, i): + self.icon_only = i + self.redraw() def set_wind_col(self): self.col(self.wind_col) @@ -236,8 +241,9 @@ class VoiceOverlayWindow(OverlayWindow): if user["id"] in self.avatars: pix = self.avatars[user["id"]] if self.align_right: - self.draw_text( - context, user["friendlyname"], w - self.avatar_size - self.horz_edge_padding, y) + if not self.icon_only: + self.draw_text( + context, user["friendlyname"], w - self.avatar_size - self.horz_edge_padding, y) self.draw_avatar_pix( context, pix, w - self.avatar_size - self.horz_edge_padding, y, c, alpha) if deaf: @@ -247,8 +253,9 @@ class VoiceOverlayWindow(OverlayWindow): self.draw_mute(context, w - self.avatar_size - self.horz_edge_padding, y, alpha) else: - self.draw_text( - context, user["friendlyname"], self.avatar_size + self.horz_edge_padding, y) + if not self.icon_only: + self.draw_text( + context, user["friendlyname"], self.avatar_size + self.horz_edge_padding, y) self.draw_avatar_pix( context, pix, self.horz_edge_padding, y, c, alpha) if deaf: diff --git a/discover_overlay/voice_settings.py b/discover_overlay/voice_settings.py index c7b2e18..d068510 100644 --- a/discover_overlay/voice_settings.py +++ b/discover_overlay/voice_settings.py @@ -56,6 +56,8 @@ class VoiceSettingsWindow(SettingsWindow): "main", "only_speaking", fallback=False) self.highlight_self = config.getboolean( "main", "highlight_self", fallback=False) + self.icon_only = config.getboolean( + "main", "icon_only", fallback=False) self.monitor = config.get("main", "monitor", fallback="None") self.vert_edge_padding = config.getint( "main", "vert_edge_padding", fallback=0) @@ -80,6 +82,7 @@ class VoiceSettingsWindow(SettingsWindow): self.overlay.set_square_avatar(self.square_avatar) self.overlay.set_only_speaking(self.only_speaking) self.overlay.set_highlight_self(self.highlight_self) + self.overlay.set_icon_only(self.icon_only) self.overlay.set_monitor(self.get_monitor_index(self.monitor)) self.overlay.set_vert_edge_padding(self.vert_edge_padding) self.overlay.set_horz_edge_padding(self.horz_edge_padding) @@ -114,6 +117,7 @@ class VoiceSettingsWindow(SettingsWindow): config.set("main", "square_avatar", "%d" % (int(self.square_avatar))) config.set("main", "only_speaking", "%d" % (int(self.only_speaking))) config.set("main", "highlight_self", "%d" % (int(self.highlight_self))) + config.set("main", "icon_only", "%d" % (int(self.icon_only))) config.set("main", "monitor", self.monitor) config.set("main", "vert_edge_padding", "%d" % (self.vert_edge_padding)) @@ -271,6 +275,12 @@ class VoiceSettingsWindow(SettingsWindow): highlight_self.set_active(self.highlight_self) highlight_self.connect("toggled", self.change_highlight_self) + # Display icon only + icon_only_label = Gtk.Label.new("Display Icon Only") + icon_only = Gtk.CheckButton.new() + icon_only.set_active(self.icon_only) + icon_only.connect("toggled", self.change_icon_only) + box.attach(font_label, 0, 0, 1, 1) box.attach(font, 1, 0, 1, 1) box.attach(bg_col_label, 0, 1, 1, 1) @@ -303,6 +313,8 @@ class VoiceSettingsWindow(SettingsWindow): box.attach(only_speaking, 1, 16, 1, 1) box.attach(highlight_self_label, 0, 17, 1, 1) box.attach(highlight_self, 1, 17, 1, 1) + box.attach(icon_only_label, 0, 18, 1, 1) + box.attach(icon_only, 1, 18, 1, 1) self.add(box) @@ -467,3 +479,9 @@ class VoiceSettingsWindow(SettingsWindow): self.highlight_self = button.get_active() self.save_config() + + def change_icon_only(self, button): + self.overlay.set_icon_only(button.get_active()) + + self.icon_only = button.get_active() + self.save_config() From 3e766aff665bcf62204ad6794343beaa81a1f4a9 Mon Sep 17 00:00:00 2001 From: trigg Date: Mon, 5 Oct 2020 14:47:03 +0100 Subject: [PATCH 18/77] - Optional sort by last spoken - Fixes #69 - Causes #73 --- discover_overlay/discord_connector.py | 6 ++++++ discover_overlay/voice_overlay.py | 17 +++++++++++++---- discover_overlay/voice_settings.py | 24 ++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/discover_overlay/discord_connector.py b/discover_overlay/discord_connector.py index e7cfc35..a372eae 100644 --- a/discover_overlay/discord_connector.py +++ b/discover_overlay/discord_connector.py @@ -160,8 +160,12 @@ class DiscordConnector: user["speaking"] = olduser["speaking"] if "nick" not in user and "nick" in olduser: user["nick"] = olduser["nick"] + if "lastspoken" not in user and "lastspoken" in olduser: + user["lastspoken"] = olduser["lastspoken"] if olduser["avatar"] != user["avatar"]: self.voice_overlay.delete_avatar(user["id"]) + if "lastspoken" not in user: # Still nothing? + user["lastspoken"] = 0 # EEEEPOOCH EEEEEPOCH! BELIEVE MEEEE self.userlist[user["id"]] = user def on_message(self, message): @@ -205,6 +209,8 @@ class DiscordConnector: # It's only possible to get alerts for the room you're in self.set_channel(j["data"]["channel_id"]) self.userlist[j["data"]["user_id"]]["speaking"] = True + self.userlist[j["data"]["user_id"]]["lastspoken"] = time.time() + self.list_altered = True self.set_in_room(j["data"]["user_id"], True) elif j["evt"] == "SPEAKING_STOP": self.list_altered = True diff --git a/discover_overlay/voice_overlay.py b/discover_overlay/voice_overlay.py index 82fe9c9..9ed7a79 100644 --- a/discover_overlay/voice_overlay.py +++ b/discover_overlay/voice_overlay.py @@ -88,7 +88,10 @@ class VoiceOverlayWindow(OverlayWindow): def set_highlight_self(self, highlight_self): self.highlight_self = highlight_self - + + def set_order(self, i): + self.order = i + def set_icon_only(self, i): self.icon_only = i self.redraw() @@ -121,7 +124,12 @@ class VoiceOverlayWindow(OverlayWindow): user["friendlyname"] = user["nick"] else: user["friendlyname"] = user["username"] - self.userlist.sort(key=lambda x: x["friendlyname"]) + if self.order == 1: # ID Sort + self.userlist.sort(key=lambda x: x["id"]) + elif self.order == 2: # Spoken sort + self.userlist.sort(key=lambda x: x["lastspoken"], reverse=True) + else: # Name sort + self.userlist.sort(key=lambda x: x["friendlyname"]) screen = self.get_screen() c = screen.is_composited() if not self.compositing == c: @@ -230,13 +238,14 @@ class VoiceOverlayWindow(OverlayWindow): mute = False deaf = False alpha = 1.0 - if "speaking" in user and user["speaking"]: - c = self.talk_col + if "mute" in user and user["mute"]: mute = True if "deaf" in user and user["deaf"]: deaf = True alpha = 0.5 + if "speaking" in user and user["speaking"] and not deaf and not mute: + c = self.talk_col pix = None if user["id"] in self.avatars: pix = self.avatars[user["id"]] diff --git a/discover_overlay/voice_settings.py b/discover_overlay/voice_settings.py index d068510..2cda7d8 100644 --- a/discover_overlay/voice_settings.py +++ b/discover_overlay/voice_settings.py @@ -68,6 +68,7 @@ class VoiceSettingsWindow(SettingsWindow): self.floating_y = config.getint("main", "floating_y", fallback=0) self.floating_w = config.getint("main", "floating_w", fallback=400) self.floating_h = config.getint("main", "floating_h", fallback=400) + self.order = config.getint("main", "order", fallback=0) # Pass all of our config over to the overlay self.overlay.set_align_x(self.align_x) @@ -86,6 +87,7 @@ class VoiceSettingsWindow(SettingsWindow): self.overlay.set_monitor(self.get_monitor_index(self.monitor)) self.overlay.set_vert_edge_padding(self.vert_edge_padding) self.overlay.set_horz_edge_padding(self.horz_edge_padding) + self.overlay.set_order(self.order) self.overlay.set_floating( self.floating, self.floating_x, self.floating_y, self.floating_w, self.floating_h) @@ -128,6 +130,7 @@ class VoiceSettingsWindow(SettingsWindow): config.set("main", "floating_y", "%s" % (self.floating_y)) config.set("main", "floating_w", "%s" % (self.floating_w)) config.set("main", "floating_h", "%s" % (self.floating_h)) + config.set("main", "order", "%s" % (self.order)) with open(self.configFile, 'w') as file: config.write(file) @@ -281,6 +284,19 @@ class VoiceSettingsWindow(SettingsWindow): icon_only.set_active(self.icon_only) icon_only.connect("toggled", self.change_icon_only) + # Order avatars + order_label = Gtk.Label.new("Order Avatars By") + order_store = Gtk.ListStore(str) + order_store.append(["Alphabetically"]) + order_store.append(["ID"]) + order_store.append(["Last Spoken"]) + order = Gtk.ComboBox.new_with_model(order_store) + order.set_active(self.order) + order.connect("changed", self.change_order) + rt = Gtk.CellRendererText() + order.pack_start(rt, True) + order.add_attribute(rt, "text", 0) + box.attach(font_label, 0, 0, 1, 1) box.attach(font, 1, 0, 1, 1) box.attach(bg_col_label, 0, 1, 1, 1) @@ -315,6 +331,8 @@ class VoiceSettingsWindow(SettingsWindow): box.attach(highlight_self, 1, 17, 1, 1) box.attach(icon_only_label, 0, 18, 1, 1) box.attach(icon_only, 1, 18, 1, 1) + box.attach(order_label, 0, 19, 1, 1) + box.attach(order, 1, 19, 1, 1) self.add(box) @@ -485,3 +503,9 @@ class VoiceSettingsWindow(SettingsWindow): self.icon_only = button.get_active() self.save_config() + + def change_order(self, button): + self.overlay.set_order(button.get_active()) + + self.order = button.get_active() + self.save_config() From c1d7447db16e1ccfea5811825bf96a4f63d41ab7 Mon Sep 17 00:00:00 2001 From: trigg Date: Mon, 5 Oct 2020 16:26:11 +0100 Subject: [PATCH 19/77] - draw img helper function --- discover_overlay/image_getter.py | 63 ++++++++++++++++++++++++++++++-- discover_overlay/text_overlay.py | 38 +++++++------------ 2 files changed, 73 insertions(+), 28 deletions(-) diff --git a/discover_overlay/image_getter.py b/discover_overlay/image_getter.py index 16d3ffb..5fcc6b7 100644 --- a/discover_overlay/image_getter.py +++ b/discover_overlay/image_getter.py @@ -63,11 +63,16 @@ class Surface_Getter(): def get_url(self): - im = Image.open(requests.get(self.url, stream=True, headers={ - 'Referer': 'https://streamkit.discord.com/overlay/voice', 'User-Agent': 'Mozilla/5.0'}).raw) - surf = self.from_pil(im) + try: + resp = requests.get(self.url, stream=True, headers={ + 'Referer': 'https://streamkit.discord.com/overlay/voice', 'User-Agent': 'Mozilla/5.0'}) + raw = resp.raw + im = Image.open(raw) + surf = self.from_pil(im) - self.func(self.id, surf) + self.func(self.id, surf) + except: + logging.error("Unable to open %s" % (self.url)) def from_pil(self, im, alpha=1.0, format=cairo.FORMAT_ARGB32): """ @@ -95,3 +100,53 @@ def get_surface(func, id, ava, size): image_getter = Surface_Getter(func, id, ava, size) t = threading.Thread(target=image_getter.get_url, args=()) t.start() + + +def get_aspected_size(img, w, h, anchor=0, hanchor=0): + px = img.get_width() + py = img.get_height() + if py < 1 or h < 1: + return (0, 0) + img_aspect = px / py + rect_aspect = w / h + + y = 0 + x = 0 + if img_aspect > rect_aspect: + oh = h + h = w / img_aspect + if anchor == 0: + y = y + (oh - h) + if anchor == 1: + y = y + ((oh - h) / 2) + elif img_aspect < rect_aspect: + ow = w + w = h * img_aspect + if hanchor == 2: + x = x + (ow - w) + if hanchor == 1: + x = x + ((ow - w) / 2) + return (x, y, w, h) + + +def draw_img_to_rect(img, ctx, x, y, w, h, path=False, aspect=False, anchor=0, hanchor=0): + # Path - only add the path do not fill : True/False + # Aspect - keep aspect ratio : True/False + # Anchor - with aspect : 0=left 1=middle 2=right + # HAnchor - with apect : 0=bottom 1=middle 2=top + ctx.save() + px = img.get_width() + py = img.get_height() + (x_off, y_off, w, h) = get_aspected_size( + img, w, h, anchor=anchor, hanchor=hanchor) + + ctx.translate(x + x_off, y + y_off) + ctx.scale(w, h) + ctx.scale(1 / px, 1 / py) + ctx.set_source_surface(img, 0, 0) + + ctx.rectangle(0, 0, px, py) + if not path: + ctx.fill() + ctx.restore() + return (w, h) diff --git a/discover_overlay/text_overlay.py b/discover_overlay/text_overlay.py index 4e2a917..7ec6692 100644 --- a/discover_overlay/text_overlay.py +++ b/discover_overlay/text_overlay.py @@ -8,7 +8,7 @@ import cairo import logging import time import re -from .image_getter import get_surface +from .image_getter import get_surface, draw_img_to_rect, get_aspected_size class TextOverlayWindow(OverlayWindow): @@ -157,18 +157,21 @@ class TextOverlayWindow(OverlayWindow): def draw_attach(self, y, url): (w, h) = self.get_size() - if self.attachment[url]: + if url in self.attachment and self.attachment[url]: pix = self.attachment[url] - h = pix.get_height() + iw = pix.get_width() + ih = pix.get_height() + iw = min(iw, w) + ih = min(ih, (h * .7)) + (ax, ay, aw, ah) = get_aspected_size(pix, iw, ih) self.col(self.bg_col) - self.context.rectangle(0, y - h, w, h) + self.context.rectangle(0, y - ah, w, ah) + self.context.fill() self.context.set_operator(cairo.OPERATOR_OVER) - self.col([1, 1, 1, 1]) - self.context.set_source_surface(pix, 0, y - h) - self.context.rectangle(0, y - h, w, h) - self.context.fill() - return y - h + new_w, new_h = draw_img_to_rect( + pix, self.context, 0, y - ih, iw, ih, aspect=True) + return y - new_h return y def draw_text(self, y, text): @@ -225,21 +228,8 @@ class TextOverlayWindow(OverlayWindow): return pix = self.attachment[key] (x, y) = ctx.get_current_point() - px = pix.get_width() - py = pix.get_height() - ctx.save() - ctx.translate(x, y - self.text_size) - ctx.scale(self.text_size, self.text_size) - ctx.scale(1 / px, 1 / py) - ctx.set_source_surface(pix, 0, 0) - - ctx.rectangle(0, 0, px, py) - if not path: - ctx.fill() - ctx.restore() - - ctx.move_to(x + self.text_size, y) - + draw_img_to_rect(pix, ctx, x, y - self.text_size, self.text_size, + self.text_size, path=path) return True def santize_string(self, string): From a45710d82cdaa1ac708c9a44d334a9c768abc700 Mon Sep 17 00:00:00 2001 From: trigg Date: Mon, 5 Oct 2020 16:42:44 +0100 Subject: [PATCH 20/77] - Use surface not pixbuf to draw avatar icon - Don't Re-get url each resize, just redraw --- discover_overlay/voice_overlay.py | 60 ++++++++++++------------------- 1 file changed, 23 insertions(+), 37 deletions(-) diff --git a/discover_overlay/voice_overlay.py b/discover_overlay/voice_overlay.py index 9ed7a79..cf377fd 100644 --- a/discover_overlay/voice_overlay.py +++ b/discover_overlay/voice_overlay.py @@ -3,7 +3,7 @@ import gi gi.require_version("Gtk", "3.0") import math from .overlay import OverlayWindow -from .image_getter import get_image +from .image_getter import get_surface, draw_img_to_rect from gi.repository import Gtk, Gdk import cairo import logging @@ -36,11 +36,9 @@ class VoiceOverlayWindow(OverlayWindow): self.users_to_draw = [] self.connected = False self.force_location() - self.def_avatar = get_image(self.recv_avatar, - "https://cdn.discordapp.com/embed/avatars/3.png", - 'def', self.avatar_size) - - self.first_draw = True + self.def_avatar = get_surface(self.recv_avatar, + "https://cdn.discordapp.com/embed/avatars/3.png", + 'def', self.avatar_size) def set_bg(self, bg): self.norm_col = bg @@ -60,7 +58,6 @@ class VoiceOverlayWindow(OverlayWindow): def set_avatar_size(self, size): self.avatar_size = size - self.reset_avatar() self.redraw() def set_icon_spacing(self, i): @@ -111,12 +108,6 @@ class VoiceOverlayWindow(OverlayWindow): def set_mute_col(self, a=1.0): self.col(self.mute_col, a) - def reset_avatar(self): - self.avatars = {} - get_image(self.recv_avatar, - "https://cdn.discordapp.com/embed/avatars/3.png", - 'def', self.avatar_size) - def set_user_list(self, userlist, alt): self.userlist = userlist for user in userlist: @@ -213,7 +204,7 @@ class VoiceOverlayWindow(OverlayWindow): self.context = None def recv_avatar(self, id, pix): - if(id == 'def'): + if id == 'def': self.def_avatar = pix else: self.avatars[id] = pix @@ -227,8 +218,8 @@ class VoiceOverlayWindow(OverlayWindow): if user["id"] not in self.avatars and user["avatar"]: url = "https://cdn.discordapp.com/avatars/%s/%s.jpg" % ( user['id'], user['avatar']) - get_image(self.recv_avatar, url, user["id"], - self.avatar_size) + get_surface(self.recv_avatar, url, user["id"], + self.avatar_size) # Set the key with no value to avoid spamming requests self.avatars[user["id"]] = None @@ -237,13 +228,11 @@ class VoiceOverlayWindow(OverlayWindow): c = None mute = False deaf = False - alpha = 1.0 if "mute" in user and user["mute"]: mute = True if "deaf" in user and user["deaf"]: deaf = True - alpha = 0.5 if "speaking" in user and user["speaking"] and not deaf and not mute: c = self.talk_col pix = None @@ -254,23 +243,23 @@ class VoiceOverlayWindow(OverlayWindow): self.draw_text( context, user["friendlyname"], w - self.avatar_size - self.horz_edge_padding, y) self.draw_avatar_pix( - context, pix, w - self.avatar_size - self.horz_edge_padding, y, c, alpha) + context, pix, w - self.avatar_size - self.horz_edge_padding, y, c) if deaf: self.draw_deaf(context, w - self.avatar_size - - self.horz_edge_padding, y, 1.0) + self.horz_edge_padding, y) elif mute: self.draw_mute(context, w - self.avatar_size - - self.horz_edge_padding, y, alpha) + self.horz_edge_padding, y) else: if not self.icon_only: self.draw_text( context, user["friendlyname"], self.avatar_size + self.horz_edge_padding, y) self.draw_avatar_pix( - context, pix, self.horz_edge_padding, y, c, alpha) + context, pix, self.horz_edge_padding, y, c) if deaf: - self.draw_deaf(context, self.horz_edge_padding, y, 1.0) + self.draw_deaf(context, self.horz_edge_padding, y) elif mute: - self.draw_mute(context, self.horz_edge_padding, y, alpha) + self.draw_mute(context, self.horz_edge_padding, y) def draw_text(self, context, string, x, y): if self.text_font: @@ -300,27 +289,24 @@ class VoiceOverlayWindow(OverlayWindow): context.move_to(x + self.text_pad, y + ho + h) context.show_text(string) - def draw_avatar_pix(self, context, pixbuf, x, y, c, alpha): + def draw_avatar_pix(self, context, pixbuf, x, y, c): if not pixbuf: pixbuf = self.def_avatar - - if not pixbuf: - return + if not pixbuf: + return context.move_to(x, y) context.save() - #context.set_source_pixbuf(pixbuf, 0.0, 0.0) if self.round_avatar: context.arc(x + (self.avatar_size / 2), y + (self.avatar_size / 2), self.avatar_size / 2, 0, 2 * math.pi) context.clip() - self.set_wind_col() + self.set_norm_col() context.set_operator(cairo.OPERATOR_SOURCE) context.rectangle(x, y, self.avatar_size, self.avatar_size) context.fill() - context.set_operator(cairo.OPERATOR_OVER) - Gdk.cairo_set_source_pixbuf(context, pixbuf, x, y) - context.paint_with_alpha(alpha) + draw_img_to_rect(pixbuf, context, x, y, + self.avatar_size, self.avatar_size) context.restore() if c: if self.round_avatar: @@ -333,11 +319,11 @@ class VoiceOverlayWindow(OverlayWindow): self.col(c) context.stroke() - def draw_mute(self, context, x, y, a): + def draw_mute(self, context, x, y): context.save() context.translate(x, y) context.scale(self.avatar_size, self.avatar_size) - self.set_mute_col(a) + self.set_mute_col() context.save() # Clip Strike-through @@ -387,11 +373,11 @@ class VoiceOverlayWindow(OverlayWindow): context.restore() - def draw_deaf(self, context, x, y, a): + def draw_deaf(self, context, x, y): context.save() context.translate(x, y) context.scale(self.avatar_size, self.avatar_size) - self.set_mute_col(a) + self.set_mute_col() context.save() # Clip Strike-through From 405e0320c4f2dc80790a52ed1812b59ebe8d8ec2 Mon Sep 17 00:00:00 2001 From: trigg Date: Mon, 5 Oct 2020 16:44:21 +0100 Subject: [PATCH 21/77] - Don't adjust ratio if not needed --- discover_overlay/image_getter.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/discover_overlay/image_getter.py b/discover_overlay/image_getter.py index 5fcc6b7..bdac51e 100644 --- a/discover_overlay/image_getter.py +++ b/discover_overlay/image_getter.py @@ -137,8 +137,11 @@ def draw_img_to_rect(img, ctx, x, y, w, h, path=False, aspect=False, anchor=0, h ctx.save() px = img.get_width() py = img.get_height() - (x_off, y_off, w, h) = get_aspected_size( - img, w, h, anchor=anchor, hanchor=hanchor) + x_off = 0 + y_off = 0 + if aspect: + (x_off, y_off, w, h) = get_aspected_size( + img, w, h, anchor=anchor, hanchor=hanchor) ctx.translate(x + x_off, y + y_off) ctx.scale(w, h) From cda5bc0c810d450dc5ea5a728a3a9e7c8d71858b Mon Sep 17 00:00:00 2001 From: trigg Date: Mon, 5 Oct 2020 17:00:25 +0100 Subject: [PATCH 22/77] - Sort by speaking alongside speaking start time fixes #73 --- discover_overlay/discord_connector.py | 2 ++ discover_overlay/voice_overlay.py | 1 + 2 files changed, 3 insertions(+) diff --git a/discover_overlay/discord_connector.py b/discover_overlay/discord_connector.py index a372eae..0ca61b2 100644 --- a/discover_overlay/discord_connector.py +++ b/discover_overlay/discord_connector.py @@ -166,6 +166,8 @@ class DiscordConnector: self.voice_overlay.delete_avatar(user["id"]) if "lastspoken" not in user: # Still nothing? user["lastspoken"] = 0 # EEEEPOOCH EEEEEPOCH! BELIEVE MEEEE + if "speaking" not in user: + user["speaking"] = False self.userlist[user["id"]] = user def on_message(self, message): diff --git a/discover_overlay/voice_overlay.py b/discover_overlay/voice_overlay.py index cf377fd..9503c19 100644 --- a/discover_overlay/voice_overlay.py +++ b/discover_overlay/voice_overlay.py @@ -119,6 +119,7 @@ class VoiceOverlayWindow(OverlayWindow): self.userlist.sort(key=lambda x: x["id"]) elif self.order == 2: # Spoken sort self.userlist.sort(key=lambda x: x["lastspoken"], reverse=True) + self.userlist.sort(key=lambda x: x["speaking"], reverse=True) else: # Name sort self.userlist.sort(key=lambda x: x["friendlyname"]) screen = self.get_screen() From 8c50d3c2cc8d69b350bc0ca1a67f51bcce837349 Mon Sep 17 00:00:00 2001 From: trigg Date: Sun, 11 Oct 2020 14:55:18 +0000 Subject: [PATCH 23/77] - Added RPC file, monitor for changes - Added PID file and if it is already locked then write args to RPC file - open configuration from args - option to '--close' and '--configure' - Added PIL and pidfile as dependencies - Added desktop files for --configure and --close - Fixed #75 - Fixed 78 --- discover_overlay/discover_overlay.py | 59 ++++++++++++++++++++++++++-- discover_overlay/text_settings.py | 1 + discover_overlay_close.desktop | 8 ++++ discover_overlay_conf.desktop | 8 ++++ setup.py | 4 +- 5 files changed, 75 insertions(+), 5 deletions(-) create mode 100644 discover_overlay_close.desktop create mode 100644 discover_overlay_conf.desktop diff --git a/discover_overlay/discover_overlay.py b/discover_overlay/discover_overlay.py index 60ddaef..5ca0f3c 100755 --- a/discover_overlay/discover_overlay.py +++ b/discover_overlay/discover_overlay.py @@ -12,7 +12,7 @@ # along with this program. If not, see . import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, GLib +from gi.repository import Gtk, GLib, Gio import select from .voice_settings import VoiceSettingsWindow from .text_settings import TextSettingsWindow @@ -21,10 +21,18 @@ from .text_overlay import TextOverlayWindow from .discord_connector import DiscordConnector from .autostart import Autostart import logging +import pidfile +import os +import sys + +try: + from xdg.BaseDirectory import xdg_config_home +except ModuleNotFoundError: + from xdg import XDG_CONFIG_HOME as xdg_config_home class Discover: - def __init__(self): + def __init__(self, rpc_file, args): self.a = Autostart("discover_overlay") # a.set_autostart(True) self.create_gui() @@ -33,12 +41,39 @@ class Discover: self.text_overlay, self.voice_overlay) self.connection.connect() GLib.timeout_add((1000 / 60), self.connection.do_read) + self.rpc_file = rpc_file + rpc_file = Gio.File.new_for_path(rpc_file) + monitor = rpc_file.monitor_file(0, None) + monitor.connect("changed", self.rpc_changed) + self.do_args(args) try: Gtk.main() except: pass + def do_args(self, data): + if "--help" in data: + pass + elif "--about" in data: + pass + elif "--configure-voice" in data: + self.show_vsettings() + elif "--configure-text" in data: + self.show_tsettings() + elif "--configure" in data: + self.show_tsettings() + self.show_vsettings() + elif "--close" in data: + sys.exit(0) + + + def rpc_changed(self, a=None, b=None, c=None,d=None): + with open (self.rpc_file, "r") as tfile: + data=tfile.readlines() + if len(data)>=1: + self.do_args(data[0]) + def create_gui(self): self.voice_overlay = VoiceOverlayWindow(self) self.text_overlay = TextOverlayWindow(self) @@ -104,5 +139,21 @@ class Discover: def entrypoint(): - logging.getLogger().setLevel(logging.INFO) - discover = Discover() + configDir = os.path.join(xdg_config_home, "discover_overlay") + os.makedirs(configDir, exist_ok=True) + line = "" + for arg in sys.argv[1:]: + line = "%s %s" % (line, arg) + pid_file = os.path.join(configDir, "discover_overlay.pid") + rpc_file = os.path.join(configDir, "discover_overlay.rpc") + try: + with pidfile.PIDFile(pid_file): + logging.getLogger().setLevel(logging.INFO) + discover = Discover(rpc_file, line) + except pidfile.AlreadyRunningError: + logging.warn("Discover overlay is currently running") + + with open(rpc_file, "w") as tfile: + tfile.write(line) + logging.warn("Sent RPC command") + diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index b3b3fd8..ed86e14 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -18,6 +18,7 @@ class TextSettingsWindow(SettingsWindow): self.placement_window = None self.init_config() self.list_channels_keys = [] + self.list_channels = {} self.ignore_channel_change = False self.create_gui() diff --git a/discover_overlay_close.desktop b/discover_overlay_close.desktop new file mode 100644 index 0000000..e49e3a0 --- /dev/null +++ b/discover_overlay_close.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Name=Discover Overlay - Close +Comment=Close Discover Overlay +Exec=discover-overlay --close +Icon=discover-overlay +Terminal=false +Type=Application +Catergories=Network; diff --git a/discover_overlay_conf.desktop b/discover_overlay_conf.desktop new file mode 100644 index 0000000..cebbbd7 --- /dev/null +++ b/discover_overlay_conf.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Name=Discover Overlay - Config +Comment=Open configuration for Discover Overlay +Exec=discover-overlay --configure +Icon=discover-overlay +Terminal=false +Type=Application +Catergories=Network; diff --git a/setup.py b/setup.py index 5e38049..22f6fa0 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ setup( packages=find_packages(), include_package_data=True, data_files=[ - ('share/applications', ['discover_overlay.desktop']), + ('share/applications', ['discover_overlay.desktop','discover_overlay_conf.desktop','discover_overlay_close.desktop']), ('share/icons', ['discover-overlay.png']) ], install_requires=[ @@ -25,6 +25,8 @@ setup( 'websocket-client', 'pyxdg', 'requests', + 'python-pidfile', + 'pillow', ], entry_points={ 'console_scripts': [ From 36411ca6c83f17c45badf79ac1bd9096c49febf9 Mon Sep 17 00:00:00 2001 From: trigg Date: Sun, 11 Oct 2020 15:11:43 +0000 Subject: [PATCH 24/77] - Some minor fixes. Added extra debug to assist with #41 --- discover_overlay/discord_connector.py | 8 ++++---- discover_overlay/discover_overlay.py | 2 +- discover_overlay/text_settings.py | 5 +---- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/discover_overlay/discord_connector.py b/discover_overlay/discord_connector.py index 0ca61b2..09ee2a5 100644 --- a/discover_overlay/discord_connector.py +++ b/discover_overlay/discord_connector.py @@ -37,7 +37,6 @@ class DiscordConnector: self.authed = False def get_access_token_stage1(self): - global oauth_token self.ws.send("{\"cmd\":\"AUTHORIZE\",\"args\":{\"client_id\":\"%s\",\"scopes\":[\"rpc\",\"messages.read\"],\"prompt\":\"none\"},\"nonce\":\"deadbeef\"}" % ( self.oauth_token)) @@ -89,7 +88,6 @@ class DiscordConnector: def add_text(self, message): utc_time = time.strptime( message["timestamp"], "%Y-%m-%dT%H:%M:%S.%f%z") - t = time.time() epoch_time = calendar.timegm(utc_time) un = message["author"]["username"] if "nick" in message and message['nick'] and len(message["nick"]) > 1: @@ -122,7 +120,6 @@ class DiscordConnector: return def delete_text(self, message_in): - global text, text_altered for idx in range(0, len(self.text)): message = self.text[idx] if message['id'] == message_in['id']: @@ -335,9 +332,12 @@ class DiscordConnector: channel, channel)) def find_user(self): + count = 0 for channel in self.channels: if self.channels[channel]["type"] == 2: self.req_channel_details(channel) + count+=1 + logging.warn("Getting %s rooms" %(count)) def sub_raw(self, cmd, channel, nonce): self.ws.send("{\"cmd\":\"SUBSCRIBE\",\"args\":{%s},\"evt\":\"%s\",\"nonce\":\"%s\"}" % ( @@ -404,7 +404,7 @@ class DiscordConnector: newlist.append(self.userlist[userid]) self.voice_overlay.set_user_list(newlist, self.list_altered) self.voice_overlay.set_connection(self.last_connection) - list_altered = False + self.list_altered = False # Update text list if self.text_overlay.popup_style: self.text_altered = True diff --git a/discover_overlay/discover_overlay.py b/discover_overlay/discover_overlay.py index 5ca0f3c..0cbe237 100755 --- a/discover_overlay/discover_overlay.py +++ b/discover_overlay/discover_overlay.py @@ -149,7 +149,7 @@ def entrypoint(): try: with pidfile.PIDFile(pid_file): logging.getLogger().setLevel(logging.INFO) - discover = Discover(rpc_file, line) + Discover(rpc_file, line) except pidfile.AlreadyRunningError: logging.warn("Discover overlay is currently running") diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index ed86e14..96115d0 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -42,10 +42,7 @@ class TextSettingsWindow(SettingsWindow): self.text_time_widget.hide() self.text_time_label_widget.hide() - model = monitor_store = Gtk.ListStore(str, bool) - # for c in self.list_channels_keys: - # print(self.list_channels[c]) - # model.append([self.list_channels[c]["name"]]) + model = Gtk.ListStore(str, bool) self.channel_lookup = [] for guild in self.guild_list(): guild_id, guild_name = guild From df8f7cd35acec029d817aa720f418e37f17c63cb Mon Sep 17 00:00:00 2001 From: trigg Date: Mon, 12 Oct 2020 00:24:19 +0000 Subject: [PATCH 25/77] - Added general settings - Option to force XShape even with composite on --- discover_overlay/discover_overlay.py | 21 ++++---- discover_overlay/general_settings.py | 75 ++++++++++++++++++++++++++++ discover_overlay/overlay.py | 7 ++- 3 files changed, 92 insertions(+), 11 deletions(-) create mode 100644 discover_overlay/general_settings.py diff --git a/discover_overlay/discover_overlay.py b/discover_overlay/discover_overlay.py index 0cbe237..8207f1d 100755 --- a/discover_overlay/discover_overlay.py +++ b/discover_overlay/discover_overlay.py @@ -19,7 +19,7 @@ from .text_settings import TextSettingsWindow from .voice_overlay import VoiceOverlayWindow from .text_overlay import TextOverlayWindow from .discord_connector import DiscordConnector -from .autostart import Autostart +from .general_settings import GeneralSettingsWindow import logging import pidfile import os @@ -33,8 +33,6 @@ except ModuleNotFoundError: class Discover: def __init__(self, rpc_file, args): - self.a = Autostart("discover_overlay") - # a.set_autostart(True) self.create_gui() self.connection = DiscordConnector( self.text_settings, self.voice_settings, @@ -57,6 +55,8 @@ class Discover: pass elif "--about" in data: pass + elif "--configure-general" in data: + self.show_gsettings() elif "--configure-voice" in data: self.show_vsettings() elif "--configure-text" in data: @@ -64,6 +64,7 @@ class Discover: elif "--configure" in data: self.show_tsettings() self.show_vsettings() + self.show_gsettings() elif "--close" in data: sys.exit(0) @@ -81,6 +82,7 @@ class Discover: self.make_sys_tray_icon(self.menu) self.voice_settings = VoiceSettingsWindow(self.voice_overlay) self.text_settings = TextSettingsWindow(self.text_overlay) + self.general_settings = GeneralSettingsWindow(self.text_overlay, self.voice_overlay) def make_sys_tray_icon(self, menu): # Create AppIndicator @@ -104,25 +106,21 @@ class Discover: menu = Gtk.Menu() vsettings_opt = Gtk.MenuItem.new_with_label("Voice Settings") tsettings_opt = Gtk.MenuItem.new_with_label("Text Settings") - autostart_opt = Gtk.CheckMenuItem("Start on boot") - autostart_opt.set_active(self.a.is_auto()) + gsettings_opt = Gtk.MenuItem.new_with_label("General Settings") close_opt = Gtk.MenuItem.new_with_label("Close") menu.append(vsettings_opt) menu.append(tsettings_opt) - menu.append(autostart_opt) + menu.append(gsettings_opt) menu.append(close_opt) vsettings_opt.connect("activate", self.show_vsettings) tsettings_opt.connect("activate", self.show_tsettings) - autostart_opt.connect("toggled", self.toggle_auto) + gsettings_opt.connect("activate", self.show_gsettings) close_opt.connect("activate", self.close) menu.show_all() return menu - def toggle_auto(self, button): - self.a.set_autostart(button.get_active()) - def show_menu(self, obj, button, time): self.menu.show_all() self.menu.popup( @@ -134,6 +132,9 @@ class Discover: def show_tsettings(self, obj=None, data=None): self.text_settings.present() + def show_gsettings(self, obj=None, data=None): + self.general_settings.present() + def close(self, a=None, b=None, c=None): Gtk.main_quit() diff --git a/discover_overlay/general_settings.py b/discover_overlay/general_settings.py new file mode 100644 index 0000000..3c76efb --- /dev/null +++ b/discover_overlay/general_settings.py @@ -0,0 +1,75 @@ +import gi +gi.require_version("Gtk", "3.0") +import json +from configparser import ConfigParser +from .draggable_window import DraggableWindow +from .settings import SettingsWindow +from .autostart import Autostart +from gi.repository import Gtk, Gdk, Pango +import logging + + +class GeneralSettingsWindow(SettingsWindow): + def __init__(self, overlay, overlay2): + Gtk.Window.__init__(self) + self.overlay = overlay + self.overlay2 = overlay + self.set_size_request(400, 200) + self.connect("destroy", self.close_window) + self.connect("delete-event", self.close_window) + self.init_config() + self.a = Autostart("discover_overlay") + + self.create_gui() + + def read_config(self): + config = ConfigParser(interpolation=None) + config.read(self.configFile) + self.xshape = config.getboolean("general", "xshape", fallback=False) + + # Pass all of our config over to the overlay + self.overlay.set_force_xshape(self.xshape) + self.overlay2.set_force_xshape(self.xshape) + + def save_config(self): + config = ConfigParser(interpolation=None) + config.read(self.configFile) + if not config.has_section("general"): + config.add_section("general") + + config.set("general", "xshape", "%d" % (int(self.xshape))) + + with open(self.configFile, 'w') as file: + config.write(file) + + def create_gui(self): + box = Gtk.Grid() + + # Auto start + autostart_label = Gtk.Label.new("Autostart on boot") + autostart = Gtk.CheckButton.new() + autostart.set_active(self.a.is_auto()) + autostart.connect("toggled", self.change_autostart) + + # Force XShape + xshape_label = Gtk.Label.new("Force XShape") + xshape = Gtk.CheckButton.new() + xshape.set_active(self.xshape) + xshape.connect("toggled", self.change_xshape) + + box.attach(autostart_label, 0, 0, 1, 1) + box.attach(autostart, 1, 0, 1, 1) + box.attach(xshape_label, 0, 1, 1, 1) + box.attach(xshape, 1, 1, 1, 1) + + self.add(box) + + def change_autostart(self, button): + self.autostart = button.get_active() + self.a.set_autostart(self.autostart) + + def change_xshape(self, button): + self.overlay.set_force_xshape(button.get_active()) + self.overlay2.set_force_xshape(button.get_active()) + self.xshape = button.get_active() + self.save_config() \ No newline at end of file diff --git a/discover_overlay/overlay.py b/discover_overlay/overlay.py index 4df097b..72bf7a9 100644 --- a/discover_overlay/overlay.py +++ b/discover_overlay/overlay.py @@ -3,6 +3,7 @@ gi.require_version("Gtk", "3.0") from gi.repository import Gtk, Gdk import cairo import logging +import sys class OverlayWindow(Gtk.Window): @@ -36,6 +37,7 @@ class OverlayWindow(Gtk.Window): self.align_right = True self.align_vert = 1 self.floating = False + self.force_xshape= False def draw(self, widget, context): pass @@ -105,7 +107,7 @@ class OverlayWindow(Gtk.Window): gdkwin = self.get_window() if gdkwin: - if not self.compositing: + if not self.compositing or self.force_xshape: (w, h) = self.get_size() surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h) surface_ctx = cairo.Context(surface) @@ -133,3 +135,6 @@ class OverlayWindow(Gtk.Window): def col(self, c, a=1.0): self.context.set_source_rgba(c[0], c[1], c[2], c[3] * a) + + def set_force_xshape(self, force): + self.force_xshape = force \ No newline at end of file From 45aeec404232684162efb3a76dfa53735f431351 Mon Sep 17 00:00:00 2001 From: trigg Date: Mon, 12 Oct 2020 17:37:39 +0000 Subject: [PATCH 26/77] - Fix for general settings window only showing once --- discover_overlay/general_settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/discover_overlay/general_settings.py b/discover_overlay/general_settings.py index 3c76efb..01d24df 100644 --- a/discover_overlay/general_settings.py +++ b/discover_overlay/general_settings.py @@ -19,6 +19,7 @@ class GeneralSettingsWindow(SettingsWindow): self.connect("delete-event", self.close_window) self.init_config() self.a = Autostart("discover_overlay") + self.placement_window = None self.create_gui() From 377787ef29586d496d37de6f77f39c5ddfee983d Mon Sep 17 00:00:00 2001 From: trigg Date: Mon, 12 Oct 2020 18:40:26 +0000 Subject: [PATCH 27/77] - Put all the setings windows together --- discover_overlay/discover_overlay.py | 42 +++++------------------- discover_overlay/general_settings.py | 2 +- discover_overlay/settings.py | 2 +- discover_overlay/settings_window.py | 49 ++++++++++++++++++++++++++++ discover_overlay/text_settings.py | 2 +- discover_overlay/voice_settings.py | 2 +- 6 files changed, 62 insertions(+), 37 deletions(-) create mode 100644 discover_overlay/settings_window.py diff --git a/discover_overlay/discover_overlay.py b/discover_overlay/discover_overlay.py index 8207f1d..4558aff 100755 --- a/discover_overlay/discover_overlay.py +++ b/discover_overlay/discover_overlay.py @@ -14,12 +14,10 @@ import gi gi.require_version("Gtk", "3.0") from gi.repository import Gtk, GLib, Gio import select -from .voice_settings import VoiceSettingsWindow -from .text_settings import TextSettingsWindow +from .settings_window import MainSettingsWindow from .voice_overlay import VoiceOverlayWindow from .text_overlay import TextOverlayWindow from .discord_connector import DiscordConnector -from .general_settings import GeneralSettingsWindow import logging import pidfile import os @@ -35,7 +33,7 @@ class Discover: def __init__(self, rpc_file, args): self.create_gui() self.connection = DiscordConnector( - self.text_settings, self.voice_settings, + self.settings.text_settings, self.settings.voice_settings, self.text_overlay, self.voice_overlay) self.connection.connect() GLib.timeout_add((1000 / 60), self.connection.do_read) @@ -55,16 +53,8 @@ class Discover: pass elif "--about" in data: pass - elif "--configure-general" in data: - self.show_gsettings() - elif "--configure-voice" in data: - self.show_vsettings() - elif "--configure-text" in data: - self.show_tsettings() elif "--configure" in data: - self.show_tsettings() - self.show_vsettings() - self.show_gsettings() + self.show_settings() elif "--close" in data: sys.exit(0) @@ -80,9 +70,7 @@ class Discover: self.text_overlay = TextOverlayWindow(self) self.menu = self.make_menu() self.make_sys_tray_icon(self.menu) - self.voice_settings = VoiceSettingsWindow(self.voice_overlay) - self.text_settings = TextSettingsWindow(self.text_overlay) - self.general_settings = GeneralSettingsWindow(self.text_overlay, self.voice_overlay) + self.settings = MainSettingsWindow(self.text_overlay, self.voice_overlay) def make_sys_tray_icon(self, menu): # Create AppIndicator @@ -104,19 +92,13 @@ class Discover: def make_menu(self): # Create System Menu menu = Gtk.Menu() - vsettings_opt = Gtk.MenuItem.new_with_label("Voice Settings") - tsettings_opt = Gtk.MenuItem.new_with_label("Text Settings") - gsettings_opt = Gtk.MenuItem.new_with_label("General Settings") + settings_opt = Gtk.MenuItem.new_with_label("Settings") close_opt = Gtk.MenuItem.new_with_label("Close") - menu.append(vsettings_opt) - menu.append(tsettings_opt) - menu.append(gsettings_opt) + menu.append(settings_opt) menu.append(close_opt) - vsettings_opt.connect("activate", self.show_vsettings) - tsettings_opt.connect("activate", self.show_tsettings) - gsettings_opt.connect("activate", self.show_gsettings) + settings_opt.connect("activate", self.show_settings) close_opt.connect("activate", self.close) menu.show_all() return menu @@ -126,14 +108,8 @@ class Discover: self.menu.popup( None, None, Gtk.StatusIcon.position_menu, obj, button, time) - def show_vsettings(self, obj=None, data=None): - self.voice_settings.present() - - def show_tsettings(self, obj=None, data=None): - self.text_settings.present() - - def show_gsettings(self, obj=None, data=None): - self.general_settings.present() + def show_settings(self, obj=None, data=None): + self.settings.present() def close(self, a=None, b=None, c=None): Gtk.main_quit() diff --git a/discover_overlay/general_settings.py b/discover_overlay/general_settings.py index 01d24df..b74764c 100644 --- a/discover_overlay/general_settings.py +++ b/discover_overlay/general_settings.py @@ -11,7 +11,7 @@ import logging class GeneralSettingsWindow(SettingsWindow): def __init__(self, overlay, overlay2): - Gtk.Window.__init__(self) + Gtk.VBox.__init__(self) self.overlay = overlay self.overlay2 = overlay self.set_size_request(400, 200) diff --git a/discover_overlay/settings.py b/discover_overlay/settings.py index a839f0c..f3cd426 100644 --- a/discover_overlay/settings.py +++ b/discover_overlay/settings.py @@ -12,7 +12,7 @@ except ModuleNotFoundError: from xdg import XDG_CONFIG_HOME as xdg_config_home -class SettingsWindow(Gtk.Window): +class SettingsWindow(Gtk.VBox): def init_config(self): self.configDir = os.path.join(xdg_config_home, "discover_overlay") os.makedirs(self.configDir, exist_ok=True) diff --git a/discover_overlay/settings_window.py b/discover_overlay/settings_window.py new file mode 100644 index 0000000..c088581 --- /dev/null +++ b/discover_overlay/settings_window.py @@ -0,0 +1,49 @@ +from .voice_settings import VoiceSettingsWindow +from .text_settings import TextSettingsWindow +from .general_settings import GeneralSettingsWindow + +import gi +gi.require_version("Gtk", "3.0") +import sys +import os +from gi.repository import Gtk, Gdk +import logging + + +class MainSettingsWindow(Gtk.Window): + def __init__(self, text_overlay, voice_overlay): + Gtk.Window.__init__(self) + + self.connect("destroy", self.close_window) + self.connect("delete-event", self.close_window) + + self.text_overlay = text_overlay + self.voice_overlay = voice_overlay + + # Create + nb = Gtk.Notebook() + #nb.set_tab_pos(Gtk.POS_TOP) + + self.voice_settings = VoiceSettingsWindow(self.voice_overlay) + nb.append_page(self.voice_settings) + nb.set_tab_label_text(self.voice_settings, "Voice") + self.text_settings = TextSettingsWindow(self.text_overlay) + nb.append_page(self.text_settings) + nb.set_tab_label_text(self.text_settings, "Text") + self.core_settings = GeneralSettingsWindow(self.text_overlay,self.voice_overlay) + nb.append_page(self.core_settings) + nb.set_tab_label_text(self.core_settings, "Core") + self.add(nb) + + def close_window(self,a=None,b=None): + self.text_settings.close_window(a,b) + self.voice_settings.close_window(a,b) + self.core_settings.close_window(a,b) + self.hide() + return True + + def present(self): + self.voice_settings.present() + self.text_settings.present() + self.core_settings.present() + self.show_all() \ No newline at end of file diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 96115d0..2e40128 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -10,7 +10,7 @@ import logging class TextSettingsWindow(SettingsWindow): def __init__(self, overlay): - Gtk.Window.__init__(self) + Gtk.VBox.__init__(self) self.overlay = overlay self.set_size_request(400, 200) self.connect("destroy", self.close_window) diff --git a/discover_overlay/voice_settings.py b/discover_overlay/voice_settings.py index 2cda7d8..aea4051 100644 --- a/discover_overlay/voice_settings.py +++ b/discover_overlay/voice_settings.py @@ -10,7 +10,7 @@ import logging class VoiceSettingsWindow(SettingsWindow): def __init__(self, overlay): - Gtk.Window.__init__(self) + Gtk.VBox.__init__(self) self.overlay = overlay self.set_size_request(400, 200) self.connect("destroy", self.close_window) From a31062251c0343a7d7a5ec5a6577a07783c35c1d Mon Sep 17 00:00:00 2001 From: trigg Date: Tue, 13 Oct 2020 14:37:45 +0000 Subject: [PATCH 28/77] - Detect Wayland & throw extra flags at it. --- discover_overlay/overlay.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/discover_overlay/overlay.py b/discover_overlay/overlay.py index 72bf7a9..c165001 100644 --- a/discover_overlay/overlay.py +++ b/discover_overlay/overlay.py @@ -7,8 +7,19 @@ import sys class OverlayWindow(Gtk.Window): + def detect_type(self): + window = Gtk.Window() + screen = window.get_screen() + screen_type = "%s" % (screen) + if "Wayland" in screen_type: + print("Using Wayland GDK. Expect bugs") + return Gtk.WindowType.TOPLEVEL + return Gtk.WindowType.POPUP + def __init__(self): - Gtk.Window.__init__(self, type=Gtk.WindowType.POPUP) + Gtk.Window.__init__(self, type=self.detect_type()) + screen = self.get_screen() + screen_type = "%s" % (screen) self.set_size_request(50, 50) self.connect('draw', self.draw) @@ -16,6 +27,7 @@ class OverlayWindow(Gtk.Window): self.compositing = False # Set RGBA screen = self.get_screen() + screen_type = "%s" % (screen) visual = screen.get_rgba_visual() if not self.get_display().supports_input_shapes(): logging.info( @@ -31,6 +43,9 @@ class OverlayWindow(Gtk.Window): self.set_untouchable() self.set_skip_pager_hint(True) self.set_skip_taskbar_hint(True) + self.set_keep_above(True) + self.set_decorated(True) + self.set_accept_focus(False) self.show_all() self.monitor = 0 @@ -137,4 +152,4 @@ class OverlayWindow(Gtk.Window): self.context.set_source_rgba(c[0], c[1], c[2], c[3] * a) def set_force_xshape(self, force): - self.force_xshape = force \ No newline at end of file + self.force_xshape = force From 0868a351a3a06239f11c83144eccff4b507ad05b Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Wed, 14 Oct 2020 12:25:10 -0700 Subject: [PATCH 29/77] Copy and tweak channel selection box to use for guild selection --- discover_overlay/text_settings.py | 46 ++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 2e40128..5715775 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -254,6 +254,16 @@ class TextSettingsWindow(SettingsWindow): channel.add_attribute(rt, "text", 0) channel.add_attribute(rt, 'sensitive', 1) + guild_label = Gtk.Label.new("Server") + guild = Gtk.ComboBox.new() + + guild.connect("changed", self.change_guild) + guild_rt = Gtk.CellRendererText() + #guild.set_row_separator_func(lambda model, path: model[path][1]) + guild.pack_start(rt, True) + guild.add_attribute(rt, "text", 0) + guild.add_attribute(rt, 'sensitive', 1) + # Show Attachments show_attach_label = Gtk.Label.new("Show Attachments") show_attach = Gtk.CheckButton.new() @@ -264,6 +274,7 @@ class TextSettingsWindow(SettingsWindow): self.align_y_widget = align_y self.align_monitor_widget = monitor self.align_placement_widget = align_placement_button + self.guild_widget = guild self.channel_widget = channel self.text_time_widget = text_time self.text_time_label_widget = text_time_label @@ -274,22 +285,25 @@ class TextSettingsWindow(SettingsWindow): box.attach(popup_style, 1, 1, 1, 1) box.attach(text_time_label, 0, 2, 1, 1) box.attach(text_time, 1, 2, 1, 1) - box.attach(channel_label, 0, 3, 1, 1) - box.attach(channel, 1, 3, 1, 1) - box.attach(font_label, 0, 4, 1, 1) - box.attach(font, 1, 4, 1, 1) - box.attach(fg_col_label, 0, 5, 1, 1) - box.attach(fg_col, 1, 5, 1, 1) - box.attach(bg_col_label, 0, 6, 1, 1) - box.attach(bg_col, 1, 6, 1, 1) - box.attach(align_label, 0, 7, 1, 5) - #box.attach(align_type_box, 1, 7, 1, 1) - box.attach(monitor, 1, 8, 1, 1) - box.attach(align_x, 1, 9, 1, 1) - box.attach(align_y, 1, 10, 1, 1) - box.attach(align_placement_button, 1, 11, 1, 1) - box.attach(show_attach_label, 0, 12, 1, 1) - box.attach(show_attach, 1, 12, 1, 1) + box.attach(guild_label, 0, 3, 1, 1) + box.attach(guild, 1, 3, 1, 1) + + box.attach(channel_label, 0, 4, 1, 1) + box.attach(channel, 1, 4, 1, 1) + box.attach(font_label, 0, 5, 1, 1) + box.attach(font, 1, 5, 1, 1) + box.attach(fg_col_label, 0, 6, 1, 1) + box.attach(fg_col, 1, 6, 1, 1) + box.attach(bg_col_label, 0, 7, 1, 1) + box.attach(bg_col, 1, 7, 1, 1) + box.attach(align_label, 0, 8, 1, 5) + #box.attach(align_type_box, 1, 8, 1, 1) + box.attach(monitor, 1, 9, 1, 1) + box.attach(align_x, 1, 10, 1, 1) + box.attach(align_y, 1, 11, 1, 1) + box.attach(align_placement_button, 1, 12, 1, 1) + box.attach(show_attach_label, 0, 13, 1, 1) + box.attach(show_attach, 1, 13, 1, 1) self.add(box) From 8f6c8690cf0958989c362864a8c0f9c9be46ec02 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Wed, 14 Oct 2020 12:25:56 -0700 Subject: [PATCH 30/77] add guild option to config --- discover_overlay/text_settings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 5715775..9fae97a 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -96,6 +96,7 @@ class TextSettingsWindow(SettingsWindow): self.floating_w = config.getint("text", "floating_w", fallback=400) self.floating_h = config.getint("text", "floating_h", fallback=400) self.channel = config.get("text", "channel", fallback="0") + self.guild = config.get("text", "guild", fallback="0") self.font = config.get("text", "font", fallback=None) self.bg_col = json.loads(config.get( "text", "bg_col", fallback="[0.0,0.0,0.0,0.5]")) @@ -139,6 +140,7 @@ class TextSettingsWindow(SettingsWindow): config.set("text", "floating_w", "%s" % (self.floating_w)) config.set("text", "floating_h", "%s" % (self.floating_h)) config.set("text", "channel", self.channel) + config.set("text", "guild", self.guild) config.set("text", "bg_col", json.dumps(self.bg_col)) config.set("text", "fg_col", json.dumps(self.fg_col)) config.set("text", "popup_style", "%s" % (int(self.popup_style))) From 75a25f3ec4d5a0e0f4ce3b9ee4d8a8906f779656 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Wed, 14 Oct 2020 12:27:10 -0700 Subject: [PATCH 31/77] duplicate and tweak `change_channel` to use as `change_guild` --- discover_overlay/text_settings.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 9fae97a..8526c5f 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -20,6 +20,7 @@ class TextSettingsWindow(SettingsWindow): self.list_channels_keys = [] self.list_channels = {} self.ignore_channel_change = False + self.ignore_guild_change = False self.create_gui() def present(self): @@ -326,6 +327,21 @@ class TextSettingsWindow(SettingsWindow): c = self.channel_lookup[button.get_active()] self.channel = c self.save_config() + + + def change_guild(self, button): + if self.ignore_guild_change: + return + + g = self.guild if self.guild != "0" else "0" + for guild in self.guild_list(): + guild_id, guild_name = guild + selected = button.get_active() + if selected == guild_name: + g = selected + + self.guild = g + self.save_config() def change_placement(self, button): if self.placement_window: From c1ac0fe0a01f54cdb49b7d8b072b61c4a137477d Mon Sep 17 00:00:00 2001 From: trigg Date: Fri, 16 Oct 2020 12:10:27 +0000 Subject: [PATCH 32/77] - Force latest python-pidfile --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 22f6fa0..269646a 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,7 @@ setup( 'websocket-client', 'pyxdg', 'requests', - 'python-pidfile', + 'python-pidfile>=3.0.0', 'pillow', ], entry_points={ From 73be243bc0f731c85ae5be762f04e0d163fa9ee1 Mon Sep 17 00:00:00 2001 From: trigg Date: Sat, 17 Oct 2020 16:01:13 +0000 Subject: [PATCH 33/77] - Fixed #85 --- discover_overlay/overlay.py | 2 -- discover_overlay/text_overlay.py | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/discover_overlay/overlay.py b/discover_overlay/overlay.py index c165001..edaf794 100644 --- a/discover_overlay/overlay.py +++ b/discover_overlay/overlay.py @@ -19,7 +19,6 @@ class OverlayWindow(Gtk.Window): def __init__(self): Gtk.Window.__init__(self, type=self.detect_type()) screen = self.get_screen() - screen_type = "%s" % (screen) self.set_size_request(50, 50) self.connect('draw', self.draw) @@ -27,7 +26,6 @@ class OverlayWindow(Gtk.Window): self.compositing = False # Set RGBA screen = self.get_screen() - screen_type = "%s" % (screen) visual = screen.get_rgba_visual() if not self.get_display().supports_input_shapes(): logging.info( diff --git a/discover_overlay/text_overlay.py b/discover_overlay/text_overlay.py index 7ec6692..29d2b82 100644 --- a/discover_overlay/text_overlay.py +++ b/discover_overlay/text_overlay.py @@ -96,7 +96,7 @@ class TextOverlayWindow(OverlayWindow): ret = "`" elif msg['type'] == 'inlineCode' or msg['type'] == 'codeBlock' or msg['type'] == 'blockQuote': ret = "%s" % ( - msg['content']) + self.make_line(msg['content'])) elif msg['type'] == 'u': ret = "%s" % (self.make_line(msg['content'])) elif msg['type'] == 'em': @@ -110,7 +110,7 @@ class TextOverlayWindow(OverlayWindow): elif msg['type'] == 'br': ret = '\n' else: - logging.warning("Unknown text type : %s" % (msg["type"])) + logging.error("Unknown text type : %s" % (msg["type"])) return ret def recv_attach(self, id, pix): From 1bd27b25068ebb0be87984f0cc312314637441fc Mon Sep 17 00:00:00 2001 From: trigg Date: Sat, 17 Oct 2020 17:06:34 +0000 Subject: [PATCH 34/77] - Subscribe less greedily. We'll need to ensure we subscribe when we need them now! --- discover_overlay/discord_connector.py | 13 +++++++++++-- discover_overlay/discover_overlay.py | 1 + discover_overlay/settings_window.py | 1 + discover_overlay/text_overlay.py | 1 + discover_overlay/text_settings.py | 7 +++++++ discover_overlay/voice_overlay.py | 7 ++++--- 6 files changed, 25 insertions(+), 5 deletions(-) diff --git a/discover_overlay/discord_connector.py b/discover_overlay/discord_connector.py index 09ee2a5..56e2dae 100644 --- a/discover_overlay/discord_connector.py +++ b/discover_overlay/discord_connector.py @@ -35,6 +35,7 @@ class DiscordConnector: self.last_connection = "" self.text = [] self.authed = False + self.last_text_channel = None def get_access_token_stage1(self): self.ws.send("{\"cmd\":\"AUTHORIZE\",\"args\":{\"client_id\":\"%s\",\"scopes\":[\"rpc\",\"messages.read\"],\"prompt\":\"none\"},\"nonce\":\"deadbeef\"}" % ( @@ -262,8 +263,8 @@ class DiscordConnector: if channel["type"] == 2: self.req_channel_details(channel["id"]) self.check_guilds() - self.sub_all_voice_guild(j["nonce"]) - self.sub_all_text_guild(j["nonce"]) + #self.sub_all_voice_guild(j["nonce"]) + #self.sub_all_text_guild(j["nonce"]) return elif j["cmd"] == "SUBSCRIBE": return @@ -308,6 +309,8 @@ class DiscordConnector: u"%s: %s" % (guild["name"], channels)) self.sub_server() self.find_user() + if self.last_text_channel: + self.sub_text_channel(self.last_text_channel) def on_error(self, error): logging.error("ERROR : %s" % (error)) @@ -430,6 +433,12 @@ class DiscordConnector: return True return True + def start_listening_text(self, ch): + if self.ws: + self.sub_text_channel(ch) + else: + self.last_text_channel = ch + def connect(self): if self.ws: return diff --git a/discover_overlay/discover_overlay.py b/discover_overlay/discover_overlay.py index 4558aff..54916ab 100755 --- a/discover_overlay/discover_overlay.py +++ b/discover_overlay/discover_overlay.py @@ -35,6 +35,7 @@ class Discover: self.connection = DiscordConnector( self.settings.text_settings, self.settings.voice_settings, self.text_overlay, self.voice_overlay) + self.settings.text_settings.add_connector(self.connection) self.connection.connect() GLib.timeout_add((1000 / 60), self.connection.do_read) self.rpc_file = rpc_file diff --git a/discover_overlay/settings_window.py b/discover_overlay/settings_window.py index c088581..d0952f1 100644 --- a/discover_overlay/settings_window.py +++ b/discover_overlay/settings_window.py @@ -19,6 +19,7 @@ class MainSettingsWindow(Gtk.Window): self.text_overlay = text_overlay self.voice_overlay = voice_overlay + self.set_title("Discover Overlay Configuration") # Create nb = Gtk.Notebook() diff --git a/discover_overlay/text_overlay.py b/discover_overlay/text_overlay.py index 29d2b82..37460a1 100644 --- a/discover_overlay/text_overlay.py +++ b/discover_overlay/text_overlay.py @@ -31,6 +31,7 @@ class TextOverlayWindow(OverlayWindow): self.imgList = [] self.imgFinder = re.compile(r"`") + self.set_title("Discover Text") def set_text_time(self, t): self.text_time = t diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 2e40128..1091f99 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -22,6 +22,11 @@ class TextSettingsWindow(SettingsWindow): self.ignore_channel_change = False self.create_gui() + def add_connector(self, conn): + self.connector = conn + if self.channel: + self.connector.start_listening_text(self.channel) + def present(self): self.show_all() if not self.floating: @@ -307,7 +312,9 @@ class TextSettingsWindow(SettingsWindow): def change_channel(self, button): if self.ignore_channel_change: return + c = self.channel_lookup[button.get_active()] + self.connector.start_listening_text(c) self.channel = c self.save_config() diff --git a/discover_overlay/voice_overlay.py b/discover_overlay/voice_overlay.py index 9503c19..edb7b18 100644 --- a/discover_overlay/voice_overlay.py +++ b/discover_overlay/voice_overlay.py @@ -36,9 +36,10 @@ class VoiceOverlayWindow(OverlayWindow): self.users_to_draw = [] self.connected = False self.force_location() - self.def_avatar = get_surface(self.recv_avatar, - "https://cdn.discordapp.com/embed/avatars/3.png", - 'def', self.avatar_size) + get_surface(self.recv_avatar, + "https://cdn.discordapp.com/embed/avatars/3.png", + 'def', self.avatar_size) + self.set_title("Discover Voice") def set_bg(self, bg): self.norm_col = bg From bac4131a0edad963121ef347872c9dfcaa641fb9 Mon Sep 17 00:00:00 2001 From: Triggerhapp Date: Sat, 17 Oct 2020 22:41:37 +0100 Subject: [PATCH 35/77] - Subscribe to voice events when joining a voice room --- discover_overlay/discord_connector.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/discover_overlay/discord_connector.py b/discover_overlay/discord_connector.py index 56e2dae..e355c80 100644 --- a/discover_overlay/discord_connector.py +++ b/discover_overlay/discord_connector.py @@ -63,6 +63,7 @@ class DiscordConnector: cn = self.channels[channel]['name'] logging.info( "Joined room: %s" % (cn)) + self.sub_voice_channel(channel) self.current_voice = channel if need_req: self.req_channel_details(channel) @@ -201,7 +202,7 @@ class DiscordConnector: self.set_in_room(j["data"]["user"]["id"], False) if j["data"]["user"]["id"] == self.user["id"]: self.in_room = [] - self.sub_all_voice() + #self.sub_all_voice() else: un = j["data"]["user"]["username"] elif j["evt"] == "SPEAKING_START": From 741edc96d43b1a9486af3b36e71af69332c9590c Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:04:26 -0700 Subject: [PATCH 36/77] rename channel model temp variable to c_model --- discover_overlay/text_settings.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 8526c5f..7b08733 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -43,20 +43,20 @@ class TextSettingsWindow(SettingsWindow): self.text_time_widget.hide() self.text_time_label_widget.hide() - model = Gtk.ListStore(str, bool) + c_model = Gtk.ListStore(str, bool) self.channel_lookup = [] for guild in self.guild_list(): guild_id, guild_name = guild self.channel_lookup.append('0') - model.append([guild_name, False]) + c_model.append([guild_name, False]) for c in self.list_channels_keys: chan = self.list_channels[c] if chan['guild_id'] == guild_id: - model.append([chan["name"], True]) + c_model.append([chan["name"], True]) self.channel_lookup.append(c) - self.channel_widget.set_model(model) - self.channel_model = model + self.channel_widget.set_model(c_model) + self.channel_model = c_model idx = 0 for c in self.channel_lookup: From 5a907309a099ea935864cefd0eb7c9b8c8cbefc5 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:07:13 -0700 Subject: [PATCH 37/77] create and populate g_model and guild_lookup --- discover_overlay/text_settings.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 7b08733..6d9552d 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -44,11 +44,16 @@ class TextSettingsWindow(SettingsWindow): self.text_time_label_widget.hide() c_model = Gtk.ListStore(str, bool) + g_model = Gtk.ListStore(str, bool) self.channel_lookup = [] + self.guild_lookup = ["0"] + for guild in self.guild_list(): guild_id, guild_name = guild self.channel_lookup.append('0') c_model.append([guild_name, False]) + self.guild_lookup.append(guild) + g_model.append([guild_name, True]) for c in self.list_channels_keys: chan = self.list_channels[c] if chan['guild_id'] == guild_id: From 59d9b877c9dcd95ff77a52ff359ebad6c1015966 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:07:33 -0700 Subject: [PATCH 38/77] set the guild model for the guild widget/UI --- discover_overlay/text_settings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 6d9552d..890de52 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -60,6 +60,8 @@ class TextSettingsWindow(SettingsWindow): c_model.append([chan["name"], True]) self.channel_lookup.append(c) + self.guild_widget.set_model(g_model) + self.guild_model = g_model self.channel_widget.set_model(c_model) self.channel_model = c_model From e145437c62fe7f42e673b95002627a6dfee6255b Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:09:15 -0700 Subject: [PATCH 39/77] populate the channel model with only channels from the selected guild (if there is one) --- discover_overlay/text_settings.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 890de52..36535d1 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -51,12 +51,19 @@ class TextSettingsWindow(SettingsWindow): for guild in self.guild_list(): guild_id, guild_name = guild self.channel_lookup.append('0') - c_model.append([guild_name, False]) self.guild_lookup.append(guild) g_model.append([guild_name, True]) + + if self.guild == "0": + c_model.append([guild_name, False]) + guilds_by_id = guild_id + else: + guilds_by_id = self.guild + + for c in self.list_channels_keys: chan = self.list_channels[c] - if chan['guild_id'] == guild_id: + if chan['guild_id'] == guilds_by_id: c_model.append([chan["name"], True]) self.channel_lookup.append(c) From fbd3c5b28eaa9afe2861728aa7c538af326d9ab3 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:10:07 -0700 Subject: [PATCH 40/77] prepopoulate the selected guild in the dropdown if one is already selected --- discover_overlay/text_settings.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 36535d1..a315376 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -81,6 +81,15 @@ class TextSettingsWindow(SettingsWindow): break idx += 1 + idxg = 0 + for g in self.guild_lookup: + if g == self.guild: + self.ignore_guild_change = True + self.guild_widget.set_active(idxg) + self.ignore_guild_change = False + break + idxg += 1 + def guild_list(self): guilds = [] done = [] From d663886670608ac0e01c3bea9d8baa7a3f5e3c3e Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:10:58 -0700 Subject: [PATCH 41/77] create class-level guild lists for more lookup --- discover_overlay/text_settings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index a315376..5028b8a 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -19,6 +19,8 @@ class TextSettingsWindow(SettingsWindow): self.init_config() self.list_channels_keys = [] self.list_channels = {} + self.list_guilds_keys = [] + self.list_guilds = {} self.ignore_channel_change = False self.ignore_guild_change = False self.create_gui() From 7fb5e45b09d2ed2089a1ff1da4c98be37472b877 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:11:40 -0700 Subject: [PATCH 42/77] change copy-pasted guild_list function to look up guilds not channels --- discover_overlay/text_settings.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 5028b8a..03ca804 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -95,10 +95,10 @@ class TextSettingsWindow(SettingsWindow): def guild_list(self): guilds = [] done = [] - for channel in self.list_channels.values(): - if not channel["guild_id"] in done: - done.append(channel["guild_id"]) - guilds.append([channel["guild_id"], channel["guild_name"]]) + for guild in self.list_guilds.values(): + if not guild["id"] in done: + done.append(guild["id"]) + guilds.append([guild["id"], guild["name"]]) return guilds def set_channels(self, in_list): From 8e5232ef80e0b497e3c6b62bf17cce416a1603f4 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:12:12 -0700 Subject: [PATCH 43/77] create a function for populating top-level guild lookup lists --- discover_overlay/text_settings.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 03ca804..295005a 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -108,6 +108,13 @@ class TextSettingsWindow(SettingsWindow): if in_list[key]["type"] == 0: self.list_channels_keys.append(key) self.list_channels_keys.sort() + + def set_guilds(self, in_list): + self.list_guilds = in_list + self.list_guilds_keys = [] + for key in in_list.keys(): + self.list_guilds_keys.append(key) + self.list_guilds_keys.sort() def read_config(self): config = ConfigParser(interpolation=None) From cde125874ce31bbfbaeafe237179ec7923df4800 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:12:39 -0700 Subject: [PATCH 44/77] call the function to populate the top level lists --- discover_overlay/discord_connector.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/discover_overlay/discord_connector.py b/discover_overlay/discord_connector.py index 09ee2a5..f979a62 100644 --- a/discover_overlay/discord_connector.py +++ b/discover_overlay/discord_connector.py @@ -413,6 +413,8 @@ class DiscordConnector: self.text_altered = False # Update text channels self.text_settings.set_channels(self.channels) + # Update guilds + self.text_settings.set_guilds(self.guilds) # Check for changed channel if self.authed: self.set_text_channel(self.text_settings.get_channel()) From b1115a3fe442c8e4b7cd63786edba17121f70439 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:12:56 -0700 Subject: [PATCH 45/77] simplify guild lookup when changing guilds --- discover_overlay/text_settings.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 295005a..2819869 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -364,14 +364,7 @@ class TextSettingsWindow(SettingsWindow): def change_guild(self, button): if self.ignore_guild_change: return - - g = self.guild if self.guild != "0" else "0" - for guild in self.guild_list(): - guild_id, guild_name = guild - selected = button.get_active() - if selected == guild_name: - g = selected - + g = self.guild_lookup[button.get_active()] self.guild = g self.save_config() From 7dd5a44c70ba4a8357179a4c5fba86e55c52320e Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:13:22 -0700 Subject: [PATCH 46/77] link to documentation explaining the magic number for channel type --- discover_overlay/text_settings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 2819869..5057c0b 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -105,6 +105,8 @@ class TextSettingsWindow(SettingsWindow): self.list_channels = in_list self.list_channels_keys = [] for key in in_list.keys(): + # filter for only text channels + # https://discord.com/developers/docs/resources/channel#channel-object-channel-types if in_list[key]["type"] == 0: self.list_channels_keys.append(key) self.list_channels_keys.sort() From b1adea41991c344fa2a78eb132251905623d4f8b Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:30:08 -0700 Subject: [PATCH 47/77] fix guild selection not populating previously selected value --- discover_overlay/text_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 5057c0b..12ff921 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -85,7 +85,7 @@ class TextSettingsWindow(SettingsWindow): idxg = 0 for g in self.guild_lookup: - if g == self.guild: + if g[0] == self.guild: self.ignore_guild_change = True self.guild_widget.set_active(idxg) self.ignore_guild_change = False From e11ba8eb96ff98ddb19c7c50e8822e4e429abb52 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:30:28 -0700 Subject: [PATCH 48/77] set the guild as well if guild and channel do not match --- discover_overlay/text_settings.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 12ff921..7ed642e 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -360,6 +360,9 @@ class TextSettingsWindow(SettingsWindow): return c = self.channel_lookup[button.get_active()] self.channel = c + # if the channel is not from the current guild, set the guild too + if c["guild_id"] != self.guild: + self.guild = c["guild_id"] self.save_config() From f6da14636a188bca6703967512d168635fcf3c35 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:30:51 -0700 Subject: [PATCH 49/77] remove needless appending of "0" to channel_lookup --- discover_overlay/text_settings.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 7ed642e..dbb328d 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -47,12 +47,11 @@ class TextSettingsWindow(SettingsWindow): c_model = Gtk.ListStore(str, bool) g_model = Gtk.ListStore(str, bool) - self.channel_lookup = [] + self.channel_lookup = ["0"] self.guild_lookup = ["0"] for guild in self.guild_list(): guild_id, guild_name = guild - self.channel_lookup.append('0') self.guild_lookup.append(guild) g_model.append([guild_name, True]) From 52d3d39241e3cadc944e5085173e4b0b58c0ef64 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:31:45 -0700 Subject: [PATCH 50/77] set the guild's id as the config value because lists arent allowed and this is apparently a list --- discover_overlay/text_settings.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index dbb328d..a00aef3 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -368,8 +368,9 @@ class TextSettingsWindow(SettingsWindow): def change_guild(self, button): if self.ignore_guild_change: return - g = self.guild_lookup[button.get_active()] - self.guild = g + g = self.guild_lookup[button.get_active()] + # get the guilds ID because config values must be strings + self.guild = g[0] self.save_config() def change_placement(self, button): From 866145e61e18e5b0de8e483ef33f49a529cdef82 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:32:14 -0700 Subject: [PATCH 51/77] set a default value for guilds_by_id middleman variable so that it has the right scope (?) --- discover_overlay/text_settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index a00aef3..896c67c 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -55,6 +55,7 @@ class TextSettingsWindow(SettingsWindow): self.guild_lookup.append(guild) g_model.append([guild_name, True]) + guilds_by_id = "0" if self.guild == "0": c_model.append([guild_name, False]) guilds_by_id = guild_id From d45065a51cabe03a3d05455fa438259102fb387b Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:42:46 -0700 Subject: [PATCH 52/77] create a constant to store the default guild id --- discover_overlay/text_settings.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 896c67c..cfa92c0 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -7,6 +7,7 @@ from .settings import SettingsWindow from gi.repository import Gtk, Gdk, Pango import logging +GUILD_DEFAULT_VALUE = "0" class TextSettingsWindow(SettingsWindow): def __init__(self, overlay): @@ -48,7 +49,7 @@ class TextSettingsWindow(SettingsWindow): c_model = Gtk.ListStore(str, bool) g_model = Gtk.ListStore(str, bool) self.channel_lookup = ["0"] - self.guild_lookup = ["0"] + self.guild_lookup = [GUILD_DEFAULT_VALUE] for guild in self.guild_list(): guild_id, guild_name = guild @@ -56,7 +57,7 @@ class TextSettingsWindow(SettingsWindow): g_model.append([guild_name, True]) guilds_by_id = "0" - if self.guild == "0": + if self.guild == GUILD_DEFAULT_VALUE: c_model.append([guild_name, False]) guilds_by_id = guild_id else: @@ -131,7 +132,7 @@ class TextSettingsWindow(SettingsWindow): self.floating_w = config.getint("text", "floating_w", fallback=400) self.floating_h = config.getint("text", "floating_h", fallback=400) self.channel = config.get("text", "channel", fallback="0") - self.guild = config.get("text", "guild", fallback="0") + self.guild = config.get("text", "guild", fallback=GUILD_DEFAULT_VALUE) self.font = config.get("text", "font", fallback=None) self.bg_col = json.loads(config.get( "text", "bg_col", fallback="[0.0,0.0,0.0,0.5]")) From 11c8b257d196e8992c107a3c762c0989e5e59aa6 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:45:38 -0700 Subject: [PATCH 53/77] fix duplicate channels in channel list for one guild --- discover_overlay/text_settings.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index cfa92c0..3464e36 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -56,17 +56,20 @@ class TextSettingsWindow(SettingsWindow): self.guild_lookup.append(guild) g_model.append([guild_name, True]) - guilds_by_id = "0" + # if no guild is specified, poulate channel list with every channel from each guild if self.guild == GUILD_DEFAULT_VALUE: c_model.append([guild_name, False]) - guilds_by_id = guild_id - else: - guilds_by_id = self.guild - - + for c in self.list_channels_keys: + chan = self.list_channels[c] + if chan['guild_id'] == guild_id: + c_model.append([chan["name"], True]) + self.channel_lookup.append(c) + + # if a guild is specified, poulate channel list with every channel from *just that guild* + if self.guild != GUILD_DEFAULT_VALUE: for c in self.list_channels_keys: chan = self.list_channels[c] - if chan['guild_id'] == guilds_by_id: + if chan['guild_id'] == self.guild: c_model.append([chan["name"], True]) self.channel_lookup.append(c) From 145586a85ea40f3b75a61962e95edd5fa6d2f2ad Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:46:02 -0700 Subject: [PATCH 54/77] correctly fetch the guild ID for a channel when setting it in change_channel --- discover_overlay/text_settings.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 3464e36..46d0196 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -364,9 +364,10 @@ class TextSettingsWindow(SettingsWindow): return c = self.channel_lookup[button.get_active()] self.channel = c + channel_guild = self.list_channels[c]["guild_id"] # if the channel is not from the current guild, set the guild too - if c["guild_id"] != self.guild: - self.guild = c["guild_id"] + if channel_guild != self.guild: + self.guild = channel_guild self.save_config() From 3bafb21ab3675831437a2ff90999efb278b929ff Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:57:56 -0700 Subject: [PATCH 55/77] create update_channel_model function to update the channel selections when the guild is changed --- discover_overlay/text_settings.py | 32 ++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 46d0196..a6e880b 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -46,9 +46,7 @@ class TextSettingsWindow(SettingsWindow): self.text_time_widget.hide() self.text_time_label_widget.hide() - c_model = Gtk.ListStore(str, bool) g_model = Gtk.ListStore(str, bool) - self.channel_lookup = ["0"] self.guild_lookup = [GUILD_DEFAULT_VALUE] for guild in self.guild_list(): @@ -56,6 +54,25 @@ class TextSettingsWindow(SettingsWindow): self.guild_lookup.append(guild) g_model.append([guild_name, True]) + self.guild_widget.set_model(g_model) + self.guild_model = g_model + self.update_channel_model() + + idxg = 0 + for g in self.guild_lookup: + if g[0] == self.guild: + self.ignore_guild_change = True + self.guild_widget.set_active(idxg) + self.ignore_guild_change = False + break + idxg += 1 + + def update_channel_model(self): + c_model = Gtk.ListStore(str, bool) + self.channel_lookup = ["0"] + + for guild in self.guild_list(): + guild_id, guild_name = guild # if no guild is specified, poulate channel list with every channel from each guild if self.guild == GUILD_DEFAULT_VALUE: c_model.append([guild_name, False]) @@ -73,8 +90,6 @@ class TextSettingsWindow(SettingsWindow): c_model.append([chan["name"], True]) self.channel_lookup.append(c) - self.guild_widget.set_model(g_model) - self.guild_model = g_model self.channel_widget.set_model(c_model) self.channel_model = c_model @@ -87,15 +102,6 @@ class TextSettingsWindow(SettingsWindow): break idx += 1 - idxg = 0 - for g in self.guild_lookup: - if g[0] == self.guild: - self.ignore_guild_change = True - self.guild_widget.set_active(idxg) - self.ignore_guild_change = False - break - idxg += 1 - def guild_list(self): guilds = [] done = [] From 31b7cbd32402bd4d8bfd79483db80ee301d7ad93 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:58:27 -0700 Subject: [PATCH 56/77] move update_channel_model above present() as it is called there --- discover_overlay/text_settings.py | 71 ++++++++++++++++--------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index a6e880b..b821f03 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -26,6 +26,42 @@ class TextSettingsWindow(SettingsWindow): self.ignore_guild_change = False self.create_gui() + def update_channel_model(self): + c_model = Gtk.ListStore(str, bool) + self.channel_lookup = ["0"] + + for guild in self.guild_list(): + guild_id, guild_name = guild + # if no guild is specified, poulate channel list with every channel from each guild + if self.guild == GUILD_DEFAULT_VALUE: + c_model.append([guild_name, False]) + for c in self.list_channels_keys: + chan = self.list_channels[c] + if chan['guild_id'] == guild_id: + c_model.append([chan["name"], True]) + self.channel_lookup.append(c) + + # if a guild is specified, poulate channel list with every channel from *just that guild* + if self.guild != GUILD_DEFAULT_VALUE: + for c in self.list_channels_keys: + chan = self.list_channels[c] + if chan['guild_id'] == self.guild: + c_model.append([chan["name"], True]) + self.channel_lookup.append(c) + + self.channel_widget.set_model(c_model) + self.channel_model = c_model + + idx = 0 + for c in self.channel_lookup: + if c == self.channel: + self.ignore_channel_change = True + self.channel_widget.set_active(idx) + self.ignore_channel_change = False + break + idx += 1 + + def present(self): self.show_all() if not self.floating: @@ -67,41 +103,6 @@ class TextSettingsWindow(SettingsWindow): break idxg += 1 - def update_channel_model(self): - c_model = Gtk.ListStore(str, bool) - self.channel_lookup = ["0"] - - for guild in self.guild_list(): - guild_id, guild_name = guild - # if no guild is specified, poulate channel list with every channel from each guild - if self.guild == GUILD_DEFAULT_VALUE: - c_model.append([guild_name, False]) - for c in self.list_channels_keys: - chan = self.list_channels[c] - if chan['guild_id'] == guild_id: - c_model.append([chan["name"], True]) - self.channel_lookup.append(c) - - # if a guild is specified, poulate channel list with every channel from *just that guild* - if self.guild != GUILD_DEFAULT_VALUE: - for c in self.list_channels_keys: - chan = self.list_channels[c] - if chan['guild_id'] == self.guild: - c_model.append([chan["name"], True]) - self.channel_lookup.append(c) - - self.channel_widget.set_model(c_model) - self.channel_model = c_model - - idx = 0 - for c in self.channel_lookup: - if c == self.channel: - self.ignore_channel_change = True - self.channel_widget.set_active(idx) - self.ignore_channel_change = False - break - idx += 1 - def guild_list(self): guilds = [] done = [] From 9f7d0b44e950af157984281f664b24fc4d7281f5 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 17:25:09 -0700 Subject: [PATCH 57/77] fix consistency of guild_lookup data --- discover_overlay/text_settings.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index b821f03..0084431 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -87,7 +87,7 @@ class TextSettingsWindow(SettingsWindow): for guild in self.guild_list(): guild_id, guild_name = guild - self.guild_lookup.append(guild) + self.guild_lookup.append(guild_id) g_model.append([guild_name, True]) self.guild_widget.set_model(g_model) @@ -95,8 +95,8 @@ class TextSettingsWindow(SettingsWindow): self.update_channel_model() idxg = 0 - for g in self.guild_lookup: - if g[0] == self.guild: + for guild_id in self.guild_lookup: + if guild_id == self.guild: self.ignore_guild_change = True self.guild_widget.set_active(idxg) self.ignore_guild_change = False @@ -381,9 +381,8 @@ class TextSettingsWindow(SettingsWindow): def change_guild(self, button): if self.ignore_guild_change: return - g = self.guild_lookup[button.get_active()] - # get the guilds ID because config values must be strings - self.guild = g[0] + guild_id = self.guild_lookup[button.get_active()] + self.guild = guild_id self.save_config() def change_placement(self, button): From 87df7c85cabf405044f65723778166156e375e64 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 19:05:05 -0700 Subject: [PATCH 58/77] update comments --- discover_overlay/text_settings.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 0084431..96af101 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -27,12 +27,14 @@ class TextSettingsWindow(SettingsWindow): self.create_gui() def update_channel_model(self): + # potentially organize channels by their group/parent_id + # https://discord.com/developers/docs/resources/channel#channel-object-channel-structure c_model = Gtk.ListStore(str, bool) self.channel_lookup = ["0"] for guild in self.guild_list(): guild_id, guild_name = guild - # if no guild is specified, poulate channel list with every channel from each guild + # if no guild is specified, populate channel list with every channel from each guild if self.guild == GUILD_DEFAULT_VALUE: c_model.append([guild_name, False]) for c in self.list_channels_keys: From 1215e6f5613496ab2ef8709a6cfeab74eac80eab Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 19:05:39 -0700 Subject: [PATCH 59/77] fix off-by-one issue when selecting a guild --- discover_overlay/text_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 96af101..4a681a0 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -85,7 +85,7 @@ class TextSettingsWindow(SettingsWindow): self.text_time_label_widget.hide() g_model = Gtk.ListStore(str, bool) - self.guild_lookup = [GUILD_DEFAULT_VALUE] + self.guild_lookup = [] for guild in self.guild_list(): guild_id, guild_name = guild From e3bcddcf4f8838261d6dd289e87b04f78bd85e46 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 19:07:10 -0700 Subject: [PATCH 60/77] update channel list when a new server is selected --- discover_overlay/text_settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 4a681a0..28864a8 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -386,6 +386,7 @@ class TextSettingsWindow(SettingsWindow): guild_id = self.guild_lookup[button.get_active()] self.guild = guild_id self.save_config() + self.update_channel_model() def change_placement(self, button): if self.placement_window: From a20f80ac79ab4a471108895da4b02ec1f6279a7d Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 19:09:52 -0700 Subject: [PATCH 61/77] remove guild update from channel update function --- discover_overlay/text_settings.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 28864a8..f06f440 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -373,10 +373,6 @@ class TextSettingsWindow(SettingsWindow): return c = self.channel_lookup[button.get_active()] self.channel = c - channel_guild = self.list_channels[c]["guild_id"] - # if the channel is not from the current guild, set the guild too - if channel_guild != self.guild: - self.guild = channel_guild self.save_config() From 34e1f3b442ee0dab60b0ab0455a8a110b763f60a Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 20:09:30 -0700 Subject: [PATCH 62/77] fix icon not displaying when falling back to systray --- discover_overlay/discover_overlay.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discover_overlay/discover_overlay.py b/discover_overlay/discover_overlay.py index 54916ab..6a568ba 100755 --- a/discover_overlay/discover_overlay.py +++ b/discover_overlay/discover_overlay.py @@ -87,7 +87,7 @@ class Discover: except Exception as e: # Create System Tray logging.info("Falling back to Systray : %s" % (e)) - self.tray = Gtk.StatusIcon.new_from_icon_name("discover_overlay") + self.tray = Gtk.StatusIcon.new_from_icon_name("discover-overlay") self.tray.connect('popup-menu', self.show_menu) def make_menu(self): From 3222425c2b7e7bd3a0a3235e2e5d992a8d1a5b23 Mon Sep 17 00:00:00 2001 From: Adrian Edwards <17362949+MoralCode@users.noreply.github.com> Date: Sun, 18 Oct 2020 20:51:00 -0700 Subject: [PATCH 63/77] setup task manager icon too --- discover_overlay/settings_window.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/discover_overlay/settings_window.py b/discover_overlay/settings_window.py index d0952f1..bca667d 100644 --- a/discover_overlay/settings_window.py +++ b/discover_overlay/settings_window.py @@ -20,7 +20,9 @@ class MainSettingsWindow(Gtk.Window): self.text_overlay = text_overlay self.voice_overlay = voice_overlay self.set_title("Discover Overlay Configuration") - + self.set_icon_from_file("discover-overlay.png") + self.set_default_size(280, 180) + # Create nb = Gtk.Notebook() #nb.set_tab_pos(Gtk.POS_TOP) From 7c97a7d9d1faeee9a4b01edf4bf8327992b5b47f Mon Sep 17 00:00:00 2001 From: trigg Date: Mon, 19 Oct 2020 09:54:06 +0000 Subject: [PATCH 64/77] - Attempt at making wayland play nicer --- discover_overlay/overlay.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/discover_overlay/overlay.py b/discover_overlay/overlay.py index edaf794..cbd7c67 100644 --- a/discover_overlay/overlay.py +++ b/discover_overlay/overlay.py @@ -1,6 +1,6 @@ import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk +from gi.repository import Gtk, Gdk, GtkLayerShell import cairo import logging import sys @@ -44,6 +44,7 @@ class OverlayWindow(Gtk.Window): self.set_keep_above(True) self.set_decorated(True) self.set_accept_focus(False) + self.set_wayland_hax() self.show_all() self.monitor = 0 @@ -52,6 +53,10 @@ class OverlayWindow(Gtk.Window): self.floating = False self.force_xshape= False + def set_wayland_hax(self): + GtkLayerShell.init_for_window(self) + GtkLayerShell.set_layer(GtkLayerShell.Layer.TOP) + def draw(self, widget, context): pass From 7ae801ba2d64c068d33d5db257cf75edc8ff3b7a Mon Sep 17 00:00:00 2001 From: trigg Date: Mon, 19 Oct 2020 10:14:28 +0000 Subject: [PATCH 65/77] - In wlroots environment pin to all edges. Good stop-gap --- discover_overlay/overlay.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/discover_overlay/overlay.py b/discover_overlay/overlay.py index cbd7c67..8d5d101 100644 --- a/discover_overlay/overlay.py +++ b/discover_overlay/overlay.py @@ -11,7 +11,9 @@ class OverlayWindow(Gtk.Window): window = Gtk.Window() screen = window.get_screen() screen_type = "%s" % (screen) + self.is_wayland=False if "Wayland" in screen_type: + self.is_wayland=True print("Using Wayland GDK. Expect bugs") return Gtk.WindowType.TOPLEVEL return Gtk.WindowType.POPUP @@ -44,7 +46,7 @@ class OverlayWindow(Gtk.Window): self.set_keep_above(True) self.set_decorated(True) self.set_accept_focus(False) - self.set_wayland_hax() + self.set_wayland_state() self.show_all() self.monitor = 0 @@ -53,9 +55,14 @@ class OverlayWindow(Gtk.Window): self.floating = False self.force_xshape= False - def set_wayland_hax(self): - GtkLayerShell.init_for_window(self) - GtkLayerShell.set_layer(GtkLayerShell.Layer.TOP) + def set_wayland_state(self): + if self.is_wayland: + GtkLayerShell.init_for_window(self) + GtkLayerShell.set_layer(self, GtkLayerShell.Layer.TOP) + GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.LEFT, True) + GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.RIGHT, True) + GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.BOTTOM, True) + GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.TOP, True) def draw(self, widget, context): pass From c6bb3fb1239297f44287323ae9c289e7dcd0e1f4 Mon Sep 17 00:00:00 2001 From: trigg Date: Mon, 19 Oct 2020 11:47:59 +0000 Subject: [PATCH 66/77] - Created window placement window for wlroots env --- discover_overlay/draggable_window.py | 8 +- discover_overlay/draggable_window_wayland.py | 137 +++++++++++++++++++ discover_overlay/overlay.py | 63 +++++---- discover_overlay/text_overlay.py | 32 +++-- discover_overlay/text_settings.py | 30 ++-- discover_overlay/voice_overlay.py | 29 ++-- discover_overlay/voice_settings.py | 25 ++-- 7 files changed, 261 insertions(+), 63 deletions(-) create mode 100644 discover_overlay/draggable_window_wayland.py diff --git a/discover_overlay/draggable_window.py b/discover_overlay/draggable_window.py index e277dcc..3432594 100644 --- a/discover_overlay/draggable_window.py +++ b/discover_overlay/draggable_window.py @@ -6,7 +6,7 @@ import logging class DraggableWindow(Gtk.Window): - def __init__(self, x=0, y=0, w=300, h=300, message="Message"): + def __init__(self, x=0, y=0, w=300, h=300, message="Message",settings=None): Gtk.Window.__init__(self, type=Gtk.WindowType.POPUP) if w < 100: w = 100 @@ -16,6 +16,7 @@ class DraggableWindow(Gtk.Window): self.y = y self.w = w self.h = h + self.settings=settings self.message = message self.set_size_request(50, 50) @@ -127,3 +128,8 @@ class DraggableWindow(Gtk.Window): context.rectangle(0, sh - 32, sw, 32) context.fill() + + def get_coords(self): + (x, y) = self.placement_window.get_position() + (w, h) = self.placement_window.get_size() + return (x,y,w,h) diff --git a/discover_overlay/draggable_window_wayland.py b/discover_overlay/draggable_window_wayland.py new file mode 100644 index 0000000..328b360 --- /dev/null +++ b/discover_overlay/draggable_window_wayland.py @@ -0,0 +1,137 @@ +import gi +gi.require_version("Gtk", "3.0") +import cairo +from gi.repository import Gtk, Gdk, GtkLayerShell +import logging + + +class DraggableWindowWayland(Gtk.Window): + def __init__(self, x=0, y=0, w=300, h=300, message="Message", settings=None): + Gtk.Window.__init__(self, type=Gtk.WindowType.TOPLEVEL) + if w < 100: + w = 100 + if h < 100: + h = 100 + self.x = x + self.y = y + self.w = w + self.h = h + self.settings=settings + self.message = message + self.set_size_request(50, 50) + + self.connect('draw', self.draw) + self.connect('motion-notify-event', self.drag) + self.connect('button-press-event', self.button_press) + self.connect('button-release-event', self.button_release) + + self.set_app_paintable(True) + self.monitor = 0 + + self.drag_type = None + self.drag_x = 0 + self.drag_y = 0 + GtkLayerShell.init_for_window(self) + GtkLayerShell.set_layer(self, GtkLayerShell.Layer.TOP) + GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.LEFT, True) + GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.RIGHT, True) + GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.BOTTOM, True) + GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.TOP, True) + + self.show_all() + #self.force_location() + + def force_location(self): + (sx, sy)= self.get_size() + if self.x < 0: + self.x=0 + if self.y < 0: + self.y=0 + if self.x + self.w > sx: + self.x = sx - self.w + if self.y + self.h > sy: + self.y = sy - self.h + self.queue_draw() + + def drag(self, w, event): + if event.state & Gdk.ModifierType.BUTTON1_MASK: + if self.drag_type == 1: + # Center is move + self.x += event.x - self.drag_x + self.y += event.y - self.drag_y + self.drag_x = event.x + self.drag_y = event.y + + self.force_location() + elif self.drag_type == 2: + # Right edge + self.w += event.x - self.drag_x + self.drag_x = event.x + self.force_location() + elif self.drag_type == 3: + # Bottom edge + self.h += event.y - self.drag_y + self.drag_y = event.y + self.force_location() + else: + # Bottom Right + self.w += event.x - self.drag_x + self.h += event.y - self.drag_y + self.drag_x = event.x + self.drag_y = event.y + self.force_location() + + def button_press(self, w, event): + px = event.x - self.x + py = event.y - self.y + + if not self.drag_type: + self.drag_type = 1 + # Where in the window did we press? + if px < 20 and py<20: + self.settings.change_placement(None) + if py > self.h - 32: + self.drag_type += 2 + if px > self.w - 32: + self.drag_type += 1 + self.drag_x = event.x + self.drag_y = event.y + + def button_release(self, w, event): + self.drag_type = None + + def draw(self, widget, context): + context.translate(self.x, self.y) + context.save() + context.rectangle(0,0,self.w,self.h) + context.clip() + + context.set_source_rgba(1.0, 1.0, 0.0, 0.7) + # Don't layer drawing over each other, always replace + context.set_operator(cairo.OPERATOR_SOURCE) + context.paint() + # Get size of window + + # Draw text + context.set_source_rgba(0.0, 0.0, 0.0, 1.0) + xb, yb, w, h, dx, dy = context.text_extents(self.message) + context.move_to(self.w / 2 - w / 2, self.h / 2 - h / 2) + context.show_text(self.message) + + # Draw resizing edges + context.set_source_rgba(0.0, 0.0, 1.0, 0.5) + context.rectangle(self.w - 32, 0, 32, self.h) + context.fill() + + context.rectangle(0, self.h - 32, self.w, 32) + context.fill() + + # Draw Done! + context.set_source_rgba(0.0, 1.0, 0.0, 0.5) + context.rectangle(0, 0, 20,20) + context.fill() + context.restore() + + + def get_coords(self): + return (self.x,self.y,self.w,self.h) \ No newline at end of file diff --git a/discover_overlay/overlay.py b/discover_overlay/overlay.py index 8d5d101..8c0e5ef 100644 --- a/discover_overlay/overlay.py +++ b/discover_overlay/overlay.py @@ -65,7 +65,7 @@ class OverlayWindow(Gtk.Window): GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.TOP, True) def draw(self, widget, context): - pass + self.do_draw(context) def do_draw(self, context): pass @@ -98,38 +98,47 @@ class OverlayWindow(Gtk.Window): self.get_window().shape_combine_region(None, 0, 0) def force_location(self): - self.set_decorated(False) - self.set_keep_above(True) - display = Gdk.Display.get_default() - if "get_monitor" in dir(display): - monitor = display.get_monitor(self.monitor) - geometry = monitor.get_geometry() - scale_factor = monitor.get_scale_factor() - if not self.floating: - w = scale_factor * geometry.width - h = scale_factor * geometry.height - x = geometry.x - y = geometry.y - self.resize(w, h) - self.move(x, y) + if not self.is_wayland: + self.set_decorated(False) + self.set_keep_above(True) + display = Gdk.Display.get_default() + if "get_monitor" in dir(display): + monitor = display.get_monitor(self.monitor) + geometry = monitor.get_geometry() + scale_factor = monitor.get_scale_factor() + if not self.floating: + w = scale_factor * geometry.width + h = scale_factor * geometry.height + x = geometry.x + y = geometry.y + self.resize(w, h) + self.move(x, y) + else: + self.move(self.x, self.y) + self.resize(self.w, self.h) else: - self.move(self.x, self.y) - self.resize(self.w, self.h) - else: - if not self.floating: - screen = display.get_default_screen() - w = screen.width() - h = screen.height() - x = 0 - y = 0 - else: - self.move(self.x, self.y) - self.resize(self.w, self.h) + if not self.floating: + screen = display.get_default_screen() + w = screen.width() + h = screen.height() + x = 0 + y = 0 + else: + self.move(self.x, self.y) + self.resize(self.w, self.h) + if not self.floating: + (w,h) = self.get_size() + self.w = w + self.h = h self.redraw() def redraw(self): gdkwin = self.get_window() + if not self.floating: + (w,h) = self.get_size() + self.w = w + self.h = h if gdkwin: if not self.compositing or self.force_xshape: diff --git a/discover_overlay/text_overlay.py b/discover_overlay/text_overlay.py index 37460a1..5555f46 100644 --- a/discover_overlay/text_overlay.py +++ b/discover_overlay/text_overlay.py @@ -118,14 +118,30 @@ class TextOverlayWindow(OverlayWindow): self.attachment[id] = pix self.redraw() + def draw(self, widget, ctx): + self.do_draw(ctx) + def do_draw(self, context): self.context = context context.set_antialias(cairo.ANTIALIAS_GOOD) (w, h) = self.get_size() - # Make background transparent context.set_source_rgba(0.0, 0.0, 0.0, 0.0) + context.set_operator(cairo.OPERATOR_SOURCE) context.paint() + context.save() + if self.is_wayland: + # Special case! + # The window is full-screen regardless of what the user has selected. Because Wayland + # We need to set a clip and a transform to imitate original behaviour + + w = self.w + h = self.h + context.translate(self.x, self.y) + context.rectangle(0,0,w,h) + context.clip() + + cy = h tnow = time.time() @@ -155,18 +171,19 @@ class TextOverlayWindow(OverlayWindow): if cy <= 0: # We've done enough break + if self.is_wayland: + context.restore() def draw_attach(self, y, url): - (w, h) = self.get_size() if url in self.attachment and self.attachment[url]: pix = self.attachment[url] iw = pix.get_width() ih = pix.get_height() - iw = min(iw, w) - ih = min(ih, (h * .7)) + iw = min(iw, self.w) + ih = min(ih, (self.h * .7)) (ax, ay, aw, ah) = get_aspected_size(pix, iw, ih) self.col(self.bg_col) - self.context.rectangle(0, y - ah, w, ah) + self.context.rectangle(0, y - ah, self.w, ah) self.context.fill() self.context.set_operator(cairo.OPERATOR_OVER) @@ -176,13 +193,12 @@ class TextOverlayWindow(OverlayWindow): return y def draw_text(self, y, text): - (w, h) = self.get_size() layout = self.create_pango_layout(text) layout.set_markup(text, -1) attr = layout.get_attributes() - layout.set_width(Pango.SCALE * w) + layout.set_width(Pango.SCALE * self.w) layout.set_spacing(Pango.SCALE * 3) if(self.text_font): font = Pango.FontDescription( @@ -190,7 +206,7 @@ class TextOverlayWindow(OverlayWindow): layout.set_font_description(font) tw, th = layout.get_pixel_size() self.col(self.bg_col) - self.context.rectangle(0, y - th, w, th) + self.context.rectangle(0, y - th, self.w, th) self.context.fill() self.context.set_operator(cairo.OPERATOR_OVER) self.col(self.fg_col) diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 6deee9e..43f7d59 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -3,6 +3,7 @@ gi.require_version("Gtk", "3.0") import json from configparser import ConfigParser from .draggable_window import DraggableWindow +from .draggable_window_wayland import DraggableWindowWayland from .settings import SettingsWindow from gi.repository import Gtk, Gdk, Pango import logging @@ -189,10 +190,10 @@ class TextSettingsWindow(SettingsWindow): config.set("text", "monitor", self.monitor) config.set("text", "enabled", "%d" % (int(self.enabled))) config.set("text", "floating", "%s" % (int(self.floating))) - config.set("text", "floating_x", "%s" % (self.floating_x)) - config.set("text", "floating_y", "%s" % (self.floating_y)) - config.set("text", "floating_w", "%s" % (self.floating_w)) - config.set("text", "floating_h", "%s" % (self.floating_h)) + config.set("text", "floating_x", "%s" % (int(self.floating_x))) + config.set("text", "floating_y", "%s" % (int(self.floating_y))) + config.set("text", "floating_w", "%s" % (int(self.floating_w))) + config.set("text", "floating_h", "%s" % (int(self.floating_h))) config.set("text", "channel", self.channel) config.set("text", "guild", self.guild) config.set("text", "bg_col", json.dumps(self.bg_col)) @@ -394,22 +395,31 @@ class TextSettingsWindow(SettingsWindow): def change_placement(self, button): if self.placement_window: - (x, y) = self.placement_window.get_position() - (w, h) = self.placement_window.get_size() + (x,y,w,h) = self.placement_window.get_coords() self.floating_x = x self.floating_y = y self.floating_w = w self.floating_h = h self.overlay.set_floating(True, x, y, w, h) self.save_config() - button.set_label("Place Window") + if not self.overlay.is_wayland: + button.set_label("Place Window") self.placement_window.close() self.placement_window = None else: - self.placement_window = DraggableWindow( - x=self.floating_x, y=self.floating_y, w=self.floating_w, h=self.floating_h, message="Place & resize this window then press Save!") - button.set_label("Save this position") + if self.overlay.is_wayland: + self.placement_window = DraggableWindowWayland( + x=self.floating_x, y=self.floating_y, + w=self.floating_w, h=self.floating_h, + message="Place & resize this window then press Green!",settings=self) + else: + self.placement_window = DraggableWindow( + x=self.floating_x, y=self.floating_y, + w=self.floating_w, h=self.floating_h, + message="Place & resize this window then press Save!",settings=self) + if not self.overlay.is_wayland: + button.set_label("Save this position") def change_align_type_edge(self, button): if button.get_active(): diff --git a/discover_overlay/voice_overlay.py b/discover_overlay/voice_overlay.py index edb7b18..be2438d 100644 --- a/discover_overlay/voice_overlay.py +++ b/discover_overlay/voice_overlay.py @@ -144,12 +144,26 @@ class VoiceOverlayWindow(OverlayWindow): def do_draw(self, context): self.context = context context.set_antialias(cairo.ANTIALIAS_GOOD) - + # Get size of window + (w, h) = self.get_size() # Make background transparent self.set_wind_col() # Don't layer drawing over each other, always replace context.set_operator(cairo.OPERATOR_SOURCE) context.paint() + context.save() + if self.is_wayland: + # Special case! + # The window is full-screen regardless of what the user has selected. Because Wayland + # We need to set a clip and a transform to imitate original behaviour + + w = self.w + h = self.h + context.translate(self.x, self.y) + context.rectangle(0,0,w,h) + context.clip() + + context.set_operator(cairo.OPERATOR_OVER) if not self.connected: return @@ -183,8 +197,6 @@ class VoiceOverlayWindow(OverlayWindow): pass # Not in list self.users_to_draw.insert(0, self_user) - # Get size of window - (w, h) = self.get_size() # Calculate height needed to show overlay height = (len(self.users_to_draw) * self.avatar_size) + \ (len(self.users_to_draw) + 1) * self.icon_spacing @@ -203,6 +215,8 @@ class VoiceOverlayWindow(OverlayWindow): rh += self.avatar_size + self.icon_spacing # Don't hold a ref + if self.is_wayland: + context.restore() self.context = None def recv_avatar(self, id, pix): @@ -226,7 +240,6 @@ class VoiceOverlayWindow(OverlayWindow): # Set the key with no value to avoid spamming requests self.avatars[user["id"]] = None - (w, h) = self.get_size() c = None mute = False deaf = False @@ -243,14 +256,14 @@ class VoiceOverlayWindow(OverlayWindow): if self.align_right: if not self.icon_only: self.draw_text( - context, user["friendlyname"], w - self.avatar_size - self.horz_edge_padding, y) + context, user["friendlyname"], self.w - self.avatar_size - self.horz_edge_padding, y) self.draw_avatar_pix( - context, pix, w - self.avatar_size - self.horz_edge_padding, y, c) + context, pix, self.w - self.avatar_size - self.horz_edge_padding, y, c) if deaf: - self.draw_deaf(context, w - self.avatar_size - + self.draw_deaf(context, self.w - self.avatar_size - self.horz_edge_padding, y) elif mute: - self.draw_mute(context, w - self.avatar_size - + self.draw_mute(context, self.w - self.avatar_size - self.horz_edge_padding, y) else: if not self.icon_only: diff --git a/discover_overlay/voice_settings.py b/discover_overlay/voice_settings.py index aea4051..79130f7 100644 --- a/discover_overlay/voice_settings.py +++ b/discover_overlay/voice_settings.py @@ -3,6 +3,7 @@ gi.require_version("Gtk", "3.0") import json from configparser import ConfigParser from .draggable_window import DraggableWindow +from .draggable_window_wayland import DraggableWindowWayland from .settings import SettingsWindow from gi.repository import Gtk, Gdk, Pango import logging @@ -340,24 +341,30 @@ class VoiceSettingsWindow(SettingsWindow): def change_placement(self, button): if self.placement_window: - (x, y) = self.placement_window.get_position() - (w, h) = self.placement_window.get_size() + (x,y,w,h) = self.placement_window.get_coords() self.floating_x = x self.floating_y = y self.floating_w = w self.floating_h = h self.overlay.set_floating(True, x, y, w, h) self.save_config - button.set_label("Place Window") - + if not self.overlay.is_wayland: + button.set_label("Place Window") self.placement_window.close() self.placement_window = None else: - self.placement_window = DraggableWindow( - x=self.floating_x, y=self.floating_y, - w=self.floating_w, h=self.floating_h, - message="Place & resize this window then press Save!") - button.set_label("Save this position") + if self.overlay.is_wayland: + self.placement_window = DraggableWindowWayland( + x=self.floating_x, y=self.floating_y, + w=self.floating_w, h=self.floating_h, + message="Place & resize this window then press Green!",settings=self) + else: + self.placement_window = DraggableWindow( + x=self.floating_x, y=self.floating_y, + w=self.floating_w, h=self.floating_h, + message="Place & resize this window then press Save!",settings=self) + if not self.overlay.is_wayland: + button.set_label("Save this position") def change_align_type_edge(self, button): if button.get_active(): From dcbc5b27244d8a5b02f52f6ee80217d138a74a91 Mon Sep 17 00:00:00 2001 From: trigg Date: Mon, 19 Oct 2020 11:49:06 +0000 Subject: [PATCH 67/77] Update README.md --- README.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3dbe6d5..854db0c 100644 --- a/README.md +++ b/README.md @@ -20,18 +20,26 @@ python3 -m pip install . ## Dependencies -Requirements should be handled by pip. - -Requires PyGTK3 3.22 or newer, websocket_client +Most requirements should be handled by pip. A compositor is strongly advised but there is a non-compositor mode optionally +It is advised to install python-gobject from your own package manager. + +#### Debian/Ubuntu + +`apt install python3-gi` + +#### Arch + +`pacman -S python-gobject` + ## Usage run `discover-overlay` if this fails it is most likely in `~/.local/bin/discover-overlay` -Comes with sane-enough defaults but has a system tray icon & settings window if needed. +Comes with sane-enough default but has a configuration screen to tweak to your own use. Configuration can be reached either via System tray or by running `discover-overlay --configure` ## Why do you keep making Discord Overlays? From 188237e3eb5480724c6f3cca04bc9a5995665d64 Mon Sep 17 00:00:00 2001 From: trigg Date: Mon, 19 Oct 2020 13:04:45 +0000 Subject: [PATCH 68/77] - Use theme icon not file --- discover_overlay/settings_window.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discover_overlay/settings_window.py b/discover_overlay/settings_window.py index bca667d..41ece10 100644 --- a/discover_overlay/settings_window.py +++ b/discover_overlay/settings_window.py @@ -20,7 +20,7 @@ class MainSettingsWindow(Gtk.Window): self.text_overlay = text_overlay self.voice_overlay = voice_overlay self.set_title("Discover Overlay Configuration") - self.set_icon_from_file("discover-overlay.png") + self.set_icon_name("discover-overlay") self.set_default_size(280, 180) # Create From 060fc11818dcd027e0d8119d7a9d540ae66d5eab Mon Sep 17 00:00:00 2001 From: trigg Date: Mon, 19 Oct 2020 13:44:44 +0000 Subject: [PATCH 69/77] - Added Wayland multimonitor - Redraw after avatar downloaded - Show monitor select for free-placed overlay --- discover_overlay/overlay.py | 7 ++++++- discover_overlay/settings.py | 10 ++++++++++ discover_overlay/settings_window.py | 4 +++- discover_overlay/text_settings.py | 6 +++--- discover_overlay/voice_overlay.py | 1 + discover_overlay/voice_settings.py | 7 ++++--- 6 files changed, 27 insertions(+), 8 deletions(-) diff --git a/discover_overlay/overlay.py b/discover_overlay/overlay.py index 8c0e5ef..06b6292 100644 --- a/discover_overlay/overlay.py +++ b/discover_overlay/overlay.py @@ -54,6 +54,7 @@ class OverlayWindow(Gtk.Window): self.align_vert = 1 self.floating = False self.force_xshape= False + self.context=None def set_wayland_state(self): if self.is_wayland: @@ -152,8 +153,12 @@ class OverlayWindow(Gtk.Window): gdkwin.shape_combine_region(None, 0, 0) self.queue_draw() - def set_monitor(self, idx): + def set_monitor(self, idx=None, mon=None): self.monitor = idx + if self.is_wayland: + print(self) + if mon: + GtkLayerShell.set_monitor(self, mon) self.force_location() self.redraw() diff --git a/discover_overlay/settings.py b/discover_overlay/settings.py index f3cd426..d37c34c 100644 --- a/discover_overlay/settings.py +++ b/discover_overlay/settings.py @@ -44,5 +44,15 @@ class SettingsWindow(Gtk.VBox): "Could not find monitor : %s" % (name)) return 0 + def get_monitor_obj(self, name): + display = Gdk.Display.get_default() + if "get_n_monitors" in dir(display): + for i in range(0, display.get_n_monitors()): + if display.get_monitor(i).get_model() == name: + return display.get_monitor(i) + logging.info( + "Could not find monitor : %s" % (name)) + return None + def present(self): self.show_all() diff --git a/discover_overlay/settings_window.py b/discover_overlay/settings_window.py index 41ece10..3e1b4da 100644 --- a/discover_overlay/settings_window.py +++ b/discover_overlay/settings_window.py @@ -37,6 +37,7 @@ class MainSettingsWindow(Gtk.Window): nb.append_page(self.core_settings) nb.set_tab_label_text(self.core_settings, "Core") self.add(nb) + self.nb=nb def close_window(self,a=None,b=None): self.text_settings.close_window(a,b) @@ -49,4 +50,5 @@ class MainSettingsWindow(Gtk.Window): self.voice_settings.present() self.text_settings.present() self.core_settings.present() - self.show_all() \ No newline at end of file + self.nb.show() + self.show() \ No newline at end of file diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 43f7d59..1324191 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -81,7 +81,7 @@ class TextSettingsWindow(SettingsWindow): else: self.align_x_widget.hide() self.align_y_widget.hide() - self.align_monitor_widget.hide() + self.align_monitor_widget.show() self.align_placement_widget.show() if self.popup_style: @@ -170,7 +170,7 @@ class TextSettingsWindow(SettingsWindow): self.overlay.set_enabled(self.enabled) self.overlay.set_align_x(self.align_x) self.overlay.set_align_y(self.align_y) - self.overlay.set_monitor(self.get_monitor_index(self.monitor)) + self.overlay.set_monitor(self.get_monitor_index(self.monitor),self.get_monitor_obj(self.monitor)) self.overlay.set_floating( self.floating, self.floating_x, self.floating_y, self.floating_w, self.floating_h) self.overlay.set_bg(self.bg_col) @@ -450,7 +450,7 @@ class TextSettingsWindow(SettingsWindow): if "get_monitor" in dir(display): mon = display.get_monitor(button.get_active()) m_s = mon.get_model() - self.overlay.set_monitor(button.get_active()) + self.overlay.set_monitor(button.get_active(), mon) self.monitor = m_s self.save_config() diff --git a/discover_overlay/voice_overlay.py b/discover_overlay/voice_overlay.py index be2438d..d0308b9 100644 --- a/discover_overlay/voice_overlay.py +++ b/discover_overlay/voice_overlay.py @@ -224,6 +224,7 @@ class VoiceOverlayWindow(OverlayWindow): self.def_avatar = pix else: self.avatars[id] = pix + self.redraw() def delete_avatar(self, id): if id in self.avatars: diff --git a/discover_overlay/voice_settings.py b/discover_overlay/voice_settings.py index 79130f7..776052c 100644 --- a/discover_overlay/voice_settings.py +++ b/discover_overlay/voice_settings.py @@ -31,7 +31,7 @@ class VoiceSettingsWindow(SettingsWindow): else: self.align_x_widget.hide() self.align_y_widget.hide() - self.align_monitor_widget.hide() + self.align_monitor_widget.show() self.align_placement_widget.show() def read_config(self): @@ -85,7 +85,7 @@ class VoiceSettingsWindow(SettingsWindow): self.overlay.set_only_speaking(self.only_speaking) self.overlay.set_highlight_self(self.highlight_self) self.overlay.set_icon_only(self.icon_only) - self.overlay.set_monitor(self.get_monitor_index(self.monitor)) + self.overlay.set_monitor(self.get_monitor_index(self.monitor),self.get_monitor_obj(self.monitor)) self.overlay.set_vert_edge_padding(self.vert_edge_padding) self.overlay.set_horz_edge_padding(self.horz_edge_padding) self.overlay.set_order(self.order) @@ -446,7 +446,8 @@ class VoiceSettingsWindow(SettingsWindow): if "get_monitor" in dir(display): mon = display.get_monitor(button.get_active()) m_s = mon.get_model() - self.overlay.set_monitor(button.get_active()) + self.overlay.set_monitor(button.get_active(), mon) + self.monitor = m_s self.save_config() From 39b1a19e3c7cbe9e3c3a43acb1820a97bdcccb61 Mon Sep 17 00:00:00 2001 From: trigg Date: Mon, 19 Oct 2020 17:46:13 +0000 Subject: [PATCH 70/77] - Heavy refactor - - Rename unused vars with _ or removed - - Remove unused sections of code - - Change name collisions with Gtk/bultins - Bumped internal version to 0.3.0 in prep --- discover_overlay/__init__.py | 13 ++++ discover_overlay/autostart.py | 44 +++++++---- discover_overlay/discord_connector.py | 53 +++++++------ discover_overlay/discover_overlay.py | 50 ++++++------ discover_overlay/draggable_window.py | 62 ++++++++------- discover_overlay/draggable_window_wayland.py | 66 ++++++++++------ discover_overlay/general_settings.py | 28 +++++-- discover_overlay/image_getter.py | 81 +++++++++++--------- discover_overlay/overlay.py | 45 ++++++----- discover_overlay/settings.py | 43 +++++++++-- discover_overlay/settings_window.py | 44 +++++++---- discover_overlay/text_overlay.py | 48 +++++++----- discover_overlay/text_settings.py | 51 +++++++----- discover_overlay/voice_overlay.py | 44 ++++++----- discover_overlay/voice_settings.py | 38 +++++---- setup.py | 2 +- 16 files changed, 436 insertions(+), 276 deletions(-) diff --git a/discover_overlay/__init__.py b/discover_overlay/__init__.py index 7ef8049..7ee925a 100644 --- a/discover_overlay/__init__.py +++ b/discover_overlay/__init__.py @@ -1 +1,14 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""Entry point for Discover Overlay""" from .discover_overlay import * diff --git a/discover_overlay/autostart.py b/discover_overlay/autostart.py index 621343c..d5aad74 100644 --- a/discover_overlay/autostart.py +++ b/discover_overlay/autostart.py @@ -1,4 +1,16 @@ -import sys +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""A class to assist auto-start""" import os import logging try: @@ -9,6 +21,8 @@ except ModuleNotFoundError: class Autostart: + """A class to assist auto-start""" + def __init__(self, app_name): if not app_name.endswith(".desktop"): app_name = "%s.desktop" % (app_name) @@ -19,35 +33,37 @@ class Autostart: xdg_data_home, 'applications/'), '/usr/share/applications/'] self.auto = self.find_auto() self.desktop = self.find_desktop() - logging.info("Autostart info : desktop %s auto %s" % - (self.desktop, self.auto)) + logging.info("Autostart info : desktop %s auto %s", + self.desktop, self.auto) def find_auto(self): - for p in self.auto_locations: - file = os.path.join(p, self.app_name) + """Check all known locations for auto-started apps""" + for path in self.auto_locations: + file = os.path.join(path, self.app_name) if os.path.exists(file): return file return None def find_desktop(self): - for p in self.desktop_locations: - file = os.path.join(p, self.app_name) + """Check all known locations for desktop apps""" + for path in self.desktop_locations: + file = os.path.join(path, self.app_name) if os.path.exists(file): return file return None - def set_autostart(self, b): - if b and not self.auto: + def set_autostart(self, enable): + """Set or Unset auto-start state""" + if enable and not self.auto: # Enable - d = os.path.join(xdg_config_home, 'autostart') - self.auto = os.path.join(d, self.app_name) + directory = os.path.join(xdg_config_home, 'autostart') + self.auto = os.path.join(directory, self.app_name) os.symlink(self.desktop, self.auto) - pass - elif not b and self.auto: + elif not enable and self.auto: # Disable if os.path.islink(self.auto): os.remove(self.auto) - pass def is_auto(self): + """Check if it's already set to auto-start""" return True if self.auto else False diff --git a/discover_overlay/discord_connector.py b/discover_overlay/discord_connector.py index f548281..1ef32d3 100644 --- a/discover_overlay/discord_connector.py +++ b/discover_overlay/discord_connector.py @@ -1,12 +1,23 @@ -import websocket +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . import select import time import json -import re import sys -import requests import logging import calendar +import websocket +import requests class DiscordConnector: @@ -17,7 +28,6 @@ class DiscordConnector: self.voice_overlay = voice_overlay self.ws = None self.access_token = "none" - # TODO Magic number self.oauth_token = "207646673902501888" self.access_delay = 0 self.warn_connection = True @@ -47,7 +57,7 @@ class DiscordConnector: x = requests.post(url, json=myobj) try: j = json.loads(x.text) - except: + except json.JSONDecodeError: j = {} if "access_token" in j: self.access_token = j["access_token"] @@ -62,7 +72,7 @@ class DiscordConnector: if channel != self.current_voice: cn = self.channels[channel]['name'] logging.info( - "Joined room: %s" % (cn)) + "Joined room: %s", cn) self.sub_voice_channel(channel) self.current_voice = channel if need_req: @@ -75,7 +85,7 @@ class DiscordConnector: if channel != self.current_text: self.current_text = channel logging.info( - "Changing text room: %s" % (channel)) + "Changing text room: %s", channel) if need_req: self.req_channel_details(channel) @@ -202,9 +212,7 @@ class DiscordConnector: self.set_in_room(j["data"]["user"]["id"], False) if j["data"]["user"]["id"] == self.user["id"]: self.in_room = [] - #self.sub_all_voice() - else: - un = j["data"]["user"]["username"] + # self.sub_all_voice() elif j["evt"] == "SPEAKING_START": self.list_altered = True # It's only possible to get alerts for the room you're in @@ -245,9 +253,9 @@ class DiscordConnector: self.req_guilds() self.user = j["data"]["user"] logging.info( - "ID is %s" % (self.user["id"])) + "ID is %s", self.user["id"]) logging.info( - "Logged in as %s" % (self.user["username"])) + "Logged in as %s", self.user["username"]) self.authed = True return elif j["cmd"] == "GET_GUILDS": @@ -264,8 +272,8 @@ class DiscordConnector: if channel["type"] == 2: self.req_channel_details(channel["id"]) self.check_guilds() - #self.sub_all_voice_guild(j["nonce"]) - #self.sub_all_text_guild(j["nonce"]) + # self.sub_all_voice_guild(j["nonce"]) + # self.sub_all_text_guild(j["nonce"]) return elif j["cmd"] == "SUBSCRIBE": return @@ -307,14 +315,14 @@ class DiscordConnector: for channel in guild["channels"]: channels = channels + " " + channel["name"] logging.info( - u"%s: %s" % (guild["name"], channels)) + u"%s: %s", guild["name"], channels) self.sub_server() self.find_user() if self.last_text_channel: self.sub_text_channel(self.last_text_channel) def on_error(self, error): - logging.error("ERROR : %s" % (error)) + logging.error("ERROR : %s", error) def on_close(self): logging.info("Connection closed") @@ -340,8 +348,8 @@ class DiscordConnector: for channel in self.channels: if self.channels[channel]["type"] == 2: self.req_channel_details(channel) - count+=1 - logging.warn("Getting %s rooms" %(count)) + count += 1 + logging.warning("Getting %s rooms", count) def sub_raw(self, cmd, channel, nonce): self.ws.send("{\"cmd\":\"SUBSCRIBE\",\"args\":{%s},\"evt\":\"%s\",\"nonce\":\"%s\"}" % ( @@ -424,14 +432,14 @@ class DiscordConnector: self.set_text_channel(self.text_settings.get_channel()) # Poll socket for new information - r, w, e = select.select((self.ws.sock,), (), (), 0) + r, _w, _e = select.select((self.ws.sock,), (), (), 0) while r: try: # Recieve & send to on_message msg = self.ws.recv() self.on_message(msg) - r, w, e = select.select((self.ws.sock,), (), (), 0) - except websocket._exceptions.WebSocketConnectionClosedException: + r, _w, _e = select.select((self.ws.sock,), (), (), 0) + except websocket.WebSocketConnectionClosedException: self.on_close() return True return True @@ -448,8 +456,7 @@ class DiscordConnector: try: self.ws = websocket.create_connection("ws://127.0.0.1:6463/?v=1&client_id=%s" % (self.oauth_token), origin="https://streamkit.discord.com") - except Exception as e: + except ConnectionError as e: if self.error_connection: logging.error(e) self.error_connection = False - pass diff --git a/discover_overlay/discover_overlay.py b/discover_overlay/discover_overlay.py index 6a568ba..a06a3a3 100755 --- a/discover_overlay/discover_overlay.py +++ b/discover_overlay/discover_overlay.py @@ -10,18 +10,18 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import os +import sys import gi -gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, GLib, Gio -import select +import logging +import pidfile from .settings_window import MainSettingsWindow from .voice_overlay import VoiceOverlayWindow from .text_overlay import TextOverlayWindow from .discord_connector import DiscordConnector -import logging -import pidfile -import os -import sys +gi.require_version("Gtk", "3.0") +# pylint: disable=wrong-import-position +from gi.repository import Gtk, GLib, Gio try: from xdg.BaseDirectory import xdg_config_home @@ -31,6 +31,9 @@ except ModuleNotFoundError: class Discover: def __init__(self, rpc_file, args): + self.ind = None + self.tray = None + self.create_gui() self.connection = DiscordConnector( self.settings.text_settings, self.settings.voice_settings, @@ -44,10 +47,7 @@ class Discover: monitor.connect("changed", self.rpc_changed) self.do_args(args) - try: - Gtk.main() - except: - pass + Gtk.main() def do_args(self, data): if "--help" in data: @@ -59,11 +59,10 @@ class Discover: elif "--close" in data: sys.exit(0) - - def rpc_changed(self, a=None, b=None, c=None,d=None): - with open (self.rpc_file, "r") as tfile: - data=tfile.readlines() - if len(data)>=1: + def rpc_changed(self, _a=None, _b=None, _c=None, _d=None): + with open(self.rpc_file, "r") as tfile: + data = tfile.readlines() + if len(data) >= 1: self.do_args(data[0]) def create_gui(self): @@ -71,12 +70,14 @@ class Discover: self.text_overlay = TextOverlayWindow(self) self.menu = self.make_menu() self.make_sys_tray_icon(self.menu) - self.settings = MainSettingsWindow(self.text_overlay, self.voice_overlay) + self.settings = MainSettingsWindow( + self.text_overlay, self.voice_overlay) def make_sys_tray_icon(self, menu): # Create AppIndicator try: gi.require_version('AppIndicator3', '0.1') + # pylint: disable=import-outside-toplevel from gi.repository import AppIndicator3 self.ind = AppIndicator3.Indicator.new( "discover_overlay", @@ -84,9 +85,9 @@ class Discover: AppIndicator3.IndicatorCategory.APPLICATION_STATUS) self.ind.set_status(AppIndicator3.IndicatorStatus.ACTIVE) self.ind.set_menu(menu) - except Exception as e: + except ImportError as exception: # Create System Tray - logging.info("Falling back to Systray : %s" % (e)) + logging.info("Falling back to Systray : %s", exception) self.tray = Gtk.StatusIcon.new_from_icon_name("discover-overlay") self.tray.connect('popup-menu', self.show_menu) @@ -109,10 +110,10 @@ class Discover: self.menu.popup( None, None, Gtk.StatusIcon.position_menu, obj, button, time) - def show_settings(self, obj=None, data=None): - self.settings.present() + def show_settings(self, _obj=None, _data=None): + self.settings.present_settings() - def close(self, a=None, b=None, c=None): + def close(self, _a=None, _b=None, _c=None): Gtk.main_quit() @@ -129,9 +130,8 @@ def entrypoint(): logging.getLogger().setLevel(logging.INFO) Discover(rpc_file, line) except pidfile.AlreadyRunningError: - logging.warn("Discover overlay is currently running") + logging.warning("Discover overlay is currently running") with open(rpc_file, "w") as tfile: tfile.write(line) - logging.warn("Sent RPC command") - + logging.warning("Sent RPC command") diff --git a/discover_overlay/draggable_window.py b/discover_overlay/draggable_window.py index 3432594..cf82e83 100644 --- a/discover_overlay/draggable_window.py +++ b/discover_overlay/draggable_window.py @@ -1,12 +1,27 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""An X11 window which can be moved and resized""" import gi -gi.require_version("Gtk", "3.0") import cairo +gi.require_version("Gtk", "3.0") +# pylint: disable=wrong-import-position from gi.repository import Gtk, Gdk -import logging class DraggableWindow(Gtk.Window): - def __init__(self, x=0, y=0, w=300, h=300, message="Message",settings=None): + """An X11 window which can be moved and resized""" + + def __init__(self, x=0, y=0, w=300, h=300, message="Message", settings=None): Gtk.Window.__init__(self, type=Gtk.WindowType.POPUP) if w < 100: w = 100 @@ -16,11 +31,11 @@ class DraggableWindow(Gtk.Window): self.y = y self.w = w self.h = h - self.settings=settings + self.settings = settings self.message = message self.set_size_request(50, 50) - self.connect('draw', self.draw) + self.connect('draw', self.dodraw) self.connect('motion-notify-event', self.drag) self.connect('button-press-event', self.button_press) self.connect('button-release-event', self.button_release) @@ -45,28 +60,15 @@ class DraggableWindow(Gtk.Window): self.show_all() def force_location(self): + """Move the window to previously given co-ords. Also double check sanity on layer & decorations""" + self.set_decorated(False) self.set_keep_above(True) - display = Gdk.Display.get_default() - if "get_monitor" in dir(display): - monitor = display.get_monitor(self.monitor) - geometry = monitor.get_geometry() - scale_factor = monitor.get_scale_factor() - w = scale_factor * geometry.width - h = scale_factor * geometry.height - x = geometry.x - y = geometry.y - else: - screen = display.get_default_screen() - w = screen.width() - h = screen.height() - x = 0 - y = 0 - #self.resize(400, h) self.move(self.x, self.y) self.resize(self.w, self.h) - def drag(self, w, event): + def drag(self, _w, event): + """Called by GTK while mouse is moving over window. Used to resize and move""" if event.state & Gdk.ModifierType.BUTTON1_MASK: if self.drag_type == 1: # Center is move @@ -92,6 +94,7 @@ class DraggableWindow(Gtk.Window): self.force_location() def button_press(self, w, event): + """Called when a mouse button is pressed on this window""" (w, h) = self.get_size() if not self.drag_type: self.drag_type = 1 @@ -103,10 +106,12 @@ class DraggableWindow(Gtk.Window): self.drag_x = event.x self.drag_y = event.y - def button_release(self, w, event): + def button_release(self, _w, _event): + """Called when a mouse button is released""" self.drag_type = None - def draw(self, widget, context): + def dodraw(self, _widget, context): + """Draw our window.""" context.set_source_rgba(1.0, 1.0, 0.0, 0.7) # Don't layer drawing over each other, always replace context.set_operator(cairo.OPERATOR_SOURCE) @@ -117,7 +122,7 @@ class DraggableWindow(Gtk.Window): # Draw text context.set_source_rgba(0.0, 0.0, 0.0, 1.0) - xb, yb, w, h, dx, dy = context.text_extents(self.message) + _xb, _yb, w, h, _dx, _dy = context.text_extents(self.message) context.move_to(sw / 2 - w / 2, sh / 2 - h / 2) context.show_text(self.message) @@ -130,6 +135,7 @@ class DraggableWindow(Gtk.Window): context.fill() def get_coords(self): - (x, y) = self.placement_window.get_position() - (w, h) = self.placement_window.get_size() - return (x,y,w,h) + """Return window position and size""" + (x, y) = self.get_position() + (w, h) = self.get_size() + return (x, y, w, h) diff --git a/discover_overlay/draggable_window_wayland.py b/discover_overlay/draggable_window_wayland.py index 328b360..fefa742 100644 --- a/discover_overlay/draggable_window_wayland.py +++ b/discover_overlay/draggable_window_wayland.py @@ -1,11 +1,26 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""A Wayland full-screen window which can be moved and resized""" +import cairo import gi gi.require_version("Gtk", "3.0") -import cairo +# pylint: disable=wrong-import-position from gi.repository import Gtk, Gdk, GtkLayerShell -import logging class DraggableWindowWayland(Gtk.Window): + """A Wayland full-screen window which can be moved and resized""" + def __init__(self, x=0, y=0, w=300, h=300, message="Message", settings=None): Gtk.Window.__init__(self, type=Gtk.WindowType.TOPLEVEL) if w < 100: @@ -16,11 +31,11 @@ class DraggableWindowWayland(Gtk.Window): self.y = y self.w = w self.h = h - self.settings=settings + self.settings = settings self.message = message self.set_size_request(50, 50) - self.connect('draw', self.draw) + self.connect('draw', self.dodraw) self.connect('motion-notify-event', self.drag) self.connect('button-press-event', self.button_press) self.connect('button-release-event', self.button_release) @@ -39,21 +54,23 @@ class DraggableWindowWayland(Gtk.Window): GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.TOP, True) self.show_all() - #self.force_location() + # self.force_location() def force_location(self): - (sx, sy)= self.get_size() + """Move the window to previously given co-ords. In wayland just clip to current screen""" + (size_x, size_y) = self.get_size() if self.x < 0: - self.x=0 + self.x = 0 if self.y < 0: - self.y=0 - if self.x + self.w > sx: - self.x = sx - self.w - if self.y + self.h > sy: - self.y = sy - self.h + self.y = 0 + if self.x + self.w > size_x: + self.x = size_x - self.w + if self.y + self.h > size_y: + self.y = size_y - self.h self.queue_draw() - def drag(self, w, event): + def drag(self, _w, event): + """Called by GTK while mouse is moving over window. Used to resize and move""" if event.state & Gdk.ModifierType.BUTTON1_MASK: if self.drag_type == 1: # Center is move @@ -81,14 +98,15 @@ class DraggableWindowWayland(Gtk.Window): self.drag_y = event.y self.force_location() - def button_press(self, w, event): + def button_press(self, _w, event): + """Called when a mouse button is pressed on this window""" px = event.x - self.x py = event.y - self.y if not self.drag_type: self.drag_type = 1 # Where in the window did we press? - if px < 20 and py<20: + if px < 20 and py < 20: self.settings.change_placement(None) if py > self.h - 32: self.drag_type += 2 @@ -97,13 +115,15 @@ class DraggableWindowWayland(Gtk.Window): self.drag_x = event.x self.drag_y = event.y - def button_release(self, w, event): + def button_release(self, _w, _event): + """Called when a mouse button is released""" self.drag_type = None - def draw(self, widget, context): + def dodraw(self, _widget, context): + """Draw our window. For wayland we're secretly a fullscreen app and need to draw only a single rectangle of the overlay""" context.translate(self.x, self.y) context.save() - context.rectangle(0,0,self.w,self.h) + context.rectangle(0, 0, self.w, self.h) context.clip() context.set_source_rgba(1.0, 1.0, 0.0, 0.7) @@ -114,8 +134,8 @@ class DraggableWindowWayland(Gtk.Window): # Draw text context.set_source_rgba(0.0, 0.0, 0.0, 1.0) - xb, yb, w, h, dx, dy = context.text_extents(self.message) - context.move_to(self.w / 2 - w / 2, self.h / 2 - h / 2) + _xb, _yb, width, height, _dx, _dy = context.text_extents(self.message) + context.move_to(self.w / 2 - width / 2, self.h / 2 - height / 2) context.show_text(self.message) # Draw resizing edges @@ -128,10 +148,10 @@ class DraggableWindowWayland(Gtk.Window): # Draw Done! context.set_source_rgba(0.0, 1.0, 0.0, 0.5) - context.rectangle(0, 0, 20,20) + context.rectangle(0, 0, 20, 20) context.fill() context.restore() - def get_coords(self): - return (self.x,self.y,self.w,self.h) \ No newline at end of file + """Return the position and size of the window""" + return (self.x, self.y, self.w, self.h) diff --git a/discover_overlay/general_settings.py b/discover_overlay/general_settings.py index b74764c..3bb179c 100644 --- a/discover_overlay/general_settings.py +++ b/discover_overlay/general_settings.py @@ -1,19 +1,31 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . import gi -gi.require_version("Gtk", "3.0") -import json from configparser import ConfigParser -from .draggable_window import DraggableWindow from .settings import SettingsWindow from .autostart import Autostart -from gi.repository import Gtk, Gdk, Pango -import logging +gi.require_version("Gtk", "3.0") +# pylint: disable=wrong-import-position +from gi.repository import Gtk class GeneralSettingsWindow(SettingsWindow): def __init__(self, overlay, overlay2): - Gtk.VBox.__init__(self) + SettingsWindow.__init__(self) self.overlay = overlay - self.overlay2 = overlay + self.overlay2 = overlay2 + self.xshape = None + self.autostart = None self.set_size_request(400, 200) self.connect("destroy", self.close_window) self.connect("delete-event", self.close_window) @@ -73,4 +85,4 @@ class GeneralSettingsWindow(SettingsWindow): self.overlay.set_force_xshape(button.get_active()) self.overlay2.set_force_xshape(button.get_active()) self.xshape = button.get_active() - self.save_config() \ No newline at end of file + self.save_config() diff --git a/discover_overlay/image_getter.py b/discover_overlay/image_getter.py index bdac51e..7ebfbbf 100644 --- a/discover_overlay/image_getter.py +++ b/discover_overlay/image_getter.py @@ -1,21 +1,32 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . import gi -gi.require_version("Gtk", "3.0") -gi.require_version('GdkPixbuf', '2.0') import urllib import requests import threading -from gi.repository.GdkPixbuf import Pixbuf -from gi.repository import Gtk, Gio, GdkPixbuf, Gdk import cairo import logging import PIL.Image as Image -from io import BytesIO +gi.require_version("Gtk", "3.0") +gi.require_version('GdkPixbuf', '2.0') +# pylint: disable=wrong-import-position +from gi.repository import Gio, GdkPixbuf class Image_Getter(): - def __init__(self, func, url, id, size): + def __init__(self, func, url, identifier, size): self.func = func - self.id = id + self.id = identifier self.url = url self.size = size @@ -28,36 +39,22 @@ class Image_Getter(): response = urllib.request.urlopen(req) input_stream = Gio.MemoryInputStream.new_from_data( response.read(), None) - pixbuf = Pixbuf.new_from_stream(input_stream, None) + pixbuf = GdkPixbuf.Pixbuf.new_from_stream(input_stream, None) if self.size: pixbuf = pixbuf.scale_simple(self.size, self.size, GdkPixbuf.InterpType.BILINEAR) - # elif self.limit_x or self.limit_y: - # px = pixbuf.width() - # py = pixbuf.height() - # aspect = px / py - # scale = 1.0 - # if self.limit_x and self.limit_y: - # scale = min(self.limit_x / px, self.limit_y / py, 1.0) - # elif self.limit_x: - # scale = min(self.limit_x / px, 1.0) - # elif self.limit_y: - # scale = min(self.limit_y / py, 1.0)## -# -# pixbuf = pixbuf.scale_simple(int(px * scale), int(py * scale), -# GdkPixbuf.InterpType.BILINEAR) self.func(self.id, pixbuf) - except Exception as e: + except urllib.error.URLError as exception: logging.error( - "Could not access : %s" % (self.url)) - logging.error(e) + "Could not access : %s", self.url) + logging.error(exception) class Surface_Getter(): - def __init__(self, func, url, id, size): + def __init__(self, func, url, identifier, size): self.func = func - self.id = id + self.id = identifier self.url = url self.size = size @@ -71,33 +68,41 @@ class Surface_Getter(): surf = self.from_pil(im) self.func(self.id, surf) - except: - logging.error("Unable to open %s" % (self.url)) + except requests.HTTPError: + logging.error("Unable to open %s", self.url) + except requests.TooManyRedirects: + logging.error("Unable to open %s - Too many redirects", self.url) + except requests.Timeout: + logging.error("Unable to open %s - Timeout", self.url) + except requests.ConnectionError: + logging.error("Unable to open %s - Connection error", self.url) + except ValueError: + logging.error("Unable to read %s", self.url) + except TypeError: + logging.error("Unable to read %s", self.url) - def from_pil(self, im, alpha=1.0, format=cairo.FORMAT_ARGB32): + def from_pil(self, im, 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 """ - assert format in ( - cairo.FORMAT_RGB24, cairo.FORMAT_ARGB32), "Unsupported pixel format: %s" % format if 'A' not in im.getbands(): im.putalpha(int(alpha * 256.)) arr = bytearray(im.tobytes('raw', 'BGRa')) surface = cairo.ImageSurface.create_for_data( - arr, format, im.width, im.height) + arr, cairo.FORMAT_ARGB32, im.width, im.height) return surface -def get_image(func, id, ava, size): - image_getter = Image_Getter(func, id, ava, size) +def get_image(func, identifier, ava, size): + image_getter = Image_Getter(func, identifier, ava, size) t = threading.Thread(target=image_getter.get_url, args=()) t.start() -def get_surface(func, id, ava, size): - image_getter = Surface_Getter(func, id, ava, size) +def get_surface(func, identifier, ava, size): + image_getter = Surface_Getter(func, identifier, ava, size) t = threading.Thread(target=image_getter.get_url, args=()) t.start() @@ -106,7 +111,7 @@ def get_aspected_size(img, w, h, anchor=0, hanchor=0): px = img.get_width() py = img.get_height() if py < 1 or h < 1: - return (0, 0) + return (0, 0, 0, 0) img_aspect = px / py rect_aspect = w / h diff --git a/discover_overlay/overlay.py b/discover_overlay/overlay.py index 06b6292..d4905ae 100644 --- a/discover_overlay/overlay.py +++ b/discover_overlay/overlay.py @@ -1,9 +1,22 @@ -import gi -gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk, GtkLayerShell -import cairo -import logging +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . import sys +import logging +import gi +import cairo +gi.require_version("Gtk", "3.0") +# pylint: disable=wrong-import-position +from gi.repository import Gtk, Gdk, GtkLayerShell class OverlayWindow(Gtk.Window): @@ -11,9 +24,9 @@ class OverlayWindow(Gtk.Window): window = Gtk.Window() screen = window.get_screen() screen_type = "%s" % (screen) - self.is_wayland=False + self.is_wayland = False if "Wayland" in screen_type: - self.is_wayland=True + self.is_wayland = True print("Using Wayland GDK. Expect bugs") return Gtk.WindowType.TOPLEVEL return Gtk.WindowType.POPUP @@ -23,7 +36,7 @@ class OverlayWindow(Gtk.Window): screen = self.get_screen() self.set_size_request(50, 50) - self.connect('draw', self.draw) + self.connect('draw', self.overlay_draw) self.compositing = False # Set RGBA @@ -53,8 +66,8 @@ class OverlayWindow(Gtk.Window): self.align_right = True self.align_vert = 1 self.floating = False - self.force_xshape= False - self.context=None + self.force_xshape = False + self.context = None def set_wayland_state(self): if self.is_wayland: @@ -65,10 +78,7 @@ class OverlayWindow(Gtk.Window): GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.BOTTOM, True) GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.TOP, True) - def draw(self, widget, context): - self.do_draw(context) - - def do_draw(self, context): + def overlay_draw(self, _w, context, data=None): pass def set_font(self, name, size): @@ -129,7 +139,7 @@ class OverlayWindow(Gtk.Window): self.resize(self.w, self.h) if not self.floating: - (w,h) = self.get_size() + (w, h) = self.get_size() self.w = w self.h = h self.redraw() @@ -137,7 +147,7 @@ class OverlayWindow(Gtk.Window): def redraw(self): gdkwin = self.get_window() if not self.floating: - (w,h) = self.get_size() + (w, h) = self.get_size() self.w = w self.h = h @@ -146,7 +156,7 @@ class OverlayWindow(Gtk.Window): (w, h) = self.get_size() surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h) surface_ctx = cairo.Context(surface) - self.do_draw(surface_ctx) + self.overlay_draw(None, surface_ctx) reg = Gdk.cairo_region_create_from_surface(surface) gdkwin.shape_combine_region(reg, 0, 0) else: @@ -156,7 +166,6 @@ class OverlayWindow(Gtk.Window): def set_monitor(self, idx=None, mon=None): self.monitor = idx if self.is_wayland: - print(self) if mon: GtkLayerShell.set_monitor(self, mon) self.force_location() diff --git a/discover_overlay/settings.py b/discover_overlay/settings.py index d37c34c..e5bbecf 100644 --- a/discover_overlay/settings.py +++ b/discover_overlay/settings.py @@ -1,9 +1,21 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +import os +import logging import gi gi.require_version("Gtk", "3.0") -import sys -import os +# pylint: disable=wrong-import-position from gi.repository import Gtk, Gdk -import logging try: @@ -13,13 +25,24 @@ except ModuleNotFoundError: class SettingsWindow(Gtk.VBox): + def __init__(self): + Gtk.VBox.__init__(self) + self.placement_window = None + self.configDir = None + self.configFile = None + self.overlay = None + self.floating_x = None + self.floating_y = None + self.floating_w = None + self.floating_h = None + def init_config(self): self.configDir = os.path.join(xdg_config_home, "discover_overlay") os.makedirs(self.configDir, exist_ok=True) self.configFile = os.path.join(self.configDir, "config.ini") self.read_config() - def close_window(self, a=None, b=None): + def close_window(self, _a=None, _b=None): if self.placement_window: (x, y) = self.placement_window.get_position() (w, h) = self.placement_window.get_size() @@ -41,7 +64,7 @@ class SettingsWindow(Gtk.VBox): if display.get_monitor(i).get_model() == name: return i logging.info( - "Could not find monitor : %s" % (name)) + "Could not find monitor : %s", name) return 0 def get_monitor_obj(self, name): @@ -51,8 +74,14 @@ class SettingsWindow(Gtk.VBox): if display.get_monitor(i).get_model() == name: return display.get_monitor(i) logging.info( - "Could not find monitor : %s" % (name)) + "Could not find monitor : %s", name) return None - def present(self): + def present_settings(self): self.show_all() + + def read_config(self): + pass + + def save_config(self): + pass diff --git a/discover_overlay/settings_window.py b/discover_overlay/settings_window.py index 3e1b4da..c5bbe55 100644 --- a/discover_overlay/settings_window.py +++ b/discover_overlay/settings_window.py @@ -1,13 +1,22 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . from .voice_settings import VoiceSettingsWindow from .text_settings import TextSettingsWindow from .general_settings import GeneralSettingsWindow - import gi gi.require_version("Gtk", "3.0") -import sys -import os -from gi.repository import Gtk, Gdk -import logging +# pylint: disable=wrong-import-position +from gi.repository import Gtk class MainSettingsWindow(Gtk.Window): @@ -25,7 +34,7 @@ class MainSettingsWindow(Gtk.Window): # Create nb = Gtk.Notebook() - #nb.set_tab_pos(Gtk.POS_TOP) + # nb.set_tab_pos(Gtk.POS_TOP) self.voice_settings = VoiceSettingsWindow(self.voice_overlay) nb.append_page(self.voice_settings) @@ -33,22 +42,23 @@ class MainSettingsWindow(Gtk.Window): self.text_settings = TextSettingsWindow(self.text_overlay) nb.append_page(self.text_settings) nb.set_tab_label_text(self.text_settings, "Text") - self.core_settings = GeneralSettingsWindow(self.text_overlay,self.voice_overlay) + self.core_settings = GeneralSettingsWindow( + self.text_overlay, self.voice_overlay) nb.append_page(self.core_settings) nb.set_tab_label_text(self.core_settings, "Core") self.add(nb) - self.nb=nb + self.nb = nb - def close_window(self,a=None,b=None): - self.text_settings.close_window(a,b) - self.voice_settings.close_window(a,b) - self.core_settings.close_window(a,b) + def close_window(self, a=None, b=None): + self.text_settings.close_window(a, b) + self.voice_settings.close_window(a, b) + self.core_settings.close_window(a, b) self.hide() return True - def present(self): - self.voice_settings.present() - self.text_settings.present() - self.core_settings.present() + def present_settings(self): + self.voice_settings.present_settings() + self.text_settings.present_settings() + self.core_settings.present_settings() self.nb.show() - self.show() \ No newline at end of file + self.show() diff --git a/discover_overlay/text_overlay.py b/discover_overlay/text_overlay.py index 5555f46..389ac5c 100644 --- a/discover_overlay/text_overlay.py +++ b/discover_overlay/text_overlay.py @@ -1,14 +1,27 @@ -import gi -gi.require_version("Gtk", "3.0") -gi.require_version('PangoCairo', '1.0') -import math +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + from .overlay import OverlayWindow -from gi.repository import Gtk, Gdk, Pango, PangoCairo import cairo import logging import time import re from .image_getter import get_surface, draw_img_to_rect, get_aspected_size +import gi +gi.require_version("Gtk", "3.0") +gi.require_version('PangoCairo', '1.0') +# pylint: disable=wrong-import-position +from gi.repository import Pango, PangoCairo class TextOverlayWindow(OverlayWindow): @@ -111,17 +124,14 @@ class TextOverlayWindow(OverlayWindow): elif msg['type'] == 'br': ret = '\n' else: - logging.error("Unknown text type : %s" % (msg["type"])) + logging.error("Unknown text type : %s", msg["type"]) return ret - def recv_attach(self, id, pix): - self.attachment[id] = pix + def recv_attach(self, identifier, pix): + self.attachment[identifier] = pix self.redraw() - def draw(self, widget, ctx): - self.do_draw(ctx) - - def do_draw(self, context): + def overlay_draw(self, _w, context, data=None): self.context = context context.set_antialias(cairo.ANTIALIAS_GOOD) (w, h) = self.get_size() @@ -138,10 +148,8 @@ class TextOverlayWindow(OverlayWindow): w = self.w h = self.h context.translate(self.x, self.y) - context.rectangle(0,0,w,h) + context.rectangle(0, 0, w, h) context.clip() - - cy = h tnow = time.time() @@ -181,13 +189,13 @@ class TextOverlayWindow(OverlayWindow): ih = pix.get_height() iw = min(iw, self.w) ih = min(ih, (self.h * .7)) - (ax, ay, aw, ah) = get_aspected_size(pix, iw, ih) + (_ax, _ay, _aw, ah) = get_aspected_size(pix, iw, ih) self.col(self.bg_col) self.context.rectangle(0, y - ah, self.w, ah) self.context.fill() self.context.set_operator(cairo.OPERATOR_OVER) - new_w, new_h = draw_img_to_rect( + _new_w, new_h = draw_img_to_rect( pix, self.context, 0, y - ih, iw, ih, aspect=True) return y - new_h return y @@ -204,7 +212,7 @@ class TextOverlayWindow(OverlayWindow): font = Pango.FontDescription( "%s %s" % (self.text_font, self.text_size)) layout.set_font_description(font) - tw, th = layout.get_pixel_size() + _tw, th = layout.get_pixel_size() self.col(self.bg_col) self.context.rectangle(0, y - th, self.w, th) self.context.fill() @@ -223,7 +231,7 @@ class TextOverlayWindow(OverlayWindow): if len(self.imgList) <= count: break # We fucked up. Who types ` anyway - url = self.imgList[count] + #url = self.imgList[count] at = Pango.attr_shape_new_with_data( self.pango_rect, self.pango_rect, count, None) @@ -236,7 +244,7 @@ class TextOverlayWindow(OverlayWindow): PangoCairo.show_layout(self.context, layout) return y - th - def render_custom(self, ctx, shape, path, data): + def render_custom(self, ctx, shape, path, _data): key = self.imgList[shape.data]['url'] if key not in self.attachment: get_surface(self.recv_attach, diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 1324191..f224bcf 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -1,18 +1,33 @@ -import gi -gi.require_version("Gtk", "3.0") +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . import json from configparser import ConfigParser from .draggable_window import DraggableWindow from .draggable_window_wayland import DraggableWindowWayland from .settings import SettingsWindow -from gi.repository import Gtk, Gdk, Pango import logging +import gi +gi.require_version("Gtk", "3.0") +# pylint: disable=wrong-import-position +from gi.repository import Gtk, Gdk, Pango + GUILD_DEFAULT_VALUE = "0" + class TextSettingsWindow(SettingsWindow): def __init__(self, overlay): - Gtk.VBox.__init__(self) + SettingsWindow.__init__(self) self.overlay = overlay self.set_size_request(400, 200) self.connect("destroy", self.close_window) @@ -27,7 +42,6 @@ class TextSettingsWindow(SettingsWindow): self.ignore_guild_change = False self.create_gui() - def update_channel_model(self): # potentially organize channels by their group/parent_id # https://discord.com/developers/docs/resources/channel#channel-object-channel-structure @@ -44,7 +58,7 @@ class TextSettingsWindow(SettingsWindow): if chan['guild_id'] == guild_id: c_model.append([chan["name"], True]) self.channel_lookup.append(c) - + # if a guild is specified, poulate channel list with every channel from *just that guild* if self.guild != GUILD_DEFAULT_VALUE: for c in self.list_channels_keys: @@ -65,13 +79,12 @@ class TextSettingsWindow(SettingsWindow): break idx += 1 - def add_connector(self, conn): self.connector = conn if self.channel: self.connector.start_listening_text(self.channel) - def present(self): + def present_settings(self): self.show_all() if not self.floating: self.align_x_widget.show() @@ -130,7 +143,7 @@ class TextSettingsWindow(SettingsWindow): if in_list[key]["type"] == 0: self.list_channels_keys.append(key) self.list_channels_keys.sort() - + def set_guilds(self, in_list): self.list_guilds = in_list self.list_guilds_keys = [] @@ -164,13 +177,14 @@ class TextSettingsWindow(SettingsWindow): "text", "show_attach", fallback=True) logging.info( - "Loading saved channel %s" % (self.channel)) + "Loading saved channel %s", self.channel) # Pass all of our config over to the overlay self.overlay.set_enabled(self.enabled) self.overlay.set_align_x(self.align_x) self.overlay.set_align_y(self.align_y) - self.overlay.set_monitor(self.get_monitor_index(self.monitor),self.get_monitor_obj(self.monitor)) + self.overlay.set_monitor(self.get_monitor_index( + self.monitor), self.get_monitor_obj(self.monitor)) self.overlay.set_floating( self.floating, self.floating_x, self.floating_y, self.floating_w, self.floating_h) self.overlay.set_bg(self.bg_col) @@ -306,7 +320,6 @@ class TextSettingsWindow(SettingsWindow): channel.connect("changed", self.change_channel) rt = Gtk.CellRendererText() - #channel.set_row_separator_func(lambda model, path: model[path][1]) channel.pack_start(rt, True) channel.add_attribute(rt, "text", 0) channel.add_attribute(rt, 'sensitive', 1) @@ -315,8 +328,7 @@ class TextSettingsWindow(SettingsWindow): guild = Gtk.ComboBox.new() guild.connect("changed", self.change_guild) - guild_rt = Gtk.CellRendererText() - #guild.set_row_separator_func(lambda model, path: model[path][1]) + rt = Gtk.CellRendererText() guild.pack_start(rt, True) guild.add_attribute(rt, "text", 0) guild.add_attribute(rt, 'sensitive', 1) @@ -378,24 +390,23 @@ class TextSettingsWindow(SettingsWindow): def change_channel(self, button): if self.ignore_channel_change: return - + c = self.channel_lookup[button.get_active()] self.connector.start_listening_text(c) self.channel = c self.save_config() - def change_guild(self, button): if self.ignore_guild_change: return - guild_id = self.guild_lookup[button.get_active()] + guild_id = self.guild_lookup[button.get_active()] self.guild = guild_id self.save_config() self.update_channel_model() def change_placement(self, button): if self.placement_window: - (x,y,w,h) = self.placement_window.get_coords() + (x, y, w, h) = self.placement_window.get_coords() self.floating_x = x self.floating_y = y self.floating_w = w @@ -412,12 +423,12 @@ class TextSettingsWindow(SettingsWindow): self.placement_window = DraggableWindowWayland( x=self.floating_x, y=self.floating_y, w=self.floating_w, h=self.floating_h, - message="Place & resize this window then press Green!",settings=self) + message="Place & resize this window then press Green!", settings=self) else: self.placement_window = DraggableWindow( x=self.floating_x, y=self.floating_y, w=self.floating_w, h=self.floating_h, - message="Place & resize this window then press Save!",settings=self) + message="Place & resize this window then press Save!", settings=self) if not self.overlay.is_wayland: button.set_label("Save this position") diff --git a/discover_overlay/voice_overlay.py b/discover_overlay/voice_overlay.py index d0308b9..6ac1b06 100644 --- a/discover_overlay/voice_overlay.py +++ b/discover_overlay/voice_overlay.py @@ -1,12 +1,19 @@ -import gi - -gi.require_version("Gtk", "3.0") +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . import math +import cairo from .overlay import OverlayWindow from .image_getter import get_surface, draw_img_to_rect -from gi.repository import Gtk, Gdk -import cairo -import logging class VoiceOverlayWindow(OverlayWindow): @@ -37,8 +44,8 @@ class VoiceOverlayWindow(OverlayWindow): self.connected = False self.force_location() get_surface(self.recv_avatar, - "https://cdn.discordapp.com/embed/avatars/3.png", - 'def', self.avatar_size) + "https://cdn.discordapp.com/embed/avatars/3.png", + 'def', self.avatar_size) self.set_title("Discover Voice") def set_bg(self, bg): @@ -137,11 +144,7 @@ class VoiceOverlayWindow(OverlayWindow): self.connected = is_connected self.redraw() - def draw(self, widget, context): - # Draw - self.do_draw(context) - - def do_draw(self, context): + def overlay_draw(self, _w, context, _data=None): self.context = context context.set_antialias(cairo.ANTIALIAS_GOOD) # Get size of window @@ -160,10 +163,9 @@ class VoiceOverlayWindow(OverlayWindow): w = self.w h = self.h context.translate(self.x, self.y) - context.rectangle(0,0,w,h) + context.rectangle(0, 0, w, h) context.clip() - context.set_operator(cairo.OPERATOR_OVER) if not self.connected: return @@ -219,16 +221,16 @@ class VoiceOverlayWindow(OverlayWindow): context.restore() self.context = None - def recv_avatar(self, id, pix): - if id == 'def': + def recv_avatar(self, identifier, pix): + if identifier == 'def': self.def_avatar = pix else: - self.avatars[id] = pix + self.avatars[identifier] = pix self.redraw() - def delete_avatar(self, id): + def delete_avatar(self, identifier): if id in self.avatars: - del self.avatars[id] + del self.avatars[identifier] def draw_avatar(self, context, user, y): # Ensure pixbuf for avatar @@ -282,7 +284,7 @@ class VoiceOverlayWindow(OverlayWindow): context.set_font_face(cairo.ToyFontFace( self.text_font, cairo.FontSlant.NORMAL, cairo.FontWeight.NORMAL)) context.set_font_size(self.text_size) - xb, yb, w, h, dx, dy = context.text_extents(string) + _xb, _yb, w, h, _dx, _dy = context.text_extents(string) ho = (self.avatar_size / 2) - (h / 2) if self.align_right: context.move_to(0, 0) diff --git a/discover_overlay/voice_settings.py b/discover_overlay/voice_settings.py index 776052c..abc43f5 100644 --- a/discover_overlay/voice_settings.py +++ b/discover_overlay/voice_settings.py @@ -1,27 +1,41 @@ -import gi -gi.require_version("Gtk", "3.0") +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . import json from configparser import ConfigParser +import gi from .draggable_window import DraggableWindow from .draggable_window_wayland import DraggableWindowWayland from .settings import SettingsWindow +gi.require_version("Gtk", "3.0") +# pylint: disable=wrong-import-position from gi.repository import Gtk, Gdk, Pango -import logging class VoiceSettingsWindow(SettingsWindow): def __init__(self, overlay): - Gtk.VBox.__init__(self) + SettingsWindow.__init__(self) self.overlay = overlay self.set_size_request(400, 200) self.connect("destroy", self.close_window) self.connect("delete-event", self.close_window) self.placement_window = None + self.align_x = None + self.align_y = None self.init_config() self.create_gui() - def present(self): + def present_settings(self): self.show_all() if not self.floating: self.align_x_widget.show() @@ -85,7 +99,8 @@ class VoiceSettingsWindow(SettingsWindow): self.overlay.set_only_speaking(self.only_speaking) self.overlay.set_highlight_self(self.highlight_self) self.overlay.set_icon_only(self.icon_only) - self.overlay.set_monitor(self.get_monitor_index(self.monitor),self.get_monitor_obj(self.monitor)) + self.overlay.set_monitor(self.get_monitor_index( + self.monitor), self.get_monitor_obj(self.monitor)) self.overlay.set_vert_edge_padding(self.vert_edge_padding) self.overlay.set_horz_edge_padding(self.horz_edge_padding) self.overlay.set_order(self.order) @@ -337,17 +352,15 @@ class VoiceSettingsWindow(SettingsWindow): self.add(box) - pass - def change_placement(self, button): if self.placement_window: - (x,y,w,h) = self.placement_window.get_coords() + (x, y, w, h) = self.placement_window.get_coords() self.floating_x = x self.floating_y = y self.floating_w = w self.floating_h = h self.overlay.set_floating(True, x, y, w, h) - self.save_config + self.save_config() if not self.overlay.is_wayland: button.set_label("Place Window") self.placement_window.close() @@ -357,12 +370,12 @@ class VoiceSettingsWindow(SettingsWindow): self.placement_window = DraggableWindowWayland( x=self.floating_x, y=self.floating_y, w=self.floating_w, h=self.floating_h, - message="Place & resize this window then press Green!",settings=self) + message="Place & resize this window then press Green!", settings=self) else: self.placement_window = DraggableWindow( x=self.floating_x, y=self.floating_y, w=self.floating_w, h=self.floating_h, - message="Place & resize this window then press Save!",settings=self) + message="Place & resize this window then press Save!", settings=self) if not self.overlay.is_wayland: button.set_label("Save this position") @@ -448,7 +461,6 @@ class VoiceSettingsWindow(SettingsWindow): m_s = mon.get_model() self.overlay.set_monitor(button.get_active(), mon) - self.monitor = m_s self.save_config() diff --git a/setup.py b/setup.py index 269646a..910c6e2 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setup( name='discover-overlay', author='trigg', author_email='', - version='0.2.2', + version='0.3.0', description='Voice chat overlay', long_description=readme(), long_description_content_type='text/markdown', From fddd68eeb17f58caf9c9dee95e9bd12f75f43b14 Mon Sep 17 00:00:00 2001 From: trigg Date: Mon, 19 Oct 2020 18:06:39 +0000 Subject: [PATCH 71/77] - Initialised all variables in respective __init__.. even if it gets set instantly elsewhere --- discover_overlay/overlay.py | 13 +++++++++---- discover_overlay/text_overlay.py | 3 +++ discover_overlay/text_settings.py | 29 ++++++++++++++++++++++++++--- discover_overlay/voice_overlay.py | 4 ++++ discover_overlay/voice_settings.py | 17 +++++++++++++++++ 5 files changed, 59 insertions(+), 7 deletions(-) diff --git a/discover_overlay/overlay.py b/discover_overlay/overlay.py index d4905ae..798ef75 100644 --- a/discover_overlay/overlay.py +++ b/discover_overlay/overlay.py @@ -34,11 +34,16 @@ class OverlayWindow(Gtk.Window): def __init__(self): Gtk.Window.__init__(self, type=self.detect_type()) screen = self.get_screen() - self.set_size_request(50, 50) - - self.connect('draw', self.overlay_draw) - self.compositing = False + self.text_font = None + self.text_size = None + self.x = None + self.y = None + self.w = None + self.h = None + + self.set_size_request(50, 50) + self.connect('draw', self.overlay_draw) # Set RGBA screen = self.get_screen() visual = screen.get_rgba_visual() diff --git a/discover_overlay/text_overlay.py b/discover_overlay/text_overlay.py index 389ac5c..b383fbc 100644 --- a/discover_overlay/text_overlay.py +++ b/discover_overlay/text_overlay.py @@ -32,6 +32,9 @@ class TextOverlayWindow(OverlayWindow): self.content = [] self.text_font = None self.text_size = 13 + self.text_time = None + self.show_attach = None + self.popup_style = None # 0, 0, self.text_size, self.text_size) self.pango_rect = Pango.Rectangle() self.pango_rect.width = self.text_size * Pango.SCALE diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index f224bcf..2c6fe75 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -29,9 +29,7 @@ class TextSettingsWindow(SettingsWindow): def __init__(self, overlay): SettingsWindow.__init__(self) self.overlay = overlay - self.set_size_request(400, 200) - self.connect("destroy", self.close_window) - self.connect("delete-event", self.close_window) + self.placement_window = None self.init_config() self.list_channels_keys = [] @@ -40,6 +38,31 @@ class TextSettingsWindow(SettingsWindow): self.list_guilds = {} self.ignore_channel_change = False self.ignore_guild_change = False + self.channel_lookup = None + self.channel_model = None + self.connector = None + self.guild_lookup = None + self.guild_model = None + self.guild_widget = None + self.align_x = None + self.align_y = None + self.monitor = None + self.floating = None + self.channel = None + self.guild = None + self.font = None + self.bg_col = None + self.fg_col = None + self.popup_style = None + self.text_time = None + self.show_attach = None + self.enabled = None + + self.set_size_request(400, 200) + self.connect("destroy", self.close_window) + self.connect("delete-event", self.close_window) + + self.init_config() self.create_gui() def update_channel_model(self): diff --git a/discover_overlay/voice_overlay.py b/discover_overlay/voice_overlay.py index 6ac1b06..3ee6be6 100644 --- a/discover_overlay/voice_overlay.py +++ b/discover_overlay/voice_overlay.py @@ -31,6 +31,10 @@ class VoiceOverlayWindow(OverlayWindow): self.icon_spacing = 8 self.vert_edge_padding = 0 self.horz_edge_padding = 0 + self.only_speaking = None + self.highlight_self = None + self.order = None + self.def_avatar = None self.round_avatar = True self.icon_only = True diff --git a/discover_overlay/voice_settings.py b/discover_overlay/voice_settings.py index abc43f5..23ea1a1 100644 --- a/discover_overlay/voice_settings.py +++ b/discover_overlay/voice_settings.py @@ -31,6 +31,23 @@ class VoiceSettingsWindow(SettingsWindow): self.placement_window = None self.align_x = None self.align_y = None + self.bg_col = None + self.fg_col = None + self.tk_col = None + self.mt_col = None + self.avatar_size = None + self.icon_spacing = None + self.text_padding = None + self.font = None + self.square_avatar = None + self.only_speaking = None + self.highlight_self = None + self.icon_only = None + self.monitor = None + self.vert_edge_padding = None + self.horz_edge_padding = None + self.floating = None + self.order = None self.init_config() self.create_gui() From ac2afa4d6a7d332583066fda9248c5fd3c4357b4 Mon Sep 17 00:00:00 2001 From: trigg Date: Mon, 19 Oct 2020 18:07:51 +0000 Subject: [PATCH 72/77] - No reason to expect bugs. Unless you're using Gnome or KDE. --- discover_overlay/overlay.py | 1 - 1 file changed, 1 deletion(-) diff --git a/discover_overlay/overlay.py b/discover_overlay/overlay.py index 798ef75..5f019b5 100644 --- a/discover_overlay/overlay.py +++ b/discover_overlay/overlay.py @@ -27,7 +27,6 @@ class OverlayWindow(Gtk.Window): self.is_wayland = False if "Wayland" in screen_type: self.is_wayland = True - print("Using Wayland GDK. Expect bugs") return Gtk.WindowType.TOPLEVEL return Gtk.WindowType.POPUP From 39537065795208ac1259c91eeb4131d552b1907a Mon Sep 17 00:00:00 2001 From: trigg Date: Mon, 19 Oct 2020 18:42:16 +0000 Subject: [PATCH 73/77] - Added some comments --- discover_overlay/discord_connector.py | 3 +++ discover_overlay/discover_overlay.py | 5 ++++- discover_overlay/general_settings.py | 5 ++++- discover_overlay/image_getter.py | 26 +++++++++++++++++--------- discover_overlay/overlay.py | 3 +++ discover_overlay/settings.py | 3 +++ discover_overlay/settings_window.py | 5 ++++- discover_overlay/text_overlay.py | 10 ++++++---- discover_overlay/text_settings.py | 8 ++++++-- discover_overlay/voice_overlay.py | 2 ++ discover_overlay/voice_settings.py | 3 +++ 11 files changed, 55 insertions(+), 18 deletions(-) diff --git a/discover_overlay/discord_connector.py b/discover_overlay/discord_connector.py index 1ef32d3..b27c2d2 100644 --- a/discover_overlay/discord_connector.py +++ b/discover_overlay/discord_connector.py @@ -10,6 +10,7 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +"""The connector for discord. Connects in as if it was Streamkit for OBS or Xsplit and communicates to get voice & text info to display""" import select import time import json @@ -21,6 +22,8 @@ import requests class DiscordConnector: + """The connector for discord. Connects in as if it was Streamkit for OBS or Xsplit and communicates to get voice & text info to display""" + def __init__(self, text_settings, voice_settings, text_overlay, voice_overlay): self.text_settings = text_settings self.text_overlay = text_overlay diff --git a/discover_overlay/discover_overlay.py b/discover_overlay/discover_overlay.py index a06a3a3..0a7c642 100755 --- a/discover_overlay/discover_overlay.py +++ b/discover_overlay/discover_overlay.py @@ -10,10 +10,11 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +"""Main application class""" import os import sys -import gi import logging +import gi import pidfile from .settings_window import MainSettingsWindow from .voice_overlay import VoiceOverlayWindow @@ -30,6 +31,8 @@ except ModuleNotFoundError: class Discover: + """Main application class""" + def __init__(self, rpc_file, args): self.ind = None self.tray = None diff --git a/discover_overlay/general_settings.py b/discover_overlay/general_settings.py index 3bb179c..3a6654d 100644 --- a/discover_overlay/general_settings.py +++ b/discover_overlay/general_settings.py @@ -10,8 +10,9 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import gi +"""Core Settings Tab""" from configparser import ConfigParser +import gi from .settings import SettingsWindow from .autostart import Autostart gi.require_version("Gtk", "3.0") @@ -20,6 +21,8 @@ from gi.repository import Gtk class GeneralSettingsWindow(SettingsWindow): + """Core Settings Tab""" + def __init__(self, overlay, overlay2): SettingsWindow.__init__(self) self.overlay = overlay diff --git a/discover_overlay/image_getter.py b/discover_overlay/image_getter.py index 7ebfbbf..73c7632 100644 --- a/discover_overlay/image_getter.py +++ b/discover_overlay/image_getter.py @@ -10,20 +10,22 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import gi +"""Functions & Classes to assist image loading.""" import urllib -import requests import threading -import cairo import logging +import gi +import requests +import cairo import PIL.Image as Image -gi.require_version("Gtk", "3.0") gi.require_version('GdkPixbuf', '2.0') # pylint: disable=wrong-import-position from gi.repository import Gio, GdkPixbuf -class Image_Getter(): +class ImageGetter(): + """Older attempt. Not advised as it can't manage anything but PNG. Loads to GDK Pixmap""" + def __init__(self, func, url, identifier, size): self.func = func self.id = identifier @@ -51,7 +53,9 @@ class Image_Getter(): logging.error(exception) -class Surface_Getter(): +class SurfaceGetter(): + """Download and decode image using PIL and store as a cairo surface""" + def __init__(self, func, url, identifier, size): self.func = func self.id = identifier @@ -59,7 +63,7 @@ class Surface_Getter(): self.size = size def get_url(self): - + """Downloads and decodes""" try: resp = requests.get(self.url, stream=True, headers={ 'Referer': 'https://streamkit.discord.com/overlay/voice', 'User-Agent': 'Mozilla/5.0'}) @@ -96,18 +100,21 @@ class Surface_Getter(): def get_image(func, identifier, ava, size): - image_getter = Image_Getter(func, identifier, ava, size) + """Download to GDK Pixmap""" + image_getter = ImageGetter(func, identifier, ava, size) t = threading.Thread(target=image_getter.get_url, args=()) t.start() def get_surface(func, identifier, ava, size): - image_getter = Surface_Getter(func, identifier, ava, size) + """Download to cairo surface""" + image_getter = SurfaceGetter(func, identifier, ava, size) t = threading.Thread(target=image_getter.get_url, args=()) t.start() def get_aspected_size(img, w, h, anchor=0, hanchor=0): + """Get dimensions of image keeping current aspect ratio""" px = img.get_width() py = img.get_height() if py < 1 or h < 1: @@ -135,6 +142,7 @@ def get_aspected_size(img, w, h, anchor=0, hanchor=0): def draw_img_to_rect(img, ctx, x, y, w, h, path=False, aspect=False, anchor=0, hanchor=0): + """Draw cairo surface onto context""" # Path - only add the path do not fill : True/False # Aspect - keep aspect ratio : True/False # Anchor - with aspect : 0=left 1=middle 2=right diff --git a/discover_overlay/overlay.py b/discover_overlay/overlay.py index 5f019b5..9f1109d 100644 --- a/discover_overlay/overlay.py +++ b/discover_overlay/overlay.py @@ -10,6 +10,7 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +"""Overlay parent class. Helpful if we need more overlay types without copy-and-pasting too much code""" import sys import logging import gi @@ -20,6 +21,8 @@ from gi.repository import Gtk, Gdk, GtkLayerShell class OverlayWindow(Gtk.Window): + """Overlay parent class. Helpful if we need more overlay types without copy-and-pasting too much code""" + def detect_type(self): window = Gtk.Window() screen = window.get_screen() diff --git a/discover_overlay/settings.py b/discover_overlay/settings.py index e5bbecf..38c5387 100644 --- a/discover_overlay/settings.py +++ b/discover_overlay/settings.py @@ -10,6 +10,7 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +"""Settings tab parent class. Helpful if we need more overlay types without copy-and-pasting too much code""" import os import logging import gi @@ -25,6 +26,8 @@ except ModuleNotFoundError: class SettingsWindow(Gtk.VBox): + """Settings tab parent class. Helpful if we need more overlay types without copy-and-pasting too much code""" + def __init__(self): Gtk.VBox.__init__(self) self.placement_window = None diff --git a/discover_overlay/settings_window.py b/discover_overlay/settings_window.py index c5bbe55..ec7bc05 100644 --- a/discover_overlay/settings_window.py +++ b/discover_overlay/settings_window.py @@ -10,16 +10,19 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +"""Settings window holding all settings tab""" +import gi from .voice_settings import VoiceSettingsWindow from .text_settings import TextSettingsWindow from .general_settings import GeneralSettingsWindow -import gi gi.require_version("Gtk", "3.0") # pylint: disable=wrong-import-position from gi.repository import Gtk class MainSettingsWindow(Gtk.Window): + """Settings window holding all settings tab""" + def __init__(self, text_overlay, voice_overlay): Gtk.Window.__init__(self) diff --git a/discover_overlay/text_overlay.py b/discover_overlay/text_overlay.py index b383fbc..654978a 100644 --- a/discover_overlay/text_overlay.py +++ b/discover_overlay/text_overlay.py @@ -10,14 +10,14 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -from .overlay import OverlayWindow -import cairo +"""Overlay window for text""" import logging import time import re -from .image_getter import get_surface, draw_img_to_rect, get_aspected_size +import cairo import gi +from .image_getter import get_surface, draw_img_to_rect, get_aspected_size +from .overlay import OverlayWindow gi.require_version("Gtk", "3.0") gi.require_version('PangoCairo', '1.0') # pylint: disable=wrong-import-position @@ -25,6 +25,8 @@ from gi.repository import Pango, PangoCairo class TextOverlayWindow(OverlayWindow): + """Overlay window for voice""" + def __init__(self, discover): OverlayWindow.__init__(self) self.discover = discover diff --git a/discover_overlay/text_settings.py b/discover_overlay/text_settings.py index 2c6fe75..9256ace 100644 --- a/discover_overlay/text_settings.py +++ b/discover_overlay/text_settings.py @@ -10,13 +10,15 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +"""Text setting tab on settings window""" import json +import logging from configparser import ConfigParser +import gi from .draggable_window import DraggableWindow from .draggable_window_wayland import DraggableWindowWayland from .settings import SettingsWindow -import logging -import gi + gi.require_version("Gtk", "3.0") # pylint: disable=wrong-import-position from gi.repository import Gtk, Gdk, Pango @@ -26,6 +28,8 @@ GUILD_DEFAULT_VALUE = "0" class TextSettingsWindow(SettingsWindow): + """Text setting tab on settings window""" + def __init__(self, overlay): SettingsWindow.__init__(self) self.overlay = overlay diff --git a/discover_overlay/voice_overlay.py b/discover_overlay/voice_overlay.py index 3ee6be6..582270c 100644 --- a/discover_overlay/voice_overlay.py +++ b/discover_overlay/voice_overlay.py @@ -10,6 +10,7 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +"""Overlay window for voice""" import math import cairo from .overlay import OverlayWindow @@ -17,6 +18,7 @@ from .image_getter import get_surface, draw_img_to_rect class VoiceOverlayWindow(OverlayWindow): + """Overlay window for voice""" def __init__(self, discover): OverlayWindow.__init__(self) diff --git a/discover_overlay/voice_settings.py b/discover_overlay/voice_settings.py index 23ea1a1..e4a98cd 100644 --- a/discover_overlay/voice_settings.py +++ b/discover_overlay/voice_settings.py @@ -10,6 +10,7 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +"""Voice setting tab on settings window""" import json from configparser import ConfigParser import gi @@ -22,6 +23,8 @@ from gi.repository import Gtk, Gdk, Pango class VoiceSettingsWindow(SettingsWindow): + """Voice setting tab on settings window""" + def __init__(self, overlay): SettingsWindow.__init__(self) self.overlay = overlay From a2a31bbc8470006c648ab11f6fdfb136504c94f6 Mon Sep 17 00:00:00 2001 From: midget3111 Date: Mon, 19 Oct 2020 20:07:30 +0100 Subject: [PATCH 74/77] update README.md Added gtk-layer-shell to dependencies section. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 854db0c..7b8a834 100644 --- a/README.md +++ b/README.md @@ -28,11 +28,11 @@ It is advised to install python-gobject from your own package manager. #### Debian/Ubuntu -`apt install python3-gi` +`apt install python3-gi gtk-layer-shell` #### Arch -`pacman -S python-gobject` +`pacman -S python-gobject gtk-layer-shell` ## Usage From cf936286b8a7f292c5c5e2416c03253be3e7d2cf Mon Sep 17 00:00:00 2001 From: trigg Date: Mon, 19 Oct 2020 19:11:12 +0000 Subject: [PATCH 75/77] - Only attempt GtkLayerShell import --- discover_overlay/discover_overlay.py | 2 +- discover_overlay/draggable_window_wayland.py | 6 +++++- discover_overlay/overlay.py | 6 +++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/discover_overlay/discover_overlay.py b/discover_overlay/discover_overlay.py index 0a7c642..f66ea20 100755 --- a/discover_overlay/discover_overlay.py +++ b/discover_overlay/discover_overlay.py @@ -21,7 +21,7 @@ from .voice_overlay import VoiceOverlayWindow from .text_overlay import TextOverlayWindow from .discord_connector import DiscordConnector gi.require_version("Gtk", "3.0") -# pylint: disable=wrong-import-position +# pylint: disable=wrong-import-position,wrong-import-order from gi.repository import Gtk, GLib, Gio try: diff --git a/discover_overlay/draggable_window_wayland.py b/discover_overlay/draggable_window_wayland.py index fefa742..c587381 100644 --- a/discover_overlay/draggable_window_wayland.py +++ b/discover_overlay/draggable_window_wayland.py @@ -15,7 +15,11 @@ import cairo import gi gi.require_version("Gtk", "3.0") # pylint: disable=wrong-import-position -from gi.repository import Gtk, Gdk, GtkLayerShell +from gi.repository import Gtk, Gdk +try: + from gi.repository import GtkLayerShell +except ImportError: + pass class DraggableWindowWayland(Gtk.Window): diff --git a/discover_overlay/overlay.py b/discover_overlay/overlay.py index 9f1109d..5639462 100644 --- a/discover_overlay/overlay.py +++ b/discover_overlay/overlay.py @@ -17,7 +17,11 @@ import gi import cairo gi.require_version("Gtk", "3.0") # pylint: disable=wrong-import-position -from gi.repository import Gtk, Gdk, GtkLayerShell +from gi.repository import Gtk, Gdk +try: + from gi.repository import GtkLayerShell +except ImportError: + pass class OverlayWindow(Gtk.Window): From 7df1a72a77bc9f4a6562ade9312a346a64ad7926 Mon Sep 17 00:00:00 2001 From: midget3111 Date: Mon, 19 Oct 2020 20:14:11 +0100 Subject: [PATCH 76/77] Premature gtk-layer-shellalation Removed gtk-layer-shell requirement --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7b8a834..854db0c 100644 --- a/README.md +++ b/README.md @@ -28,11 +28,11 @@ It is advised to install python-gobject from your own package manager. #### Debian/Ubuntu -`apt install python3-gi gtk-layer-shell` +`apt install python3-gi` #### Arch -`pacman -S python-gobject gtk-layer-shell` +`pacman -S python-gobject` ## Usage From 8e8b060889aef2d02f55ca6bbc0544559868be42 Mon Sep 17 00:00:00 2001 From: trigg Date: Tue, 20 Oct 2020 09:28:40 +0000 Subject: [PATCH 77/77] - Bumped version --- setup.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 910c6e2..bddd809 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setup( name='discover-overlay', author='trigg', author_email='', - version='0.3.0', + version='0.3.1', description='Voice chat overlay', long_description=readme(), long_description_content_type='text/markdown', @@ -17,7 +17,8 @@ setup( packages=find_packages(), include_package_data=True, data_files=[ - ('share/applications', ['discover_overlay.desktop','discover_overlay_conf.desktop','discover_overlay_close.desktop']), + ('share/applications', ['discover_overlay.desktop', + 'discover_overlay_conf.desktop', 'discover_overlay_close.desktop']), ('share/icons', ['discover-overlay.png']) ], install_requires=[