Updated VOD Thumbnailer, added icon gen logic #6
|
@ -35,6 +35,7 @@ class Plugin:
|
||||||
self._builder = None
|
self._builder = None
|
||||||
self._thumbnailer_dialog = None
|
self._thumbnailer_dialog = None
|
||||||
self._thumbnail_preview_img = None
|
self._thumbnail_preview_img = None
|
||||||
|
self._scrub_step = None
|
||||||
self._file_name = None
|
self._file_name = None
|
||||||
self._file_location = None
|
self._file_location = None
|
||||||
self._file_hash = None
|
self._file_hash = None
|
||||||
|
@ -63,6 +64,7 @@ class Plugin:
|
||||||
self._builder.connect_signals(handlers)
|
self._builder.connect_signals(handlers)
|
||||||
|
|
||||||
self._thumbnailer_dialog = self._builder.get_object("thumbnailer_dialog")
|
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_name = self._builder.get_object("file_name")
|
||||||
self._file_location = self._builder.get_object("file_location")
|
self._file_location = self._builder.get_object("file_location")
|
||||||
self._thumbnail_preview_img = self._builder.get_object("thumbnail_preview_img")
|
self._thumbnail_preview_img = self._builder.get_object("thumbnail_preview_img")
|
||||||
|
@ -99,29 +101,33 @@ class Plugin:
|
||||||
self._state = state
|
self._state = state
|
||||||
self._set_ui_data()
|
self._set_ui_data()
|
||||||
response = self._thumbnailer_dialog.run()
|
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()
|
self._thumbnailer_dialog.hide()
|
||||||
|
|
||||||
|
|
||||||
def _regenerate_thumbnail(self, widget=None, eve=None):
|
def _regenerate_thumbnail(self, widget=None, eve=None):
|
||||||
print("Regenerating thumbnail...")
|
scrub_percent = int(self._scrub_step.get_value())
|
||||||
file = self._file_name.get_text()
|
file = self._file_name.get_text()
|
||||||
dir = self._file_location.get_text()
|
dir = self._file_location.get_text()
|
||||||
file_hash = self._file_hash.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:
|
try:
|
||||||
if os.path.isfile(hash_img_pth):
|
os.remove(hash_img_pth) if os.path.isfile(hash_img_pth) else ...
|
||||||
os.remove(hash_img_pth)
|
|
||||||
|
|
||||||
img_pixbuf = self._state.tab.create_icon(dir, file)
|
self._state.tab.create_thumbnail(dir, file, f"{scrub_percent}%")
|
||||||
self._thumbnail_preview_img.set_from_pixbuf(img_pixbuf)
|
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:
|
except Exception as e:
|
||||||
|
print(repr(e))
|
||||||
print("Couldn't regenerate thumbnail!")
|
print("Couldn't regenerate thumbnail!")
|
||||||
|
|
||||||
def _use_selected_thumbnail(self, widget=None, eve=None):
|
|
||||||
print("_use_selected_thumbnail stub...")
|
|
||||||
|
|
||||||
|
|
||||||
def _set_ui_data(self):
|
def _set_ui_data(self):
|
||||||
uri = self._state.selected_files[0]
|
uri = self._state.selected_files[0]
|
||||||
|
@ -130,9 +136,9 @@ class Plugin:
|
||||||
|
|
||||||
file_hash = hashlib.sha256(str.encode(uri)).hexdigest()
|
file_hash = hashlib.sha256(str.encode(uri)).hexdigest()
|
||||||
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"
|
||||||
img_pixbuf = GdkPixbuf.Pixbuf.new_from_file(hash_img_pth)
|
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_name.set_text(parts[ len(parts) - 1 ])
|
||||||
self._file_location.set_text(path)
|
self._file_location.set_text(path)
|
||||||
self._file_hash.set_text(file_hash)
|
self._file_hash.set_text(file_hash)
|
||||||
|
|
|
@ -2,6 +2,13 @@
|
||||||
<!-- Generated with glade 3.38.2 -->
|
<!-- Generated with glade 3.38.2 -->
|
||||||
<interface>
|
<interface>
|
||||||
<requires lib="gtk+" version="3.16"/>
|
<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">
|
<object class="GtkDialog" id="thumbnailer_dialog">
|
||||||
<property name="can-focus">False</property>
|
<property name="can-focus">False</property>
|
||||||
<property name="border-width">6</property>
|
<property name="border-width">6</property>
|
||||||
|
@ -26,7 +33,7 @@
|
||||||
<property name="layout-style">end</property>
|
<property name="layout-style">end</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkButton" id="cancel_button">
|
<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="visible">True</property>
|
||||||
<property name="can-focus">True</property>
|
<property name="can-focus">True</property>
|
||||||
<property name="can-default">True</property>
|
<property name="can-default">True</property>
|
||||||
|
@ -66,14 +73,55 @@
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<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>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkTable" id="general_table">
|
<object class="GtkTable" id="general_table">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can-focus">False</property>
|
<property name="can-focus">False</property>
|
||||||
<property name="border-width">4</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="n-columns">2</property>
|
||||||
<property name="column-spacing">12</property>
|
<property name="column-spacing">12</property>
|
||||||
<property name="row-spacing">6</property>
|
<property name="row-spacing">6</property>
|
||||||
|
@ -136,34 +184,6 @@
|
||||||
<property name="y-options"/>
|
<property name="y-options"/>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</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>
|
<child>
|
||||||
<object class="GtkLabel" id="hash">
|
<object class="GtkLabel" id="hash">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
@ -213,7 +233,7 @@
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<action-widgets>
|
<action-widgets>
|
||||||
<action-widget response="-6">cancel_button</action-widget>
|
<action-widget response="-7">cancel_button</action-widget>
|
||||||
</action-widgets>
|
</action-widgets>
|
||||||
</object>
|
</object>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
|
@ -145,7 +145,6 @@ class Controller_Data:
|
||||||
|
|
||||||
|
|
||||||
selected_files = state.icon_grid.get_selected_items()
|
selected_files = state.icon_grid.get_selected_items()
|
||||||
# if self.selected_files:
|
|
||||||
if selected_files:
|
if selected_files:
|
||||||
state.selected_files = self.format_to_uris(state.store, state.wid, state.tid, selected_files, True)
|
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.remove_class("notebook-unselected-focus")
|
||||||
ctx.add_class("notebook-selected-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)
|
self.set_bottom_labels(tab)
|
||||||
|
|
||||||
def set_path_text(self, wid, tid):
|
def set_path_text(self, wid, tid):
|
||||||
|
|
|
@ -30,7 +30,7 @@ class Icon(DesktopIconMixin, VideoIconMixin):
|
||||||
if file.lower().endswith(self.fvideos): # Video icon
|
if file.lower().endswith(self.fvideos): # Video icon
|
||||||
thumbnl = self.create_thumbnail(dir, file)
|
thumbnl = self.create_thumbnail(dir, file)
|
||||||
elif file.lower().endswith(self.fimages): # Image Icon
|
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
|
elif full_path.lower().endswith( ('.desktop',) ): # .desktop file parsing
|
||||||
thumbnl = self.parse_desktop_files(full_path)
|
thumbnl = self.parse_desktop_files(full_path)
|
||||||
|
|
||||||
|
@ -38,13 +38,13 @@ class Icon(DesktopIconMixin, VideoIconMixin):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def create_thumbnail(self, dir, file):
|
def create_thumbnail(self, dir, file, scrub_percent = "65%"):
|
||||||
full_path = f"{dir}/{file}"
|
full_path = f"{dir}/{file}"
|
||||||
try:
|
try:
|
||||||
file_hash = hashlib.sha256(str.encode(full_path)).hexdigest()
|
file_hash = hashlib.sha256(str.encode(full_path)).hexdigest()
|
||||||
hash_img_pth = f"{self.ABS_THUMBS_PTH}/{file_hash}.jpg"
|
hash_img_pth = f"{self.ABS_THUMBS_PTH}/{file_hash}.jpg"
|
||||||
if isfile(hash_img_pth) == False:
|
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)
|
thumbnl = self.create_scaled_image(hash_img_pth, self.video_icon_wh)
|
||||||
if thumbnl == None: # If no icon whatsoever, return internal default
|
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")
|
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:
|
try:
|
||||||
if path.lower().endswith(".gif"):
|
if path.lower().endswith(".gif"):
|
||||||
return GdkPixbuf.PixbufAnimation.new_from_file(path) \
|
return GdkPixbuf.PixbufAnimation.new_from_file(path) \
|
||||||
|
|
|
@ -7,9 +7,9 @@ import subprocess
|
||||||
|
|
||||||
|
|
||||||
class VideoIconMixin:
|
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:
|
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()
|
proc.wait()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.debug(repr(e))
|
self.logger.debug(repr(e))
|
||||||
|
|
Loading…
Reference in New Issue