diff --git a/gridplayer/params/actions.py b/gridplayer/params/actions.py index d589a1c..1a8982a 100644 --- a/gridplayer/params/actions.py +++ b/gridplayer/params/actions.py @@ -151,14 +151,14 @@ "key": "S", "icon": "next-frame", "func": ("active", "manual_seek", "next_frame"), - "show_if": "is_active_seekable", + "show_if": AND("is_active_has_video", "is_active_seekable"), }, "Previous frame": { "title": translate("Actions", "Previous frame"), "key": "D", "icon": "previous-frame", "func": ("active", "manual_seek", "previous_frame"), - "show_if": "is_active_seekable", + "show_if": AND("is_active_has_video", "is_active_seekable"), }, "+1%": { "title": "+1%", @@ -327,42 +327,42 @@ "key": "+", "icon": "zoom-in", "func": ("active", "scale_increase"), - "show_if": "is_active_initialized", + "show_if": "is_active_has_video", }, "Zoom Out": { "title": translate("Actions", "Zoom Out"), "key": "-", "icon": "zoom-out", "func": ("active", "scale_decrease"), - "show_if": "is_active_initialized", + "show_if": "is_active_has_video", }, "Zoom Reset": { "title": translate("Actions", "Zoom Reset"), "key": "*", "icon": "zoom-reset", "func": ("active", "scale_reset"), - "show_if": "is_active_initialized", + "show_if": "is_active_has_video", }, "Aspect Fit": { "title": translate("Actions", "Aspect Fit"), "icon": "aspect-fit", "func": ("active", "set_aspect", VideoAspect.FIT), "check_if": ("is_active_param_set_to", "aspect_mode", VideoAspect.FIT), - "show_if": "is_active_initialized", + "show_if": "is_active_has_video", }, "Aspect Stretch": { "title": translate("Actions", "Aspect Stretch"), "icon": "aspect-stretch", "func": ("active", "set_aspect", VideoAspect.STRETCH), "check_if": ("is_active_param_set_to", "aspect_mode", VideoAspect.STRETCH), - "show_if": "is_active_initialized", + "show_if": "is_active_has_video", }, "Aspect None": { "title": translate("Actions", "Aspect None"), "icon": "aspect-none", "func": ("active", "set_aspect", VideoAspect.NONE), "check_if": ("is_active_param_set_to", "aspect_mode", VideoAspect.NONE), - "show_if": "is_active_initialized", + "show_if": "is_active_has_video", }, "Seek Others (Percent)": { "title": translate("Actions", "Sync By Percent"), @@ -647,14 +647,14 @@ "key": "Shift+S", "icon": "next-frame", "func": ("all", "next_frame"), - "show_if": "is_any_videos_seekable", + "show_if": AND("is_any_videos_have_video", "is_any_videos_seekable"), }, "Previous frame [ALL]": { "title": translate("Actions", "Previous frame"), "key": "Shift+D", "icon": "previous-frame", "func": ("all", "previous_frame"), - "show_if": "is_any_videos_seekable", + "show_if": AND("is_any_videos_have_video", "is_any_videos_seekable"), }, "+1% [ALL]": { "title": "+1%", @@ -811,39 +811,39 @@ "key": "Shift++", "icon": "zoom-in", "func": ("all", "scale_increase"), - "show_if": "is_any_videos_initialized", + "show_if": "is_any_videos_have_video", }, "Zoom Out [ALL]": { "title": translate("Actions", "Zoom Out"), "key": "Shift+-", "icon": "zoom-out", "func": ("all", "scale_decrease"), - "show_if": "is_any_videos_initialized", + "show_if": "is_any_videos_have_video", }, "Zoom Reset [ALL]": { "title": translate("Actions", "Zoom Reset"), "key": "Shift+*", "icon": "zoom-reset", "func": ("all", "scale_reset"), - "show_if": "is_any_videos_initialized", + "show_if": "is_any_videos_have_video", }, "Aspect Fit [ALL]": { "title": translate("Actions", "Aspect Fit"), "icon": "aspect-fit", "func": ("all", "set_aspect", VideoAspect.FIT), - "show_if": "is_any_videos_initialized", + "show_if": "is_any_videos_have_video", }, "Aspect Stretch [ALL]": { "title": translate("Actions", "Aspect Stretch"), "icon": "aspect-stretch", "func": ("all", "set_aspect", VideoAspect.STRETCH), - "show_if": "is_any_videos_initialized", + "show_if": "is_any_videos_have_video", }, "Aspect None [ALL]": { "title": translate("Actions", "Aspect None"), "icon": "aspect-none", "func": ("all", "set_aspect", VideoAspect.NONE), - "show_if": "is_any_videos_initialized", + "show_if": "is_any_videos_have_video", }, "Audio Mode - Original [ALL]": { "title": translate("Audio Mode", "Original"), diff --git a/gridplayer/player/managers/active_block.py b/gridplayer/player/managers/active_block.py index 6f50cd9..77089c4 100644 --- a/gridplayer/player/managers/active_block.py +++ b/gridplayer/player/managers/active_block.py @@ -39,6 +39,7 @@ def commands(self): "is_active_multistream": self.is_active_multistream, "is_active_local_file": self.is_active_local_file, "is_active_has_audio": self.is_active_has_audio, + "is_active_has_video": self.is_active_has_video, "menu_generator_stream_quality": self.menu_generator_stream_quality, "menu_generator_video_track": self.menu_generator_video_track, "menu_generator_audio_track": self.menu_generator_audio_track, @@ -107,6 +108,12 @@ def is_active_has_audio(self): return bool(self._ctx.active_block.audio_tracks) + def is_active_has_video(self): + if not self.is_active_initialized(): + return False + + return bool(self._ctx.active_block.video_tracks) + def is_active_multistream(self): if self.is_no_active_block: return False diff --git a/gridplayer/player/managers/video_blocks.py b/gridplayer/player/managers/video_blocks.py index 5dcbc8b..abeb9f0 100644 --- a/gridplayer/player/managers/video_blocks.py +++ b/gridplayer/player/managers/video_blocks.py @@ -162,6 +162,7 @@ def commands(self): "is_any_videos_local_file": self.is_any_videos_local_file, "is_any_videos_live": self.is_any_videos_live, "is_any_videos_have_audio": self.is_any_videos_have_audio, + "is_any_videos_have_video": self.is_any_videos_have_video, "is_seek_sync_mode_set_to": self.is_seek_sync_mode_set_to, "set_seek_sync_mode": self.set_seek_sync_mode, "reload_all": self.reload_videos, @@ -260,6 +261,9 @@ def is_any_videos_live(self): def is_any_videos_have_audio(self): return any(vb.audio_tracks for vb in self._ctx.video_blocks.initialized) + def is_any_videos_have_video(self): + return any(vb.video_tracks for vb in self._ctx.video_blocks.initialized) + def is_any_videos_local_file(self): return any(vb.is_local_file for vb in self._ctx.video_blocks.initialized) diff --git a/gridplayer/widgets/video_block.py b/gridplayer/widgets/video_block.py index ba8046d..7cc4a6a 100644 --- a/gridplayer/widgets/video_block.py +++ b/gridplayer/widgets/video_block.py @@ -85,6 +85,16 @@ def wrapper(*args, **kwargs): return wrapper +def only_with_video_tacks(func): + def wrapper(*args, **kwargs): + self = args[0] # noqa: WPS117 + if not self.video_tracks: + return None + return func(*args, **kwargs) + + return wrapper + + def only_live(func): def wrapper(*args, **kwargs): self = args[0] # noqa: WPS117 @@ -421,7 +431,7 @@ def customEvent(self, event): def manual_seek(self, command, *args): getattr(self, command)(*args) - if command in {"next_frame", "previous_frame"}: + if command in {"next_frame", "previous_frame"} and self.video_tracks: self.sync_paused.emit(True) self.sync_percent.emit(self.position) @@ -791,6 +801,7 @@ def load_video_finish(self): self.video_driver.adjust_view() + @only_with_video_tacks def set_aspect(self, aspect): self.video_params.aspect_mode = aspect @@ -892,18 +903,21 @@ def seek(self, seek_ms): self.video_driver.set_time(seek_ms) self.time = seek_ms - @only_initialized + @only_with_video_tacks @only_seekable + @only_initialized def next_frame(self): self.step_frame(1) - @only_initialized + @only_with_video_tacks @only_seekable + @only_initialized def previous_frame(self): self.step_frame(-1) - @only_initialized + @only_with_video_tacks @only_seekable + @only_initialized def step_frame(self, frames): if not self.video_params.is_paused: self.set_pause(True) @@ -913,6 +927,7 @@ def step_frame(self, frames): self.seek_shift_ms(ms_per_frame * frames) + @only_with_video_tacks @only_initialized def scale_increase(self): self.video_params.scale += 0.1 @@ -920,6 +935,7 @@ def scale_increase(self): self.set_scale(self.video_params.scale) + @only_with_video_tacks @only_initialized def scale_decrease(self): self.video_params.scale -= 0.1 @@ -927,10 +943,12 @@ def scale_decrease(self): self.set_scale(self.video_params.scale) + @only_with_video_tacks @only_initialized def scale_reset(self): self.set_scale(1.0) + @only_with_video_tacks @only_initialized def set_scale(self, scale, is_silent=False): self.video_params.scale = scale