fix(present): finish up state machine (#234)

This commit is contained in:
Jérome Eertmans
2023-08-04 16:17:21 +02:00
committed by GitHub
parent 9e1e0f2367
commit 455f104a11

View File

@ -3,7 +3,7 @@ import platform
import signal import signal
import sys import sys
import time import time
from enum import Enum, IntEnum, auto, unique from enum import Enum, IntFlag, auto, unique
from pathlib import Path from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple, Union from typing import Any, Dict, List, Optional, Tuple, Union
@ -60,16 +60,20 @@ RESIZE_MODES = {
@unique @unique
class State(IntEnum): class State(IntFlag):
"""Represents all possible states of a slide presentation.""" """Represents all possible states of a slide presentation."""
"""A video is actively being played."""
PLAYING = auto() PLAYING = auto()
"""A video was manually paused."""
PAUSED = auto() PAUSED = auto()
"""Waiting for user to press next (or else)."""
WAIT = auto() WAIT = auto()
"""Presentation was terminated."""
END = auto() END = auto()
def __str__(self) -> str: def __str__(self) -> str:
return self.name.capitalize() return self.name.capitalize() # type: ignore
def now() -> float: def now() -> float:
@ -279,10 +283,10 @@ class Presentation:
def load_last_slide(self) -> None: def load_last_slide(self) -> None:
"""Loads last slide.""" """Loads last slide."""
self.current_slide_index = len(self.slides) - 2 self.current_slide_index = len(self.slides) - 1
assert ( assert (
self.current_slide_index >= 0 self.current_slide_index >= 0
), "Slides should be at list of a least two elements" ), "Slides should be at list of a least one element"
self.current_animation = self.current_slide.start_animation self.current_animation = self.current_slide.start_animation
self.load_animation_cap(self.current_animation) self.load_animation_cap(self.current_animation)
self.slides[-1].terminated = False self.slides[-1].terminated = False
@ -315,34 +319,30 @@ class Presentation:
It does this by reading the video information and checking if the state is still correct. It does this by reading the video information and checking if the state is still correct.
It returns the frame to show (lastframe) and the new state. It returns the frame to show (lastframe) and the new state.
""" """
if state == State.PAUSED: if state ^ State.PLAYING: # If not playing, we return the same
if self.lastframe is None: if self.lastframe is None:
_, self.lastframe = self.current_cap.read() _, self.lastframe = self.current_cap.read()
return self.lastframe, state return self.lastframe, state
still_playing, frame = self.current_cap.read() still_playing, frame = self.current_cap.read()
if still_playing: if still_playing:
self.lastframe = frame self.lastframe = frame
elif state == state.WAIT or state == state.PAUSED: # type: ignore return self.lastframe, State.PLAYING
return self.lastframe, state
elif self.current_slide.is_last() and self.current_slide.terminated: # Video was terminated
return self.lastframe, State.END
else: # not still playing
if self.is_last_animation: if self.is_last_animation:
if self.current_slide.is_slide(): if self.current_slide.is_loop():
state = State.WAIT
elif self.current_slide.is_loop():
if self.reverse: if self.reverse:
state = State.WAIT state = State.WAIT
else: else:
self.current_animation = self.current_slide.start_animation self.current_animation = self.current_slide.start_animation
state = State.PLAYING state = State.PLAYING
self.rewind_current_slide() self.rewind_current_slide()
elif self.current_slide.is_last(): elif self.current_slide.is_last():
self.current_slide.terminated = True state = State.END
elif ( else:
self.current_slide.is_last()
and self.current_slide.end_animation == self.current_animation
):
state = State.WAIT state = State.WAIT
else: else:
# Play next video! # Play next video!
@ -431,6 +431,11 @@ class Display(QThread): # type: ignore
"""Returns the background color of the current presentation.""" """Returns the background color of the current presentation."""
return self.current_presentation.background_color return self.current_presentation.background_color
@property
def is_last_presentation(self) -> bool:
"""Returns True if current presentation is the last one."""
return self.current_presentation_index == len(self) - 1
def start(self) -> None: def start(self) -> None:
super().start() super().start()
self.change_presentation_signal.emit() self.change_presentation_signal.emit()
@ -442,18 +447,15 @@ class Display(QThread): # type: ignore
self.lastframe, self.state = self.current_presentation.update_state( self.lastframe, self.state = self.current_presentation.update_state(
self.state self.state
) )
if self.state == State.PLAYING or self.state == State.PAUSED: if self.state & (State.PLAYING | State.PAUSED):
if self.start_paused: if self.start_paused:
self.state = State.PAUSED self.state = State.PAUSED
self.start_paused = False self.start_paused = False
if self.state == State.END: if self.state & State.END:
if self.current_presentation_index == len(self.presentations) - 1: if self.current_presentation_index == len(self.presentations) - 1:
if self.exit_after_last_slide: if self.exit_after_last_slide:
self.run_flag = False self.run_flag = False
continue continue
else:
self.current_presentation_index += 1
self.state = State.PLAYING
self.handle_key() self.handle_key()
self.show_video() self.show_video()
@ -560,9 +562,13 @@ class Display(QThread): # type: ignore
self.state = State.PAUSED self.state = State.PAUSED
elif self.state == State.PAUSED and keys.PLAY_PAUSE.match(key): elif self.state == State.PAUSED and keys.PLAY_PAUSE.match(key):
self.state = State.PLAYING self.state = State.PLAYING
elif self.state == State.WAIT and ( elif self.state & (State.END | State.WAIT) and (
keys.CONTINUE.match(key) or keys.PLAY_PAUSE.match(key) keys.CONTINUE.match(key) or keys.PLAY_PAUSE.match(key) or self.skip_all
): ):
if (self.state & State.END) and not self.is_last_presentation:
self.current_presentation_index += 1
self.current_presentation.rewind_current_slide()
else:
self.current_presentation.load_next_slide() self.current_presentation.load_next_slide()
self.state = State.PLAYING self.state = State.PLAYING
elif ( elif (
@ -574,6 +580,7 @@ class Display(QThread): # type: ignore
if self.current_presentation_index == 0: if self.current_presentation_index == 0:
self.current_presentation.load_previous_slide() self.current_presentation.load_previous_slide()
else: else:
self.current_presentation.cancel_reverse()
self.current_presentation_index -= 1 self.current_presentation_index -= 1
self.current_presentation.load_last_slide() self.current_presentation.load_last_slide()
self.state = State.PLAYING self.state = State.PLAYING