Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions gridplayer/dialogs/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,8 @@ def fill_repeatMode(self):
VideoRepeat.SINGLE_FILE: self.tr("Single File"),
VideoRepeat.DIR: self.tr("Directory"),
VideoRepeat.DIR_SHUFFLE: self.tr("Directory (Shuffle)"),
VideoRepeat.REC_DIR: self.tr("Recursive Directory"),
VideoRepeat.REC_DIR_SHUFFLE: self.tr("Recursive Directory (Shuffle)"),
}

_fill_combo_box(self.repeatMode, repeat_modes)
Expand Down
31 changes: 31 additions & 0 deletions gridplayer/params/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,13 @@
"check_if": ("is_active_param_set_to", "repeat_mode", VideoRepeat.DIR),
"show_if": "is_active_local_file",
},
"Repeat Directory Recursively": {
"title": translate("Actions", "Repeat Directory Recursively"),
"icon": "loop-dir",
"func": ("active", "set_repeat_mode", VideoRepeat.REC_DIR),
"check_if": ("is_active_param_set_to", "repeat_mode", VideoRepeat.REC_DIR),
"show_if": "is_active_local_file",
},
"Repeat Directory (Shuffle)": {
"title": translate("Actions", "Repeat Directory (Shuffle)"),
"icon": "loop-dir-shuffle",
Expand All @@ -299,6 +306,17 @@
),
"show_if": "is_active_local_file",
},
"Repeat Directory Recursively (Shuffle)": {
"title": translate("Actions", "Repeat Directory Recursively (Shuffle)"),
"icon": "loop-dir-shuffle",
"func": ("active", "set_repeat_mode", VideoRepeat.REC_DIR_SHUFFLE),
"check_if": (
"is_active_param_set_to",
"repeat_mode",
VideoRepeat.REC_DIR_SHUFFLE,
),
"show_if": "is_active_local_file",
},
"Faster": {
"title": translate("Actions", "Faster"),
"key": "C",
Expand Down Expand Up @@ -934,12 +952,25 @@
"func": ("all", "set_repeat_mode", VideoRepeat.DIR),
"show_if": "is_any_videos_local_file",
},
"Repeat Directory Recursively [ALL]": {
"title": translate("Actions", "Repeat Directory Recursively"),
"icon": "loop-dir",
"func": ("all", "set_repeat_mode", VideoRepeat.REC_DIR),
"show_if": "is_any_videos_local_file",
},

"Repeat Directory (Shuffle) [ALL]": {
"title": translate("Actions", "Repeat Directory (Shuffle)"),
"icon": "loop-dir-shuffle",
"func": ("all", "set_repeat_mode", VideoRepeat.DIR_SHUFFLE),
"show_if": "is_any_videos_local_file",
},
"Repeat Directory Recursively (Shuffle) [ALL]": {
"title": translate("Actions", "Repeat Directory Recursively (Shuffle)"),
"icon": "loop-dir-shuffle",
"func": ("all", "set_repeat_mode", VideoRepeat.REC_DIR_SHUFFLE),
"show_if": "is_any_videos_local_file",
},
"Faster [ALL]": {
"title": translate("Actions", "Faster"),
"key": "Shift+C",
Expand Down
4 changes: 4 additions & 0 deletions gridplayer/params/menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,9 @@
"---",
"Repeat Single File",
"Repeat Directory",
"Repeat Directory Recursively",
"Repeat Directory (Shuffle)",
"Repeat Directory Recursively (Shuffle)",
),
(
"Speed",
Expand Down Expand Up @@ -294,7 +296,9 @@
"---",
"Repeat Single File [ALL]",
"Repeat Directory [ALL]",
"Repeat Directory Recursively [ALL]",
"Repeat Directory (Shuffle) [ALL]",
"Repeat Directory Recursively (Shuffle) [ALL]",
),
(
"Speed",
Expand Down
2 changes: 2 additions & 0 deletions gridplayer/params/static.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ class VideoRepeat(AutoName):
SINGLE_FILE = auto()
DIR = auto()
DIR_SHUFFLE = auto()
REC_DIR = auto()
REC_DIR_SHUFFLE = auto()


class VideoDriver(AutoName):
Expand Down
75 changes: 37 additions & 38 deletions gridplayer/utils/next_file.py
Original file line number Diff line number Diff line change
@@ -1,44 +1,43 @@
import random
from pathlib import Path
from typing import Optional
from typing import Optional, List

from gridplayer.params.extensions import SUPPORTED_MEDIA_EXT


def next_video_file(file: Path, is_shuffle=False) -> Optional[Path]:
siblings = _file_siblings(file)

if is_shuffle:
random.shuffle(siblings)

try:
next_id = siblings.index(file) + 1
except ValueError:
return None

if next_id >= len(siblings):
next_id = 0

return siblings[next_id]


def previous_video_file(file: Path) -> Optional[Path]:
siblings = _file_siblings(file)

try:
next_id = siblings.index(file) - 1
except ValueError:
return None

if next_id >= len(siblings):
next_id = 0

return siblings[next_id]


def _file_siblings(file: Path):
return sorted(
f
for f in file.parent.iterdir()
if f.is_file() and f.suffix[1:].lower() in SUPPORTED_MEDIA_EXT
)
class VideoNavigator:
def __init__(self, start_file: Path, is_shuffle: bool, is_recursive: bool):
self.original_dir = start_file.parent
if is_recursive:
self.siblings = get_file_siblings(self.original_dir, is_recursive = True)
else:
self.siblings = get_file_siblings(self.original_dir, is_recursive = False)
if is_shuffle:
random.shuffle(self.siblings)
self.current_index = self.siblings.index(start_file) if start_file in self.siblings else -1

def next_video_file(self) -> Optional[Path]:
if not self.siblings or self.current_index == -1:
return None
self.current_index = (self.current_index + 1) % len(self.siblings)
return self.siblings[self.current_index]

def previous_video_file(self) -> Optional[Path]:
if not self.siblings or self.current_index == -1:
return None
self.current_index = (self.current_index - 1) % len(self.siblings)
return self.siblings[self.current_index]

def get_file_siblings(directory: Path, is_recursive: bool = False) -> List[Path]:
if is_recursive:
return sorted(
f
for f in directory.rglob("*") # Recursively includes subdirectories
if f.is_file() and f.suffix[1:].lower() in SUPPORTED_MEDIA_EXT
)
else:
return sorted(
f
for f in directory.iterdir() # Only includes top-level files
if f.is_file() and f.suffix[1:].lower() in SUPPORTED_MEDIA_EXT
)
42 changes: 26 additions & 16 deletions gridplayer/widgets/video_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
)
from gridplayer.settings import Settings
from gridplayer.utils.libvlc_options_parser import get_vlc_options
from gridplayer.utils.next_file import next_video_file, previous_video_file
from gridplayer.utils.next_file import VideoNavigator, get_file_siblings
from gridplayer.utils.qt import qt_connect, translate
from gridplayer.utils.url_resolve.static import ResolvedVideo
from gridplayer.utils.url_resolve.url_resolve import VideoURLResolver
Expand Down Expand Up @@ -677,10 +677,8 @@ def loop_end_action(self):
self.seek_random()
else:
self.seek(self.loop_start)
elif self.video_params.repeat_mode == VideoRepeat.DIR:
if not self.video_params.repeat_mode == VideoRepeat.SINGLE_FILE:
self.next_video()
elif self.video_params.repeat_mode == VideoRepeat.DIR_SHUFFLE:
self.shuffle_video()

def apply_snapshot(self, snapshot: Video):
if snapshot.uri != self.video_params.uri:
Expand Down Expand Up @@ -713,10 +711,25 @@ def apply_snapshot(self, snapshot: Video):

def set_video(self, video_params: Video):
is_first_video = self.video_params is None
is_options_changed = get_vlc_options(self.video_params) != get_vlc_options(
video_params
)

is_options_changed = get_vlc_options(self.video_params) != get_vlc_options(video_params)

last_repeat_mode = getattr(self, 'last_repeat_mode', None)
is_repeat_mode_changed = last_repeat_mode != video_params.repeat_mode


if is_first_video or is_repeat_mode_changed:
self.original_dir = video_params.uri.parent # Use the parent directory of the first video
self.siblings = get_file_siblings(self.original_dir) # Compute sibling list for navigation
if video_params.repeat_mode == VideoRepeat.DIR_SHUFFLE:
self.navigator = VideoNavigator(video_params.uri, is_shuffle = True, is_recursive = False)
elif video_params.repeat_mode == VideoRepeat.REC_DIR_SHUFFLE:
self.navigator = VideoNavigator(video_params.uri, is_shuffle = True, is_recursive = True)
elif video_params.repeat_mode == VideoRepeat.REC_DIR:
self.navigator = VideoNavigator(video_params.uri, is_shuffle = False, is_recursive = True)
elif video_params.repeat_mode == VideoRepeat.DIR:
self.navigator = VideoNavigator(video_params.uri, is_shuffle = False, is_recursive = False)

self.last_repeat_mode = video_params.repeat_mode
self.video_params = video_params

# Shut down current video
Expand Down Expand Up @@ -1109,17 +1122,14 @@ def play_pause(self):
@only_initialized
@only_local_file
def previous_video(self):
self.switch_video(previous_video_file(self.video_params.uri))

new_video = self.navigator.previous_video_file()
self.switch_video(new_video)

@only_initialized
@only_local_file
def next_video(self):
self.switch_video(next_video_file(self.video_params.uri))

@only_initialized
@only_local_file
def shuffle_video(self):
self.switch_video(next_video_file(self.video_params.uri, is_shuffle=True))
new_video = self.navigator.next_video_file()
self.switch_video(new_video)

@only_initialized
@only_local_file
Expand Down