33import signal
44import sys
55import time
6- from enum import Enum , IntEnum , auto , unique
6+ from enum import Enum , IntFlag , auto , unique
77from pathlib import Path
88from typing import Any , Dict , List , Optional , Tuple , Union
99
@@ -52,16 +52,20 @@ class AspectRatio(Enum):
5252
5353
5454@unique
55- class State (IntEnum ):
55+ class State (IntFlag ):
5656 """Represents all possible states of a slide presentation."""
5757
58+ """A video is actively being played."""
5859 PLAYING = auto ()
60+ """A video was manually paused."""
5961 PAUSED = auto ()
62+ """Waiting for user to press next (or else)."""
6063 WAIT = auto ()
64+ """Presentation was terminated."""
6165 END = auto ()
6266
6367 def __str__ (self ) -> str :
64- return self .name .capitalize ()
68+ return self .name .capitalize () # type: ignore
6569
6670
6771def now () -> float :
@@ -271,10 +275,10 @@ def reset(self) -> None:
271275
272276 def load_last_slide (self ) -> None :
273277 """Loads last slide."""
274- self .current_slide_index = len (self .slides ) - 2
278+ self .current_slide_index = len (self .slides ) - 1
275279 assert (
276280 self .current_slide_index >= 0
277- ), "Slides should be at list of a least two elements "
281+ ), "Slides should be at list of a least one element "
278282 self .current_animation = self .current_slide .start_animation
279283 self .load_animation_cap (self .current_animation )
280284 self .slides [- 1 ].terminated = False
@@ -307,41 +311,37 @@ def update_state(self, state: State) -> Tuple[np.ndarray, State]:
307311 It does this by reading the video information and checking if the state is still correct.
308312 It returns the frame to show (lastframe) and the new state.
309313 """
310- if state == State .PAUSED :
314+ if state ^ State .PLAYING : # If not playing, we return the same
311315 if self .lastframe is None :
312316 _ , self .lastframe = self .current_cap .read ()
313317 return self .lastframe , state
318+
314319 still_playing , frame = self .current_cap .read ()
320+
315321 if still_playing :
316322 self .lastframe = frame
317- elif state == state .WAIT or state == state .PAUSED : # type: ignore
318- return self .lastframe , state
319- elif self .current_slide .is_last () and self .current_slide .terminated :
320- return self .lastframe , State .END
321- else : # not still playing
322- if self .is_last_animation :
323- if self .current_slide .is_slide ():
323+ return self .lastframe , State .PLAYING
324+
325+ # Video was terminated
326+ if self .is_last_animation :
327+ if self .current_slide .is_loop ():
328+ if self .reverse :
324329 state = State .WAIT
325- elif self .current_slide .is_loop ():
326- if self .reverse :
327- state = State .WAIT
328- else :
329- self .current_animation = self .current_slide .start_animation
330- state = State .PLAYING
331- self .rewind_current_slide ()
332- elif self .current_slide .is_last ():
333- self .current_slide .terminated = True
334- elif (
335- self .current_slide .is_last ()
336- and self .current_slide .end_animation == self .current_animation
337- ):
338- state = State .WAIT
330+
331+ else :
332+ self .current_animation = self .current_slide .start_animation
333+ state = State .PLAYING
334+ self .rewind_current_slide ()
335+ elif self .current_slide .is_last ():
336+ state = State .END
339337 else :
340- # Play next video!
341- self .current_animation = self .next_animation
342- self .load_animation_cap (self .current_animation )
343- # Reset video to position zero if it has been played before
344- self .current_cap .set (cv2 .CAP_PROP_POS_FRAMES , 0 )
338+ state = State .WAIT
339+ else :
340+ # Play next video!
341+ self .current_animation = self .next_animation
342+ self .load_animation_cap (self .current_animation )
343+ # Reset video to position zero if it has been played before
344+ self .current_cap .set (cv2 .CAP_PROP_POS_FRAMES , 0 )
345345
346346 return self .lastframe , state
347347
@@ -423,25 +423,27 @@ def current_background_color(self) -> Color:
423423 """Returns the background color of the current presentation."""
424424 return self .current_presentation .background_color
425425
426+ @property
427+ def is_last_presentation (self ) -> bool :
428+ """Returns True if current presentation is the last one."""
429+ return self .current_presentation_index == len (self ) - 1
430+
426431 def run (self ) -> None :
427432 """Runs a series of presentations until end or exit."""
428433 while self .run_flag :
429434 last_time = now ()
430435 self .lastframe , self .state = self .current_presentation .update_state (
431436 self .state
432437 )
433- if self .state == State .PLAYING or self . state == State .PAUSED :
438+ if self .state & ( State .PLAYING | State .PAUSED ) :
434439 if self .start_paused :
435440 self .state = State .PAUSED
436441 self .start_paused = False
437- if self .state == State .END :
442+ if self .state & State .END :
438443 if self .current_presentation_index == len (self .presentations ) - 1 :
439444 if self .exit_after_last_slide :
440445 self .run_flag = False
441446 continue
442- else :
443- self .current_presentation_index += 1
444- self .state = State .PLAYING
445447
446448 self .handle_key ()
447449 self .show_video ()
@@ -548,10 +550,14 @@ def handle_key(self) -> None:
548550 self .state = State .PAUSED
549551 elif self .state == State .PAUSED and keys .PLAY_PAUSE .match (key ):
550552 self .state = State .PLAYING
551- elif self .state == State .WAIT and (
552- keys .CONTINUE .match (key ) or keys .PLAY_PAUSE .match (key )
553+ elif self .state & ( State .END | State . WAIT ) and (
554+ keys .CONTINUE .match (key ) or keys .PLAY_PAUSE .match (key ) or self . skip_all
553555 ):
554- self .current_presentation .load_next_slide ()
556+ if (self .state & State .END ) and not self .is_last_presentation :
557+ self .current_presentation_index += 1
558+ self .current_presentation .rewind_current_slide ()
559+ else :
560+ self .current_presentation .load_next_slide ()
555561 self .state = State .PLAYING
556562 elif (
557563 self .state == State .PLAYING and keys .CONTINUE .match (key )
@@ -562,6 +568,7 @@ def handle_key(self) -> None:
562568 if self .current_presentation_index == 0 :
563569 self .current_presentation .load_previous_slide ()
564570 else :
571+ self .current_presentation .cancel_reverse ()
565572 self .current_presentation_index -= 1
566573 self .current_presentation .load_last_slide ()
567574 self .state = State .PLAYING
0 commit comments