3
3
import signal
4
4
import sys
5
5
import time
6
- from enum import Enum , IntEnum , auto , unique
6
+ from enum import Enum , IntFlag , auto , unique
7
7
from pathlib import Path
8
8
from typing import Any , Dict , List , Optional , Tuple , Union
9
9
@@ -52,16 +52,20 @@ class AspectRatio(Enum):
52
52
53
53
54
54
@unique
55
- class State (IntEnum ):
55
+ class State (IntFlag ):
56
56
"""Represents all possible states of a slide presentation."""
57
57
58
+ """A video is actively being played."""
58
59
PLAYING = auto ()
60
+ """A video was manually paused."""
59
61
PAUSED = auto ()
62
+ """Waiting for user to press next (or else)."""
60
63
WAIT = auto ()
64
+ """Presentation was terminated."""
61
65
END = auto ()
62
66
63
67
def __str__ (self ) -> str :
64
- return self .name .capitalize ()
68
+ return self .name .capitalize () # type: ignore
65
69
66
70
67
71
def now () -> float :
@@ -271,10 +275,10 @@ def reset(self) -> None:
271
275
272
276
def load_last_slide (self ) -> None :
273
277
"""Loads last slide."""
274
- self .current_slide_index = len (self .slides ) - 2
278
+ self .current_slide_index = len (self .slides ) - 1
275
279
assert (
276
280
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 "
278
282
self .current_animation = self .current_slide .start_animation
279
283
self .load_animation_cap (self .current_animation )
280
284
self .slides [- 1 ].terminated = False
@@ -307,41 +311,37 @@ def update_state(self, state: State) -> Tuple[np.ndarray, State]:
307
311
It does this by reading the video information and checking if the state is still correct.
308
312
It returns the frame to show (lastframe) and the new state.
309
313
"""
310
- if state == State .PAUSED :
314
+ if state ^ State .PLAYING : # If not playing, we return the same
311
315
if self .lastframe is None :
312
316
_ , self .lastframe = self .current_cap .read ()
313
317
return self .lastframe , state
318
+
314
319
still_playing , frame = self .current_cap .read ()
320
+
315
321
if still_playing :
316
322
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 :
324
329
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
339
337
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 )
345
345
346
346
return self .lastframe , state
347
347
@@ -423,25 +423,27 @@ def current_background_color(self) -> Color:
423
423
"""Returns the background color of the current presentation."""
424
424
return self .current_presentation .background_color
425
425
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
+
426
431
def run (self ) -> None :
427
432
"""Runs a series of presentations until end or exit."""
428
433
while self .run_flag :
429
434
last_time = now ()
430
435
self .lastframe , self .state = self .current_presentation .update_state (
431
436
self .state
432
437
)
433
- if self .state == State .PLAYING or self . state == State .PAUSED :
438
+ if self .state & ( State .PLAYING | State .PAUSED ) :
434
439
if self .start_paused :
435
440
self .state = State .PAUSED
436
441
self .start_paused = False
437
- if self .state == State .END :
442
+ if self .state & State .END :
438
443
if self .current_presentation_index == len (self .presentations ) - 1 :
439
444
if self .exit_after_last_slide :
440
445
self .run_flag = False
441
446
continue
442
- else :
443
- self .current_presentation_index += 1
444
- self .state = State .PLAYING
445
447
446
448
self .handle_key ()
447
449
self .show_video ()
@@ -548,10 +550,14 @@ def handle_key(self) -> None:
548
550
self .state = State .PAUSED
549
551
elif self .state == State .PAUSED and keys .PLAY_PAUSE .match (key ):
550
552
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
553
555
):
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 ()
555
561
self .state = State .PLAYING
556
562
elif (
557
563
self .state == State .PLAYING and keys .CONTINUE .match (key )
@@ -562,6 +568,7 @@ def handle_key(self) -> None:
562
568
if self .current_presentation_index == 0 :
563
569
self .current_presentation .load_previous_slide ()
564
570
else :
571
+ self .current_presentation .cancel_reverse ()
565
572
self .current_presentation_index -= 1
566
573
self .current_presentation .load_last_slide ()
567
574
self .state = State .PLAYING
0 commit comments