diff --git a/lazy_player/__init__.py b/lazy_player/__init__.py index 8fa0d07..a9e6ba9 100644 --- a/lazy_player/__init__.py +++ b/lazy_player/__init__.py @@ -3,7 +3,7 @@ from __future__ import annotations import os import sys from pathlib import Path -from typing import Any, cast, overload +from typing import Any, cast import gi @@ -152,13 +152,13 @@ class MainWindow(Gtk.ApplicationWindow): self._populate_file_list() return - position = self._load_attribute("position", 0) + position = file_item.load_attribute("position", 0) # Start playing the video full_path = os.path.abspath(file_item.full_path) self.playbin.set_property("uri", f"file://{full_path}") - track = self._load_attribute("subtitle_track", -2) + track = file_item.load_attribute("subtitle_track", -2) if track >= 0: flags = self.playbin.get_property("flags") @@ -207,18 +207,10 @@ class MainWindow(Gtk.ApplicationWindow): self.set_child(self.stack) @property - def currently_playing(self): + def selection(self) -> FileItem: selected_item = self.selection_model.get_selected_item() - - if not selected_item: - return None - - file_item = cast(FileItem, selected_item) - - if file_item.file_type == FileType.DIRECTORY: - return None - - return file_item.full_path + assert selected_item + return cast(FileItem, selected_item) def _setup_list_item(self, factory: Gtk.SignalListItemFactory, list_item: Gtk.ListItem): # Create horizontal box to hold icon and label @@ -367,46 +359,15 @@ class MainWindow(Gtk.ApplicationWindow): def _save_position(self) -> None: """Save current playback position as xattr""" + file_item = self.selection + assert file_item.file_type != FileType.DIRECTORY success, position = self.pipeline.query_position(Gst.Format.TIME) success2, duration = self.pipeline.query_duration(Gst.Format.TIME) if success and success2: - self._save_attribute("position", position) - self._save_attribute("duration", duration) - - def _save_attribute(self, name: str, value: str | float | int | None): - path = self.currently_playing - - if path is None: - return - - try: - if value is None: - os.removexattr(path, f"user.lazy_player.{name}") - else: - os.setxattr(path, f"user.lazy_player.{name}", str(value).encode("utf8")) - except OSError as err: - print(err, file=sys.stderr) - - @overload - def _load_attribute(self, name: str, dfl: str) -> str: ... - - @overload - def _load_attribute(self, name: str, dfl: int) -> int: ... - - def _load_attribute(self, name: str, dfl: str | int) -> str | int: - path = self.currently_playing - - if path is None: - return dfl - - try: - strval = os.getxattr(path, f"user.lazy_player.{name}") - return type(dfl)(strval) - except OSError as err: - print(err, file=sys.stderr) - return dfl + file_item.save_attribute("position", position) + file_item.save_attribute("duration", duration) def _cycle_subtitles(self) -> None: """Cycle through available subtitle tracks, including off state""" @@ -427,7 +388,9 @@ class MainWindow(Gtk.ApplicationWindow): self.playbin.set_property("current-text", 0) track_info = self._get_subtitle_info(0) self.show_overlay_text(f"Subtitle track: {track_info}") - self._save_attribute("subtitle_track", 0) + file_item = self.selection + assert file_item.file_type != FileType.DIRECTORY + file_item.save_attribute("subtitle_track", 0) return # If we're on the last track, disable subtitles @@ -435,7 +398,9 @@ class MainWindow(Gtk.ApplicationWindow): flags &= ~0x00000004 # TEXT flag self.playbin.set_property("flags", flags) self.show_overlay_text("Subtitles: Off") - self._save_attribute("subtitle_track", -1) + file_item = self.selection + assert file_item.file_type != FileType.DIRECTORY + file_item.save_attribute("subtitle_track", -1) return # Otherwise cycle to next track @@ -443,7 +408,9 @@ class MainWindow(Gtk.ApplicationWindow): self.playbin.set_property("current-text", next_track) track_info = self._get_subtitle_info(next_track) self.show_overlay_text(f"Subtitle track: {track_info}") - self._save_attribute("subtitle_track", next_track) + file_item = self.selection + assert file_item.file_type != FileType.DIRECTORY + file_item.save_attribute("subtitle_track", next_track) def show_overlay_text(self, text: str, timeout_seconds: float = 1.0) -> None: """Show text in a centered overlay that disappears after timeout""" diff --git a/lazy_player/file_model.py b/lazy_player/file_model.py index 25b617e..00b4bb1 100644 --- a/lazy_player/file_model.py +++ b/lazy_player/file_model.py @@ -1,7 +1,9 @@ from __future__ import annotations import os +import sys from enum import Enum, auto +from typing import overload import gi @@ -39,3 +41,26 @@ class FileItem(GObject.Object): return FileItem(name, FileType.VIDEO, path) raise ValueError(f"Unsupported file type: {path}") + + @overload + def load_attribute(self, name: str, dfl: str) -> str: ... + + @overload + def load_attribute(self, name: str, dfl: int) -> int: ... + + def load_attribute(self, name: str, dfl: str | int) -> str | int: + try: + strval = os.getxattr(self.full_path, f"user.lazy_player.{name}") + return type(dfl)(strval) + except OSError as err: + print(err, file=sys.stderr) + return dfl + + def save_attribute(self, name: str, value: str | float | int | None) -> None: + try: + if value is None: + os.removexattr(self.full_path, f"user.lazy_player.{name}") + else: + os.setxattr(self.full_path, f"user.lazy_player.{name}", str(value).encode("utf8")) + except OSError as err: + print(err, file=sys.stderr)