Updated VOD Thumbnailer, added icon gen logic #6
@@ -35,6 +35,7 @@ class Plugin:
 | 
			
		||||
        self._builder               = None
 | 
			
		||||
        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
 | 
			
		||||
@@ -63,6 +64,7 @@ class Plugin:
 | 
			
		||||
        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")
 | 
			
		||||
@@ -99,40 +101,44 @@ class Plugin:
 | 
			
		||||
                self._state = state
 | 
			
		||||
                self._set_ui_data()
 | 
			
		||||
                response   = self._thumbnailer_dialog.run()
 | 
			
		||||
                if response in [Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT]:
 | 
			
		||||
                if response in [Gtk.ResponseType.CLOSE, Gtk.ResponseType.DELETE_EVENT]:
 | 
			
		||||
                    self._thumbnailer_dialog.hide()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def _regenerate_thumbnail(self, widget=None, eve=None):
 | 
			
		||||
        print("Regenerating thumbnail...")
 | 
			
		||||
        file      = self._file_name.get_text()
 | 
			
		||||
        dir       = self._file_location.get_text()
 | 
			
		||||
        file_hash = self._file_hash.get_text()
 | 
			
		||||
        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._state.tab.ABS_THUMBS_PTH}/{file_hash}.jpg"
 | 
			
		||||
 | 
			
		||||
        hash_img_pth = f"{self._state.tab.ABS_THUMBS_PTH}/{file_hash}.jpg"
 | 
			
		||||
        try:
 | 
			
		||||
            if os.path.isfile(hash_img_pth):
 | 
			
		||||
                os.remove(hash_img_pth)
 | 
			
		||||
            os.remove(hash_img_pth) if os.path.isfile(hash_img_pth) else ...
 | 
			
		||||
 | 
			
		||||
            img_pixbuf = self._state.tab.create_icon(dir, file)
 | 
			
		||||
            self._thumbnail_preview_img.set_from_pixbuf(img_pixbuf)
 | 
			
		||||
            self._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._state.tab.create_scaled_image(hash_img_pth)
 | 
			
		||||
            tree_pth   = self._state.icon_grid.get_selected_items()[0]
 | 
			
		||||
            itr        = self._state.store.get_iter(tree_pth)
 | 
			
		||||
            pixbuff    = self._state.store.get(itr, 0)[0]
 | 
			
		||||
            self._state.store.set(itr, 0, img_pixbuf)
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            print(repr(e))
 | 
			
		||||
            print("Couldn't regenerate thumbnail!")
 | 
			
		||||
 | 
			
		||||
    def _use_selected_thumbnail(self, widget=None, eve=None):
 | 
			
		||||
        print("_use_selected_thumbnail stub...")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def _set_ui_data(self):
 | 
			
		||||
        uri          = self._state.selected_files[0]
 | 
			
		||||
        path         = self._state.tab.get_current_directory()
 | 
			
		||||
        parts        = uri.split("/")
 | 
			
		||||
        uri            = self._state.selected_files[0]
 | 
			
		||||
        path           = self._state.tab.get_current_directory()
 | 
			
		||||
        parts          = uri.split("/")
 | 
			
		||||
 | 
			
		||||
        file_hash    = hashlib.sha256(str.encode(uri)).hexdigest()
 | 
			
		||||
        hash_img_pth = f"{self._state.tab.ABS_THUMBS_PTH}/{file_hash}.jpg"
 | 
			
		||||
        img_pixbuf   = GdkPixbuf.Pixbuf.new_from_file(hash_img_pth)
 | 
			
		||||
        file_hash      = hashlib.sha256(str.encode(uri)).hexdigest()
 | 
			
		||||
        hash_img_pth   = f"{self._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(img_pixbuf)
 | 
			
		||||
        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)
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,13 @@
 | 
			
		||||
<!-- Generated with glade 3.38.2 -->
 | 
			
		||||
<interface>
 | 
			
		||||
  <requires lib="gtk+" version="3.16"/>
 | 
			
		||||
  <object class="GtkAdjustment" id="scrub_step_adjuster">
 | 
			
		||||
    <property name="lower">1</property>
 | 
			
		||||
    <property name="upper">100</property>
 | 
			
		||||
    <property name="value">65</property>
 | 
			
		||||
    <property name="step-increment">1</property>
 | 
			
		||||
    <property name="page-increment">10</property>
 | 
			
		||||
  </object>
 | 
			
		||||
  <object class="GtkDialog" id="thumbnailer_dialog">
 | 
			
		||||
    <property name="can-focus">False</property>
 | 
			
		||||
    <property name="border-width">6</property>
 | 
			
		||||
@@ -26,7 +33,7 @@
 | 
			
		||||
            <property name="layout-style">end</property>
 | 
			
		||||
            <child>
 | 
			
		||||
              <object class="GtkButton" id="cancel_button">
 | 
			
		||||
                <property name="label">gtk-cancel</property>
 | 
			
		||||
                <property name="label">gtk-close</property>
 | 
			
		||||
                <property name="visible">True</property>
 | 
			
		||||
                <property name="can-focus">True</property>
 | 
			
		||||
                <property name="can-default">True</property>
 | 
			
		||||
@@ -66,14 +73,55 @@
 | 
			
		||||
              </packing>
 | 
			
		||||
            </child>
 | 
			
		||||
            <child>
 | 
			
		||||
              <placeholder/>
 | 
			
		||||
              <object class="GtkBox">
 | 
			
		||||
                <property name="visible">True</property>
 | 
			
		||||
                <property name="can-focus">False</property>
 | 
			
		||||
                <property name="orientation">vertical</property>
 | 
			
		||||
                <child>
 | 
			
		||||
                  <object class="GtkLabel">
 | 
			
		||||
                    <property name="visible">True</property>
 | 
			
		||||
                    <property name="can-focus">False</property>
 | 
			
		||||
                    <property name="margin-start">5</property>
 | 
			
		||||
                    <property name="label" translatable="yes">New Thumbnail Scrub Step: </property>
 | 
			
		||||
                  </object>
 | 
			
		||||
                  <packing>
 | 
			
		||||
                    <property name="expand">False</property>
 | 
			
		||||
                    <property name="fill">True</property>
 | 
			
		||||
                    <property name="position">0</property>
 | 
			
		||||
                  </packing>
 | 
			
		||||
                </child>
 | 
			
		||||
                <child>
 | 
			
		||||
                  <object class="GtkScale" id="scrub_step">
 | 
			
		||||
                    <property name="visible">True</property>
 | 
			
		||||
                    <property name="can-focus">True</property>
 | 
			
		||||
                    <property name="margin-start">5</property>
 | 
			
		||||
                    <property name="margin-end">5</property>
 | 
			
		||||
                    <property name="adjustment">scrub_step_adjuster</property>
 | 
			
		||||
                    <property name="show-fill-level">True</property>
 | 
			
		||||
                    <property name="round-digits">1</property>
 | 
			
		||||
                    <property name="digits">0</property>
 | 
			
		||||
                    <property name="value-pos">right</property>
 | 
			
		||||
                    <signal name="value-changed" handler="_regenerate_thumbnail" swapped="no"/>
 | 
			
		||||
                  </object>
 | 
			
		||||
                  <packing>
 | 
			
		||||
                    <property name="expand">True</property>
 | 
			
		||||
                    <property name="fill">True</property>
 | 
			
		||||
                    <property name="position">1</property>
 | 
			
		||||
                  </packing>
 | 
			
		||||
                </child>
 | 
			
		||||
              </object>
 | 
			
		||||
              <packing>
 | 
			
		||||
                <property name="expand">False</property>
 | 
			
		||||
                <property name="fill">True</property>
 | 
			
		||||
                <property name="position">1</property>
 | 
			
		||||
              </packing>
 | 
			
		||||
            </child>
 | 
			
		||||
            <child>
 | 
			
		||||
              <object class="GtkTable" id="general_table">
 | 
			
		||||
                <property name="visible">True</property>
 | 
			
		||||
                <property name="can-focus">False</property>
 | 
			
		||||
                <property name="border-width">4</property>
 | 
			
		||||
                <property name="n-rows">4</property>
 | 
			
		||||
                <property name="n-rows">3</property>
 | 
			
		||||
                <property name="n-columns">2</property>
 | 
			
		||||
                <property name="column-spacing">12</property>
 | 
			
		||||
                <property name="row-spacing">6</property>
 | 
			
		||||
@@ -136,34 +184,6 @@
 | 
			
		||||
                    <property name="y-options"/>
 | 
			
		||||
                  </packing>
 | 
			
		||||
                </child>
 | 
			
		||||
                <child>
 | 
			
		||||
                  <object class="GtkButton">
 | 
			
		||||
                    <property name="label" translatable="yes">Regenerate</property>
 | 
			
		||||
                    <property name="visible">True</property>
 | 
			
		||||
                    <property name="can-focus">True</property>
 | 
			
		||||
                    <property name="receives-default">True</property>
 | 
			
		||||
                    <signal name="released" handler="_regenerate_thumbnail" swapped="no"/>
 | 
			
		||||
                  </object>
 | 
			
		||||
                  <packing>
 | 
			
		||||
                    <property name="left-attach">1</property>
 | 
			
		||||
                    <property name="right-attach">2</property>
 | 
			
		||||
                    <property name="top-attach">3</property>
 | 
			
		||||
                    <property name="bottom-attach">4</property>
 | 
			
		||||
                  </packing>
 | 
			
		||||
                </child>
 | 
			
		||||
                <child>
 | 
			
		||||
                  <object class="GtkButton">
 | 
			
		||||
                    <property name="label" translatable="yes">Use Selected</property>
 | 
			
		||||
                    <property name="visible">True</property>
 | 
			
		||||
                    <property name="can-focus">True</property>
 | 
			
		||||
                    <property name="receives-default">True</property>
 | 
			
		||||
                    <signal name="released" handler="_use_selected_thumbnail" swapped="no"/>
 | 
			
		||||
                  </object>
 | 
			
		||||
                  <packing>
 | 
			
		||||
                    <property name="top-attach">3</property>
 | 
			
		||||
                    <property name="bottom-attach">4</property>
 | 
			
		||||
                  </packing>
 | 
			
		||||
                </child>
 | 
			
		||||
                <child>
 | 
			
		||||
                  <object class="GtkLabel" id="hash">
 | 
			
		||||
                    <property name="visible">True</property>
 | 
			
		||||
@@ -213,7 +233,7 @@
 | 
			
		||||
      </object>
 | 
			
		||||
    </child>
 | 
			
		||||
    <action-widgets>
 | 
			
		||||
      <action-widget response="-6">cancel_button</action-widget>
 | 
			
		||||
      <action-widget response="-7">cancel_button</action-widget>
 | 
			
		||||
    </action-widgets>
 | 
			
		||||
  </object>
 | 
			
		||||
</interface>
 | 
			
		||||
 
 | 
			
		||||
@@ -145,7 +145,6 @@ class Controller_Data:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        selected_files       = state.icon_grid.get_selected_items()
 | 
			
		||||
        # if self.selected_files:
 | 
			
		||||
        if selected_files:
 | 
			
		||||
            state.selected_files = self.format_to_uris(state.store, state.wid, state.tid, selected_files, True)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -147,7 +147,7 @@ class WindowMixin(TabMixin):
 | 
			
		||||
        ctx.remove_class("notebook-unselected-focus")
 | 
			
		||||
        ctx.add_class("notebook-selected-focus")
 | 
			
		||||
 | 
			
		||||
        self.window.set_title(f"SolarFM ~ {dir}")
 | 
			
		||||
        self.window.set_title(f"{app_name} ~ {dir}")
 | 
			
		||||
        self.set_bottom_labels(tab)
 | 
			
		||||
 | 
			
		||||
    def set_path_text(self, wid, tid):
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ class Icon(DesktopIconMixin, VideoIconMixin):
 | 
			
		||||
            if file.lower().endswith(self.fvideos):              # Video icon
 | 
			
		||||
                thumbnl = self.create_thumbnail(dir, file)
 | 
			
		||||
            elif file.lower().endswith(self.fimages):            # Image Icon
 | 
			
		||||
                thumbnl = self.create_scaled_image(full_path, self.video_icon_wh)
 | 
			
		||||
                thumbnl = self.create_scaled_image(full_path)
 | 
			
		||||
            elif full_path.lower().endswith( ('.desktop',) ):    # .desktop file parsing
 | 
			
		||||
                thumbnl = self.parse_desktop_files(full_path)
 | 
			
		||||
 | 
			
		||||
@@ -38,13 +38,13 @@ class Icon(DesktopIconMixin, VideoIconMixin):
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            return None
 | 
			
		||||
 | 
			
		||||
    def create_thumbnail(self, dir, file):
 | 
			
		||||
    def create_thumbnail(self, dir, file, scrub_percent = "65%"):
 | 
			
		||||
        full_path = f"{dir}/{file}"
 | 
			
		||||
        try:
 | 
			
		||||
            file_hash    = hashlib.sha256(str.encode(full_path)).hexdigest()
 | 
			
		||||
            hash_img_pth = f"{self.ABS_THUMBS_PTH}/{file_hash}.jpg"
 | 
			
		||||
            if isfile(hash_img_pth) == False:
 | 
			
		||||
                self.generate_video_thumbnail(full_path, hash_img_pth)
 | 
			
		||||
                self.generate_video_thumbnail(full_path, hash_img_pth, scrub_percent)
 | 
			
		||||
 | 
			
		||||
            thumbnl = self.create_scaled_image(hash_img_pth, self.video_icon_wh)
 | 
			
		||||
            if thumbnl == None: # If no icon whatsoever, return internal default
 | 
			
		||||
@@ -57,7 +57,10 @@ class Icon(DesktopIconMixin, VideoIconMixin):
 | 
			
		||||
            return GdkPixbuf.Pixbuf.new_from_file(f"{self.DEFAULT_ICONS}/video.png")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def create_scaled_image(self, path, wxh):
 | 
			
		||||
    def create_scaled_image(self, path, wxh = None):
 | 
			
		||||
        if not wxh:
 | 
			
		||||
            wxh = self.video_icon_wh
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            if path.lower().endswith(".gif"):
 | 
			
		||||
                return  GdkPixbuf.PixbufAnimation.new_from_file(path) \
 | 
			
		||||
 
 | 
			
		||||
@@ -7,9 +7,9 @@ import subprocess
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VideoIconMixin:
 | 
			
		||||
    def generate_video_thumbnail(self, full_path, hash_img_pth):
 | 
			
		||||
    def generate_video_thumbnail(self, full_path, hash_img_pth, scrub_percent = "65%"):
 | 
			
		||||
        try:
 | 
			
		||||
            proc = subprocess.Popen([self.FFMPG_THUMBNLR, "-t", "65%", "-s", "300", "-c", "jpg", "-i", full_path, "-o", hash_img_pth])
 | 
			
		||||
            proc = subprocess.Popen([self.FFMPG_THUMBNLR, "-t", scrub_percent, "-s", "300", "-c", "jpg", "-i", full_path, "-o", hash_img_pth])
 | 
			
		||||
            proc.wait()
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            self.logger.debug(repr(e))
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user