@@ 0,0 1,25 @@
+import threading
+from time import sleep
+
+class Queue():
+ tasks = []
+ thread = None
+ starting = False
+ def __init__(self, workers=1):
+ for i in range(workers):
+ self.thread = threading.Thread(target=self.run, name=str(i))
+ self.thread.daemon = True
+ self.thread.start()
+ def run(self):
+ while True:
+ while not self.tasks:
+ sleep(1)
+ task = self.tasks.pop(0)
+ func = task[0]
+ args = task[1]
+ # run task
+ func(*args)
+ def add(self, func, *args):
+ self.tasks.append((func, args))
+
+queue = Queue(1)
@@ 7,6 7,8 @@ from melon.servers import Resource,Video,Playlist,Channel
from melon.servers.utils import pixbuf_from_url
from melon.widgets.iconbutton import IconButton
from melon.models import PlaylistWrapperType,PlaylistWrapper
+import threading
+from melon.background import queue
class AdaptiveFeedItem(Adw.ActionRow):
"""
@@ 14,16 16,30 @@ class AdaptiveFeedItem(Adw.ActionRow):
"""
def __init__(self, resource:Resource, show_preview=True, clickable=True, *args, **kwargs):
super().__init__(*args, **kwargs)
- pixbuf = None
+ self.res = resource
+ self.show_preview = show_preview
+ self.clickable = clickable
+ self.update()
+ def set_resource(self, resource: Resource):
+ self.res = resource
+ self.update()
+ def update(self):
+ if self.res is None:
+ return
+ resource = self.res
+ show_preview = self.show_preview
+ clickable = self.clickable
+ self.set_activatable(clickable)
+ self.set_action_target_value(
+ GLib.Variant("as", [resource.server, resource.id]))
+ thumb_url = None
if isinstance(resource, Video):
- if show_preview:
- pixbuf = pixbuf_from_url(resource.thumbnail)
+ thumb_url = resource.thumbnail
self.set_title(resource.title.replace("&","&"))
self.set_subtitle(resource.channel[0].replace("&","&"))
self.set_action_name("win.player")
elif isinstance(resource, Playlist):
- if show_preview:
- pixbuf = pixbuf_from_url(resource.thumbnail)
+ thumb_url = resource.thumbnail
self.set_title(resource.title.replace("&","&"))
pad = ""
if len(resource.description) > 80:
@@ 32,8 48,7 @@ class AdaptiveFeedItem(Adw.ActionRow):
self.set_subtitle(sub.replace("&","&"))
self.set_action_name("win.browse_playlist")
elif isinstance(resource, Channel):
- if show_preview:
- pixbuf = pixbuf_from_url(resource.avatar)
+ thumb_url = resource.avatar
self.set_title(resource.name.replace("&","&"))
pad = ""
if len(resource.bio) > 80:
@@ 43,16 58,22 @@ class AdaptiveFeedItem(Adw.ActionRow):
self.set_action_name("win.browse_channel")
self.preview = Adw.Avatar()
self.preview.set_size(48)
+ self.preview.set_show_initials(True)
+ self.preview.set_text(self.get_title())
+ self.add_prefix(self.preview)
+ if show_preview:
+ queue.add(self.update_avatar, thumb_url)
+
+ def update_avatar(self, url):
+ pixbuf = pixbuf_from_url(url)
if not pixbuf is None:
texture = Gdk.Texture.new_for_pixbuf(pixbuf)
- self.preview.set_custom_image(texture)
- else:
- self.preview.set_show_initials(True)
- self.preview.set_text(self.get_title())
- self.add_prefix(self.preview)
- self.set_activatable(clickable)
- self.set_action_target_value(
- GLib.Variant("as", [resource.server, resource.id]))
+ GLib.idle_add(self.complete_avatar, texture)
+ def complete_avatar(self, texture):
+ self.preview.set_custom_image(texture)
+ # return false to cancel the idle job
+ return False
+
class AdaptivePlaylistFeedItem(Adw.ActionRow):
def __init__(self, playlist:PlaylistWrapper, show_preview=True, *args, **kwargs):