138 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			138 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# Python imports
 | 
						|
import os, threading, subprocess, time, inspect, hashlib
 | 
						|
from datetime import datetime
 | 
						|
 | 
						|
# Gtk imports
 | 
						|
import gi
 | 
						|
gi.require_version('Gtk', '3.0')
 | 
						|
gi.require_version('GdkPixbuf', '2.0')
 | 
						|
from gi.repository import Gtk, GLib, Gio, GdkPixbuf
 | 
						|
 | 
						|
# Application imports
 | 
						|
from plugins.plugin_base import PluginBase
 | 
						|
 | 
						|
 | 
						|
# NOTE: Threads WILL NOT die with parent's destruction.
 | 
						|
def threaded(fn):
 | 
						|
    def wrapper(*args, **kwargs):
 | 
						|
        threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=False).start()
 | 
						|
    return wrapper
 | 
						|
 | 
						|
# NOTE: Threads WILL die with parent's destruction.
 | 
						|
def daemon_threaded(fn):
 | 
						|
    def wrapper(*args, **kwargs):
 | 
						|
        threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
 | 
						|
    return wrapper
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
class Plugin(PluginBase):
 | 
						|
    def __init__(self):
 | 
						|
        super().__init__()
 | 
						|
 | 
						|
        self.path                   = os.path.dirname(os.path.realpath(__file__))
 | 
						|
        self._GLADE_FILE            = f"{self.path}/re_thumbnailer.glade"
 | 
						|
        self.name                   = "VOD Thumbnailer"  # NOTE: Need to remove after establishing private bidirectional 1-1 message bus
 | 
						|
                                                         #       where self.name should not be needed for message comms
 | 
						|
 | 
						|
        self._thumbnailer_dialog    = None
 | 
						|
        self._thumbnail_preview_img = None
 | 
						|
        self._scrub_step            = None
 | 
						|
        self._file_name             = None
 | 
						|
        self._file_location         = None
 | 
						|
        self._file_hash             = None
 | 
						|
 | 
						|
 | 
						|
    def run(self):
 | 
						|
        self._builder           = Gtk.Builder()
 | 
						|
        self._builder.add_from_file(self._GLADE_FILE)
 | 
						|
 | 
						|
        classes  = [self]
 | 
						|
        handlers = {}
 | 
						|
        for c in classes:
 | 
						|
            methods = None
 | 
						|
            try:
 | 
						|
                methods = inspect.getmembers(c, predicate=inspect.ismethod)
 | 
						|
                handlers.update(methods)
 | 
						|
            except Exception as e:
 | 
						|
                print(repr(e))
 | 
						|
 | 
						|
        self._builder.connect_signals(handlers)
 | 
						|
 | 
						|
        self._thumbnailer_dialog    = self._builder.get_object("thumbnailer_dialog")
 | 
						|
        self._scrub_step            = self._builder.get_object("scrub_step")
 | 
						|
        self._file_name             = self._builder.get_object("file_name")
 | 
						|
        self._file_location         = self._builder.get_object("file_location")
 | 
						|
        self._thumbnail_preview_img = self._builder.get_object("thumbnail_preview_img")
 | 
						|
        self._file_hash             = self._builder.get_object("file_hash")
 | 
						|
 | 
						|
    def generate_reference_ui_element(self):
 | 
						|
        pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(f"{self.path}/../../icons/video.png", 16, 16, True)
 | 
						|
        icon   = Gtk.Image.new_from_pixbuf(pixbuf)
 | 
						|
        item   = Gtk.ImageMenuItem("Delete")
 | 
						|
        item.set_image( icon )
 | 
						|
        item.connect("activate", self._show_thumbnailer_page)
 | 
						|
        item.set_always_show_image(True)
 | 
						|
        return item
 | 
						|
 | 
						|
 | 
						|
    @threaded
 | 
						|
    def _show_thumbnailer_page(self, widget=None, eve=None):
 | 
						|
        self._event_system.emit("get_current_state")
 | 
						|
 | 
						|
        state               = self._fm_state
 | 
						|
        self._event_message = None
 | 
						|
 | 
						|
        GLib.idle_add(self._process_changes, (state))
 | 
						|
 | 
						|
    def _process_changes(self, state):
 | 
						|
        self._fm_state = None
 | 
						|
 | 
						|
        if len(state.selected_files) == 1:
 | 
						|
            if state.selected_files[0].lower().endswith(state.tab.fvideos):
 | 
						|
                self._fm_state = state
 | 
						|
                self._set_ui_data()
 | 
						|
                response   = self._thumbnailer_dialog.run()
 | 
						|
                if response in [Gtk.ResponseType.CLOSE, Gtk.ResponseType.DELETE_EVENT]:
 | 
						|
                    self._thumbnailer_dialog.hide()
 | 
						|
 | 
						|
 | 
						|
    def _regenerate_thumbnail(self, widget=None, eve=None):
 | 
						|
        scrub_percent = int(self._scrub_step.get_value())
 | 
						|
        file          = self._file_name.get_text()
 | 
						|
        dir           = self._file_location.get_text()
 | 
						|
        file_hash     = self._file_hash.get_text()
 | 
						|
        hash_img_pth  = f"{self._fm_state.tab.ABS_THUMBS_PTH}/{file_hash}.jpg"
 | 
						|
 | 
						|
        try:
 | 
						|
            os.remove(hash_img_pth) if os.path.isfile(hash_img_pth) else ...
 | 
						|
 | 
						|
            self._fm_state.tab.create_thumbnail(dir, file, f"{scrub_percent}%")
 | 
						|
            preview_pixbuf = GdkPixbuf.Pixbuf.new_from_file(hash_img_pth)
 | 
						|
            self._thumbnail_preview_img.set_from_pixbuf(preview_pixbuf)
 | 
						|
 | 
						|
            img_pixbuf = self._fm_state.tab.create_scaled_image(hash_img_pth)
 | 
						|
            tree_pth   = self._fm_state.icon_grid.get_selected_items()[0]
 | 
						|
            itr        = self._fm_state.store.get_iter(tree_pth)
 | 
						|
            pixbuff    = self._fm_state.store.get(itr, 0)[0]
 | 
						|
            self._fm_state.store.set(itr, 0, img_pixbuf)
 | 
						|
        except Exception as e:
 | 
						|
            print(repr(e))
 | 
						|
            print("Couldn't regenerate thumbnail!")
 | 
						|
 | 
						|
 | 
						|
    def _set_ui_data(self):
 | 
						|
        uri            = self._fm_state.selected_files[0]
 | 
						|
        path           = self._fm_state.tab.get_current_directory()
 | 
						|
        parts          = uri.split("/")
 | 
						|
 | 
						|
        file_hash      = hashlib.sha256(str.encode(uri)).hexdigest()
 | 
						|
        hash_img_pth   = f"{self._fm_state.tab.ABS_THUMBS_PTH}/{file_hash}.jpg"
 | 
						|
        preview_pixbuf = GdkPixbuf.Pixbuf.new_from_file(hash_img_pth)
 | 
						|
 | 
						|
        self._thumbnail_preview_img.set_from_pixbuf(preview_pixbuf)
 | 
						|
        self._file_name.set_text(parts[ len(parts) - 1 ])
 | 
						|
        self._file_location.set_text(path)
 | 
						|
        self._file_hash.set_text(file_hash)
 |