moved thumbnail generation to plugin; extended plugin loading for pre and post window loading

This commit is contained in:
itdominator 2024-06-29 21:37:44 -05:00
parent 2f954f4c79
commit ce00970171
40 changed files with 359 additions and 125 deletions

View File

@ -14,6 +14,7 @@ class Manifest:
'ui_target': "plugin_control_list", 'ui_target': "plugin_control_list",
'pass_fm_events': "true" 'pass_fm_events': "true"
} }
pre_launch: bool = False
``` ```

View File

@ -8,6 +8,7 @@
"ui_target": "plugin_control_list", "ui_target": "plugin_control_list",
"pass_fm_events": "true", "pass_fm_events": "true",
"bind_keys": ["Example Plugin||send_message:<Control>f"] "bind_keys": ["Example Plugin||send_message:<Control>f"]
} },
"pre_launch": "false"
} }
} }

View File

@ -0,0 +1,3 @@
"""
Pligin Module
"""

View File

@ -0,0 +1,3 @@
"""
Pligin Package
"""

View File

@ -0,0 +1,73 @@
# Python imports
import json
import os
from os import path
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
# Application imports
from .icon import Icon
class IconController(Icon):
def __init__(self):
CURRENT_PATH = os.path.dirname(os.path.realpath(__file__))
# NOTE: app_name should be defined using python 'builtins' and so too must be logger used in the various classes
app_name_exists = False
try:
app_name
app_name_exists = True
except Exception as e:
...
APP_CONTEXT = f"{app_name.lower()}" if app_name_exists else "shellfm"
USR_APP_CONTEXT = f"/usr/share/{APP_CONTEXT}"
USER_HOME = path.expanduser('~')
CONFIG_PATH = f"{USER_HOME}/.config/{APP_CONTEXT}"
self.DEFAULT_ICONS = f"{CONFIG_PATH}/icons"
self.DEFAULT_ICON = f"{self.DEFAULT_ICONS}/text.png"
self.FFMPG_THUMBNLR = f"{CONFIG_PATH}/ffmpegthumbnailer" # Thumbnail generator binary
self.BLENDER_THUMBNLR = f"{CONFIG_PATH}/blender-thumbnailer" # Blender thumbnail generator binary
self.ICON_DIRS = ["/usr/share/icons", f"{USER_HOME}/.icons" "/usr/share/pixmaps"]
self.BASE_THUMBS_PTH = f"{USER_HOME}/.thumbnails"
self.ABS_THUMBS_PTH = f"{self.BASE_THUMBS_PTH}/normal"
self.STEAM_ICONS_PTH = f"{self.BASE_THUMBS_PTH}/steam_icons"
if not path.isdir(self.BASE_THUMBS_PTH):
os.mkdir(self.BASE_THUMBS_PTH)
if not path.isdir(self.ABS_THUMBS_PTH):
os.mkdir(self.ABS_THUMBS_PTH)
if not path.isdir(self.STEAM_ICONS_PTH):
os.mkdir(self.STEAM_ICONS_PTH)
if not os.path.exists(self.DEFAULT_ICONS):
self.DEFAULT_ICONS = f"{USR_APP_CONTEXT}/icons"
self.DEFAULT_ICON = f"{self.DEFAULT_ICONS}/text.png"
CONFIG_FILE = f"{CURRENT_PATH}/../settings.json"
with open(CONFIG_FILE) as f:
settings = json.load(f)
config = settings["config"]
self.container_icon_wh = config["container_icon_wh"]
self.video_icon_wh = config["video_icon_wh"]
self.sys_icon_wh = config["sys_icon_wh"]
# Filters
filters = settings["filters"]
self.fmeshs = tuple(filters["meshs"])
self.fcode = tuple(filters["code"])
self.fvideos = tuple(filters["videos"])
self.foffice = tuple(filters["office"])
self.fimages = tuple(filters["images"])
self.ftext = tuple(filters["text"])
self.fmusic = tuple(filters["music"])
self.fpdf = tuple(filters["pdf"])

View File

@ -14,4 +14,4 @@ class MeshsIconMixin:
proc = subprocess.Popen([self.BLENDER_THUMBNLR, full_path, hash_img_path]) proc = subprocess.Popen([self.BLENDER_THUMBNLR, full_path, hash_img_path])
proc.wait() proc.wait()
except Exception as e: except Exception as e:
self.logger.debug(repr(e)) logger.debug(repr(e))

View File

@ -14,7 +14,7 @@ class VideoIconMixin:
proc = subprocess.Popen([self.FFMPG_THUMBNLR, "-t", scrub_percent, "-s", "300", "-c", "jpg", "-i", full_path, "-o", hash_img_path]) proc = subprocess.Popen([self.FFMPG_THUMBNLR, "-t", scrub_percent, "-s", "300", "-c", "jpg", "-i", full_path, "-o", hash_img_path])
proc.wait() proc.wait()
except Exception as e: except Exception as e:
self.logger.debug(repr(e)) logger.info(repr(e))
self.ffprobe_generate_video_thumbnail(full_path, hash_img_path) self.ffprobe_generate_video_thumbnail(full_path, hash_img_path)
@ -51,5 +51,4 @@ class VideoIconMixin:
proc.wait() proc.wait()
except Exception as e: except Exception as e:
print("Video thumbnail generation issue in thread:") print("Video thumbnail generation issue in thread:")
print( repr(e) ) logger.info(repr(e))
self.logger.debug(repr(e))

View File

@ -0,0 +1,12 @@
{
"manifest": {
"name": "Thumbnailer",
"author": "ITDominator",
"version": "0.0.1",
"support": "",
"requests": {
"pass_fm_events": "true"
},
"pre_launch": "true"
}
}

View File

@ -0,0 +1,59 @@
# Python imports
import os
# Lib imports
# Application imports
from plugins.plugin_base import PluginBase
from .icons.controller import IconController
class Plugin(PluginBase):
def __init__(self):
super().__init__()
self.name = "Thumbnailer" # NOTE: Need to remove after establishing private bidirectional 1-1 message bus
# where self.name should not be needed for message comms
# self.path = os.path.dirname(os.path.realpath(__file__))
def run(self):
self.icon_controller = IconController()
self._event_system.subscribe("create-thumbnail", self.create_thumbnail)
def generate_reference_ui_element(self):
...
def create_thumbnail(self, dir, file) -> str:
return self.icon_controller.create_icon(dir, file)
def get_video_icons(self, dir) -> list:
data = []
def get_video_icons(self) -> list:
data = []
fvideos = self.icon_controller.fvideos
vids = [ file for file in os.path.list_dir(dir) if file.lower().endswith(fvideos) ]
for file in vids:
img_hash, hash_img_path = self.create_video_thumbnail(full_path = f"{dir}/{file}", returnHashInstead = True)
data.append([img_hash, hash_img_path])
return data
def get_pixbuf_icon_str_combo(self, dir) -> list:
data = []
for file in os.path.list_dir(dir):
icon = self.icon_controller.create_icon(dir, file).get_pixbuf()
data.append([icon, file])
return data
def get_gtk_icon_str_combo(self, dir) -> list:
data = []
for file in os.path.list_dir(dir):
icon = self.icon_controller.create_icon(dir, file)
data.append([icon, file[0]])
return data

View File

@ -0,0 +1,101 @@
{
"config":{
"thumbnailer_path":"ffmpegthumbnailer",
"blender_thumbnailer_path":"",
"container_icon_wh":[
128,
128
],
"video_icon_wh":[
128,
64
],
"sys_icon_wh":[
56,
56
],
"steam_cdn_url":"https://steamcdn-a.akamaihd.net/steam/apps/",
"remux_folder_max_disk_usage":"8589934592"
},
"filters":{
"meshs":[
".dae",
".fbx",
".gltf",
".obj",
".stl"
],
"code":[
".cpp",
".css",
".c",
".go",
".html",
".htm",
".java",
".js",
".json",
".lua",
".md",
".py",
".rs",
".toml",
".xml",
".pom"
],
"videos":[
".mkv",
".mp4",
".webm",
".avi",
".mov",
".m4v",
".mpg",
".mpeg",
".wmv",
".flv"
],
"office":[
".doc",
".docx",
".xls",
".xlsx",
".xlt",
".xltx",
".xlm",
".ppt",
".pptx",
".pps",
".ppsx",
".odt",
".rtf"
],
"images":[
".png",
".jpg",
".jpeg",
".gif",
".ico",
".tga",
".webp"
],
"text":[
".txt",
".text",
".sh",
".cfg",
".conf",
".log"
],
"music":[
".psf",
".mp3",
".ogg",
".flac",
".m4a"
],
"pdf":[
".pdf"
]
}
}

View File

@ -111,6 +111,8 @@ class Plugin(PluginBase):
for uri in state.uris: for uri in state.uris:
self.trashman.trash(uri, verbocity) self.trashman.trash(uri, verbocity)
self.trashman.regenerate()
def restore_trash_files(self, widget = None, eve = None, verbocity = False): def restore_trash_files(self, widget = None, eve = None, verbocity = False):
self._event_system.emit("get_current_state") self._event_system.emit("get_current_state")
state = self._fm_state state = self._fm_state

View File

@ -43,4 +43,4 @@ class Trash(object):
def restore(self, filename, verbose): def restore(self, filename, verbose):
"""Restore a file from trash.""" """Restore a file from trash."""
raise NotImplementedError(_('Backend didnt \ implement this functionality')) raise NotImplementedError(_('Backend didnt implement this functionality'))

View File

@ -127,7 +127,7 @@ DeletionDate={}
f.write(infofile) f.write(infofile)
f.close() f.close()
self.regenerate() # self.regenerate()
if verbose: if verbose:
sys.stderr.write(_('trashed \'{}\'\n').format(filename)) sys.stderr.write(_('trashed \'{}\'\n').format(filename))

View File

@ -44,10 +44,13 @@ class Controller(UIMixin, SignalsMixins, Controller_Data):
self._subscribe_to_events() self._subscribe_to_events()
self._load_widgets() self._load_widgets()
if args.no_plugins == "false":
self.plugins_controller.pre_launch_plugins()
self._generate_file_views(self.fm_controller_data) self._generate_file_views(self.fm_controller_data)
if args.no_plugins == "false": if args.no_plugins == "false":
self.plugins.launch_plugins() self.plugins_controller.post_launch_plugins()
for arg in unknownargs + [args.new_tab,]: for arg in unknownargs + [args.new_tab,]:
if os.path.isdir(arg): if os.path.isdir(arg):
@ -116,7 +119,7 @@ class Controller(UIMixin, SignalsMixins, Controller_Data):
def reload_plugins(self, widget=None, eve=None): def reload_plugins(self, widget=None, eve=None):
self.plugins.reload_plugins() self.plugins_controller.reload_plugins()
def do_action_from_menu_controls(self, _action=None, eve=None): def do_action_from_menu_controls(self, _action=None, eve=None):
@ -196,4 +199,4 @@ class Controller(UIMixin, SignalsMixins, Controller_Data):
tab.execute([f"{tab.terminal_app}"], start_dir=tab.get_current_directory()) tab.execute([f"{tab.terminal_app}"], start_dir=tab.get_current_directory())
def go_to_path(self, path: str): def go_to_path(self, path: str):
self.builder.get_object("path_entry").set_text(path) self.builder.get_object("path_entry").set_text(path)

View File

@ -29,7 +29,7 @@ class Controller_Data:
self._load_glade_file() self._load_glade_file()
self.fm_controller = WindowController() self.fm_controller = WindowController()
self.plugins = PluginsController() self.plugins_controller = PluginsController()
self.fm_controller_data = self.fm_controller.get_state_from_file() self.fm_controller_data = self.fm_controller.get_state_from_file()
self.window1 = self.builder.get_object("window_1") self.window1 = self.builder.get_object("window_1")
@ -179,4 +179,4 @@ class Controller_Data:
proc = subprocess.Popen(['xclip','-selection','clipboard'], stdin=subprocess.PIPE) proc = subprocess.Popen(['xclip','-selection','clipboard'], stdin=subprocess.PIPE)
proc.stdin.write(data.encode("utf-8")) proc.stdin.write(data.encode("utf-8"))
proc.stdin.close() proc.stdin.close()
retcode = proc.wait() retcode = proc.wait()

View File

@ -31,7 +31,6 @@ class GridMixin:
# return # return
dir = tab.get_current_directory() dir = tab.get_current_directory()
files = tab.get_files() files = tab.get_files()
@ -167,4 +166,4 @@ class GridMixin:
icon_grid = obj.get_children()[0] icon_grid = obj.get_children()[0]
name = icon_grid.get_name() name = icon_grid.get_name()
if name == _name: if name == _name:
return icon_grid return icon_grid

View File

@ -86,4 +86,4 @@ class UIMixin(PaneMixin, WindowMixin):
for j in range(0, 4): for j in range(0, 4):
i = j + 1 i = j + 1
self.fm_controller.create_window() self.fm_controller.create_window()
self.create_new_tab_notebook(None, i, None) self.create_new_tab_notebook(None, i, None)

View File

@ -15,32 +15,37 @@ class ManifestProcessorException(Exception):
... ...
@dataclass(slots=True) @dataclass(slots = True)
class PluginInfo: class PluginInfo:
path: str = None path: str = None
name: str = None name: str = None
author: str = None author: str = None
version: str = None version: str = None
support: str = None support: str = None
requests:{} = None requests:{} = None
reference: type = None reference: type = None
pre_launch: bool = False
class ManifestProcessor: class ManifestProcessor:
def __init__(self, path, builder): def __init__(self, path, builder):
manifest = join(path, "manifest.json") manifest_pth = join(path, "manifest.json")
if not os.path.exists(manifest): if not os.path.exists(manifest_pth):
raise ManifestProcessorException("Invalid Plugin Structure: Plugin doesn't have 'manifest.json'. Aboarting load...") raise ManifestProcessorException("Invalid Plugin Structure: Plugin doesn't have 'manifest.json'. Aboarting load...")
self._path = path self._path = path
self._builder = builder self._builder = builder
with open(manifest) as f: with open(manifest_pth) as f:
data = json.load(f) data = json.load(f)
self._manifest = data["manifest"] self._manifest = data["manifest"]
self._plugin = self.collect_info() self._plugin = self.collect_info()
def is_pre_launch(self) -> bool:
return self._plugin.pre_launch
def collect_info(self) -> PluginInfo: def collect_info(self) -> PluginInfo:
plugin = PluginInfo() plugin = PluginInfo()
plugin.path = self._path plugin.path = self._path
plugin.name = self._manifest["name"] plugin.name = self._manifest["name"]
plugin.author = self._manifest["author"] plugin.author = self._manifest["author"]
@ -48,6 +53,9 @@ class ManifestProcessor:
plugin.support = self._manifest["support"] plugin.support = self._manifest["support"]
plugin.requests = self._manifest["requests"] plugin.requests = self._manifest["requests"]
if "pre_launch" in self._manifest.keys():
plugin.pre_launch = True if self._manifest["pre_launch"] == "true" else False
return plugin return plugin
def get_loading_data(self): def get_loading_data(self):
@ -90,4 +98,4 @@ class ManifestProcessor:
if isinstance(requests["bind_keys"], list): if isinstance(requests["bind_keys"], list):
loading_data["bind_keys"] = requests["bind_keys"] loading_data["bind_keys"] = requests["bind_keys"]
return self._plugin, loading_data return self._plugin, loading_data

View File

@ -36,41 +36,76 @@ class PluginsController:
self._plugins_dir_watcher = None self._plugins_dir_watcher = None
self._plugin_collection = [] self._plugin_collection = []
self._plugin_manifests = {}
self._load_manifests()
def launch_plugins(self) -> None: def _load_manifests(self):
logger.info(f"Loading manifests...")
for path, folder in [[join(self._plugins_path, item), item] if os.path.isdir(join(self._plugins_path, item)) else None for item in os.listdir(self._plugins_path)]:
manifest = ManifestProcessor(path, self._builder)
self._plugin_manifests[path] = {
"path": path,
"folder": folder,
"manifest": manifest
}
self._set_plugins_watcher() self._set_plugins_watcher()
self.load_plugins()
def _set_plugins_watcher(self) -> None: def _set_plugins_watcher(self) -> None:
self._plugins_dir_watcher = Gio.File.new_for_path(self._plugins_path) \ self._plugins_dir_watcher = Gio.File.new_for_path(self._plugins_path) \
.monitor_directory(Gio.FileMonitorFlags.WATCH_MOVES, Gio.Cancellable()) .monitor_directory(Gio.FileMonitorFlags.WATCH_MOVES, Gio.Cancellable())
self._plugins_dir_watcher.connect("changed", self._on_plugins_changed, ()) self._plugins_dir_watcher.connect("changed", self._on_plugins_changed, ())
def _on_plugins_changed(self, file_monitor, file, other_file=None, eve_type=None, data=None): def _on_plugins_changed(self, file_monitor, file, other_file = None, eve_type = None, data = None):
if eve_type in [Gio.FileMonitorEvent.CREATED, Gio.FileMonitorEvent.DELETED, if eve_type in [Gio.FileMonitorEvent.CREATED, Gio.FileMonitorEvent.DELETED,
Gio.FileMonitorEvent.RENAMED, Gio.FileMonitorEvent.MOVED_IN, Gio.FileMonitorEvent.RENAMED, Gio.FileMonitorEvent.MOVED_IN,
Gio.FileMonitorEvent.MOVED_OUT]: Gio.FileMonitorEvent.MOVED_OUT]:
self.reload_plugins(file) self.reload_plugins(file)
@daemon_threaded def pre_launch_plugins(self) -> None:
def load_plugins(self, file: str = None) -> None: logger.info(f"Loading pre-launch plugins...")
logger.info(f"Loading plugins...") plugin_manifests: {} = {}
for key in self._plugin_manifests:
target_manifest = self._plugin_manifests[key]["manifest"]
if target_manifest.is_pre_launch():
plugin_manifests[key] = self._plugin_manifests[key]
self._load_plugins(plugin_manifests, is_pre_launch = True)
def post_launch_plugins(self) -> None:
logger.info(f"Loading post-launch plugins...")
plugin_manifests: {} = {}
for key in self._plugin_manifests:
target_manifest = self._plugin_manifests[key]["manifest"]
if not target_manifest.is_pre_launch():
plugin_manifests[key] = self._plugin_manifests[key]
self._load_plugins(plugin_manifests)
def _load_plugins(self, plugin_manifests: {} = {}, is_pre_launch: bool = False) -> None:
parent_path = os.getcwd() parent_path = os.getcwd()
for path, folder in [[join(self._plugins_path, item), item] if os.path.isdir(join(self._plugins_path, item)) else None for item in os.listdir(self._plugins_path)]: for key in plugin_manifests:
try: target_manifest = plugin_manifests[key]
target = join(path, "plugin.py") path, folder, manifest = target_manifest["path"], target_manifest["folder"], target_manifest["manifest"]
manifest = ManifestProcessor(path, self._builder)
try:
target = join(path, "plugin.py")
if not os.path.exists(target): if not os.path.exists(target):
raise FileNotFoundError("Invalid Plugin Structure: Plugin doesn't have 'plugin.py'. Aboarting load...") raise FileNotFoundError("Invalid Plugin Structure: Plugin doesn't have 'plugin.py'. Aboarting load...")
plugin, loading_data = manifest.get_loading_data() plugin, loading_data = manifest.get_loading_data()
module = self.load_plugin_module(path, folder, target) module = self.load_plugin_module(path, folder, target)
GLib.idle_add(self.execute_plugin, *(module, plugin, loading_data)) if is_pre_launch:
# self.execute_plugin(module, plugin, loading_data) self.execute_plugin(module, plugin, loading_data)
else:
GLib.idle_add(self.execute_plugin, *(module, plugin, loading_data))
except InvalidPluginException as e: except InvalidPluginException as e:
logger.info(f"Malformed Plugin: Not loading -->: '{folder}' !") logger.info(f"Malformed Plugin: Not loading -->: '{folder}' !")
logger.debug("Trace: ", traceback.print_exc()) logger.debug("Trace: ", traceback.print_exc())
@ -128,4 +163,4 @@ class PluginsController:
os.chdir(plugin.path) os.chdir(plugin.path)
plugin.reference.reload_package(f"{plugin.path}/plugin.py") plugin.reference.reload_package(f"{plugin.path}/plugin.py")
os.chdir(parent_path) os.chdir(parent_path)

View File

@ -14,7 +14,6 @@ from random import randint
from .utils.settings import Settings from .utils.settings import Settings
from .utils.launcher import Launcher from .utils.launcher import Launcher
from .utils.filehandler import FileHandler from .utils.filehandler import FileHandler
from .icons.icon import Icon
from .path import Path from .path import Path
@ -40,9 +39,8 @@ except Exception as e:
class Tab(Settings, FileHandler, Launcher, Icon, Path): class Tab(Settings, FileHandler, Launcher, Path):
def __init__(self): def __init__(self):
self.logger = None
self._id_length: int = 10 self._id_length: int = 10
self._id: str = "" self._id: str = ""
@ -168,33 +166,6 @@ class Tab(Settings, FileHandler, Launcher, Icon, Path):
} }
} }
def get_video_icons(self) -> list:
data = []
dir = self.get_current_directory()
for file in self._vids:
img_hash, hash_img_path = self.create_video_thumbnail(full_path=f"{dir}/{file}", returnHashInstead=True)
data.append([img_hash, hash_img_path])
return data
def get_pixbuf_icon_str_combo(self):
data = []
dir = self.get_current_directory()
for file in self._files:
icon = self.create_icon(dir, file).get_pixbuf()
data.append([icon, file])
return data
def get_gtk_icon_str_combo(self) -> list:
data = []
dir = self.get_current_directory()
for file in self._files:
icon = self.create_icon(dir, file)
data.append([icon, file[0]])
return data
def get_current_directory(self) -> str: def get_current_directory(self) -> str:
return self.get_path() return self.get_path()
@ -264,7 +235,7 @@ class Tab(Settings, FileHandler, Launcher, Icon, Path):
return int(text) if text.isdigit() else text return int(text) if text.isdigit() else text
def _natural_keys(self, text): def _natural_keys(self, text):
return [ self._atoi(c) for c in re.split('(\d+)',text) ] return [ self._atoi(c) for c in re.split(r'(\d+)', text) ]
def _hash_text(self, text) -> str: def _hash_text(self, text) -> str:
return hashlib.sha256(str.encode(text)).hexdigest()[:18] return hashlib.sha256(str.encode(text)).hexdigest()[:18]
@ -289,3 +260,7 @@ class Tab(Settings, FileHandler, Launcher, Icon, Path):
def _set_error_message(self, text: str): def _set_error_message(self, text: str):
self.error_message = text self.error_message = text
def create_icon(self, dir, file):
return event_system.emit_and_await("create-thumbnail", (dir, file,))

View File

@ -41,11 +41,11 @@ class Launcher:
def execute(self, command, start_dir=os.getenv("HOME"), use_shell=False): def execute(self, command, start_dir=os.getenv("HOME"), use_shell=False):
try: try:
self.logger.debug(command) logger.debug(command)
subprocess.Popen(command, cwd=start_dir, shell=use_shell, start_new_session=True, stdout=None, stderr=None, close_fds=True) subprocess.Popen(command, cwd=start_dir, shell=use_shell, start_new_session=True, stdout=None, stderr=None, close_fds=True)
except ShellFMLauncherException as e: except ShellFMLauncherException as e:
self.logger.error(f"Couldn't execute: {command}") logger.error(f"Couldn't execute: {command}")
self.logger.error(e) logger.error(e)
# TODO: Return std(out/in/err) handlers along with subprocess instead of sinking to null # TODO: Return std(out/in/err) handlers along with subprocess instead of sinking to null
def execute_and_return_thread_handler(self, command, start_dir=os.getenv("HOME"), use_shell=False): def execute_and_return_thread_handler(self, command, start_dir=os.getenv("HOME"), use_shell=False):
@ -53,8 +53,8 @@ class Launcher:
DEVNULL = open(os.devnull, 'w') DEVNULL = open(os.devnull, 'w')
return subprocess.Popen(command, cwd=start_dir, shell=use_shell, start_new_session=False, stdout=DEVNULL, stderr=DEVNULL, close_fds=False) return subprocess.Popen(command, cwd=start_dir, shell=use_shell, start_new_session=False, stdout=DEVNULL, stderr=DEVNULL, close_fds=False)
except ShellFMLauncherException as e: except ShellFMLauncherException as e:
self.logger.error(f"Couldn't execute and return thread: {command}") logger.error(f"Couldn't execute and return thread: {command}")
self.logger.error(e) logger.error(e)
return None return None
@threaded @threaded
@ -63,7 +63,7 @@ class Launcher:
def remux_video(self, hash, file): def remux_video(self, hash, file):
remux_vid_pth = "{self.REMUX_FOLDER}/{hash}.mp4" remux_vid_pth = "{self.REMUX_FOLDER}/{hash}.mp4"
self.logger.debug(remux_vid_pth) logger.debug(remux_vid_pth)
if not os.path.isfile(remux_vid_pth): if not os.path.isfile(remux_vid_pth):
self.check_remux_space() self.check_remux_space()
@ -83,8 +83,8 @@ class Launcher:
proc = subprocess.Popen(command) proc = subprocess.Popen(command)
proc.wait() proc.wait()
except ShellFMLauncherException as e: except ShellFMLauncherException as e:
self.logger.error(message) logger.error(message)
self.logger.error(e) logger.error(e)
return False return False
return True return True
@ -94,7 +94,7 @@ class Launcher:
try: try:
limit = int(limit) limit = int(limit)
except ShellFMLauncherException as e: except ShellFMLauncherException as e:
self.logger.debug(e) logger.debug(e)
return return
usage = self.get_remux_folder_usage(self.REMUX_FOLDER) usage = self.get_remux_folder_usage(self.REMUX_FOLDER)
@ -113,4 +113,4 @@ class Launcher:
if not os.path.islink(fp): # Skip if it is symbolic link if not os.path.islink(fp): # Skip if it is symbolic link
total_size += os.path.getsize(fp) total_size += os.path.getsize(fp)
return total_size return total_size

View File

@ -14,8 +14,6 @@ class ShellFMSettingsException(Exception):
class Settings: class Settings:
logger = None
# NOTE: app_name should be defined using python 'builtins' # NOTE: app_name should be defined using python 'builtins'
app_name_exists = False app_name_exists = False
try: try:
@ -31,45 +29,13 @@ class Settings:
CONFIG_FILE = f"{CONFIG_PATH}/settings.json" CONFIG_FILE = f"{CONFIG_PATH}/settings.json"
HIDE_HIDDEN_FILES = True HIDE_HIDDEN_FILES = True
DEFAULT_ICONS = f"{CONFIG_PATH}/icons"
DEFAULT_ICON = f"{DEFAULT_ICONS}/text.png"
FFMPG_THUMBNLR = f"{CONFIG_PATH}/ffmpegthumbnailer" # Thumbnail generator binary
BLENDER_THUMBNLR = f"{CONFIG_PATH}/blender-thumbnailer" # Blender thumbnail generator binary
REMUX_FOLDER = f"{USER_HOME}/.remuxs" # Remuxed files folder REMUX_FOLDER = f"{USER_HOME}/.remuxs" # Remuxed files folder
ICON_DIRS = ["/usr/share/icons", f"{USER_HOME}/.icons" "/usr/share/pixmaps"]
BASE_THUMBS_PTH = f"{USER_HOME}/.thumbnails"
ABS_THUMBS_PTH = f"{BASE_THUMBS_PTH}/normal"
STEAM_ICONS_PTH = f"{BASE_THUMBS_PTH}/steam_icons"
if not os.path.exists(CONFIG_PATH) or not os.path.exists(CONFIG_FILE):
msg = f"No config file located! Aborting loading ShellFM library...\nExpected: {CONFIG_FILE}"
raise ShellFMSettingsException(msg)
if not path.isdir(REMUX_FOLDER):
os.mkdir(REMUX_FOLDER)
if not path.isdir(BASE_THUMBS_PTH):
os.mkdir(BASE_THUMBS_PTH)
if not path.isdir(ABS_THUMBS_PTH):
os.mkdir(ABS_THUMBS_PTH)
if not path.isdir(STEAM_ICONS_PTH):
os.mkdir(STEAM_ICONS_PTH)
if not os.path.exists(DEFAULT_ICONS):
DEFAULT_ICONS = f"{USR_APP_CONTEXT}/icons"
DEFAULT_ICON = f"{DEFAULT_ICONS}/text.png"
with open(CONFIG_FILE) as f: with open(CONFIG_FILE) as f:
settings = json.load(f) settings = json.load(f)
config = settings["config"] config = settings["config"]
subpath = config["base_of_home"] subpath = config["base_of_home"]
STEAM_CDN_URL = config["steam_cdn_url"]
FFMPG_THUMBNLR = FFMPG_THUMBNLR if config["thumbnailer_path"] == "" else config["thumbnailer_path"]
BLENDER_THUMBNLR = BLENDER_THUMBNLR if config["blender_thumbnailer_path"] == "" else config["blender_thumbnailer_path"]
HIDE_HIDDEN_FILES = True if config["hide_hidden_files"] in ["true", ""] else False HIDE_HIDDEN_FILES = True if config["hide_hidden_files"] in ["true", ""] else False
go_past_home = True if config["go_past_home"] in ["true", ""] else False go_past_home = True if config["go_past_home"] in ["true", ""] else False
lock_folder = False if config["lock_folder"] in ["false", ""] else True lock_folder = False if config["lock_folder"] in ["false", ""] else True
@ -83,9 +49,6 @@ class Settings:
code_app = config["code_app"] code_app = config["code_app"]
text_app = config["text_app"] text_app = config["text_app"]
terminal_app = config["terminal_app"] terminal_app = config["terminal_app"]
container_icon_wh = config["container_icon_wh"]
video_icon_wh = config["video_icon_wh"]
sys_icon_wh = config["sys_icon_wh"]
file_manager_app = config["file_manager_app"] file_manager_app = config["file_manager_app"]
remux_folder_max_disk_usage = config["remux_folder_max_disk_usage"] remux_folder_max_disk_usage = config["remux_folder_max_disk_usage"]

View File

@ -2,8 +2,6 @@
"config": { "config": {
"base_of_home": "", "base_of_home": "",
"hide_hidden_files": "true", "hide_hidden_files": "true",
"thumbnailer_path": "ffmpegthumbnailer",
"blender_thumbnailer_path": "",
"go_past_home": "true", "go_past_home": "true",
"lock_folder": "false", "lock_folder": "false",
"locked_folders": "venv::::flasks", "locked_folders": "venv::::flasks",
@ -16,11 +14,7 @@
"code_app": "newton", "code_app": "newton",
"text_app": "mousepad", "text_app": "mousepad",
"terminal_app": "terminator", "terminal_app": "terminator",
"container_icon_wh": [128, 128],
"video_icon_wh": [128, 64],
"sys_icon_wh": [56, 56],
"file_manager_app": "solarfm", "file_manager_app": "solarfm",
"steam_cdn_url": "https://steamcdn-a.akamaihd.net/steam/apps/",
"remux_folder_max_disk_usage": "8589934592", "remux_folder_max_disk_usage": "8589934592",
"make_transparent":0, "make_transparent":0,
"main_window_x":721, "main_window_x":721,
@ -29,6 +23,9 @@
"main_window_min_height":480, "main_window_min_height":480,
"main_window_width":800, "main_window_width":800,
"main_window_height":600, "main_window_height":600,
"application_dirs":[
"/usr/share/applications"
]
}, },
"filters": { "filters": {
"meshs": [".dae", ".fbx", ".gltf", ".obj", ".stl"], "meshs": [".dae", ".fbx", ".gltf", ".obj", ".stl"],
@ -49,4 +46,4 @@
"ch_log_lvl": 20, "ch_log_lvl": 20,
"fh_log_lvl": 10 "fh_log_lvl": 10
} }
} }