diff --git a/Adafruit_Video_Looper/model.py b/Adafruit_Video_Looper/model.py index fda419f..ddae9ad 100644 --- a/Adafruit_Video_Looper/model.py +++ b/Adafruit_Video_Looper/model.py @@ -2,7 +2,7 @@ # Author: Tony DiCola # License: GNU GPLv2, see LICENSE.txt import random -from typing import Optional +from typing import Optional, Union random.seed() @@ -25,11 +25,16 @@ def was_played(self): def clear_playcount(self): self.playcount = 0 - + + def finish_playing(self): + self.playcount = self.repeats+1 + def __lt__(self, other): return self.filename < other.filename def __eq__(self, other): + if isinstance(other, str): + return self.filename == other return self.filename == other.filename def __str__(self): @@ -45,6 +50,7 @@ def __init__(self, movies): """Create a playlist from the provided list of movies.""" self._movies = movies self._index = None + self._next = None def get_next(self, is_random, resume = False) -> Movie: """Get the next movie in the playlist. Will loop to start of playlist @@ -53,6 +59,13 @@ def get_next(self, is_random, resume = False) -> Movie: # Check if no movies are in the playlist and return nothing. if len(self._movies) == 0: return None + + # Check if next movie is set and jump directly there: + if self._next is not None and self._next >= 0 and self._next <= self.length(): + self._index=self._next + self._next = None + return self._movies[self._index] + # Start Random movie if is_random: self._index = random.randrange(0, self.length()) @@ -79,7 +92,30 @@ def get_next(self, is_random, resume = False) -> Movie: f.write(str(self._index)) return self._movies[self._index] + + # sets next by filename or Movie object + def set_next(self, thing: Union[Movie, str]): + if isinstance(thing, Movie): + if (thing in self._movies): + self._next(thing) + elif isinstance(thing, str): + if thing in self._movies: + self._next = self._movies[self._movies.index(thing)] + + # sets next to the absolut index + def jump(self, index:int): + self.clear_all_playcounts() + self._movies[self._index].finish_playing() + self._next = index + + # sets next relative to current index + def seek(self, amount:int): + self.jump((self._index+amount)%self.length()) def length(self): """Return the number of movies in the playlist.""" return len(self._movies) + + def clear_all_playcounts(self): + for movie in self._movies: + movie.clear_playcount() diff --git a/Adafruit_Video_Looper/video_looper.py b/Adafruit_Video_Looper/video_looper.py index 8e49d67..19b6b1e 100644 --- a/Adafruit_Video_Looper/video_looper.py +++ b/Adafruit_Video_Looper/video_looper.py @@ -82,6 +82,7 @@ def __init__(self, config_path): # Load configured video player and file reader modules. self._player = self._load_player() self._reader = self._load_file_reader() + self._playlist = None # Load ALSA hardware configuration. self._alsa_hw_device = parse_hw_device(self._config.get('alsa', 'hw_device')) self._alsa_hw_vol_control = self._config.get('alsa', 'hw_vol_control') @@ -364,6 +365,7 @@ def _handle_keyboard_shortcuts(self): self.quit() if event.key == pygame.K_k: self._print("k was pressed. skipping...") + self._playlist.seek(1) self._player.stop(3) if event.key == pygame.K_s: if self._playbackStopped: @@ -376,16 +378,21 @@ def _handle_keyboard_shortcuts(self): if event.key == pygame.K_p: self._print("p was pressed. shutting down...") self.quit(True) + if event.key == pygame.K_b: + self._print("b was pressed. jumping back...") + self._playlist.seek(-1) + self._player.stop(3) + def run(self): """Main program loop. Will never return!""" # Get playlist of movies to play from file reader. - playlist = self._build_playlist() - self._prepare_to_run_playlist(playlist) + self._playlist = self._build_playlist() + self._prepare_to_run_playlist(self._playlist) self._set_hardware_volume() - movie = playlist.get_next(self._is_random, self._resume_playlist) + movie = self._playlist.get_next(self._is_random, self._resume_playlist) # Main loop to play videos in the playlist and listen for file changes. while self._running: # Load and play a new movie if nothing is playing. @@ -394,10 +401,10 @@ def run(self): if movie.playcount >= movie.repeats: movie.clear_playcount() - movie = playlist.get_next(self._is_random, self._resume_playlist) + movie = self._playlist.get_next(self._is_random, self._resume_playlist) elif self._player.can_loop_count() and movie.playcount > 0: movie.clear_playcount() - movie = playlist.get_next(self._is_random, self._resume_playlist) + movie = self._playlist.get_next(self._is_random, self._resume_playlist) movie.was_played() @@ -411,13 +418,13 @@ def run(self): infotext = '{0} time{1} (player counts loops)'.format(movie.repeats, "s" if movie.repeats>1 else "") else: infotext = '{0}/{1}'.format(movie.playcount, movie.repeats) - if playlist.length()==1: + if self._playlist.length()==1: infotext = '(endless loop)' # Start playing the first available movie. self._print('Playing movie: {0} {1}'.format(movie, infotext)) # todo: maybe clear screen to black so that background (image/color) is not visible for videos with a resolution that is < screen resolution - self._player.play(movie, loop=-1 if playlist.length()==1 else None, vol = self._sound_vol) + self._player.play(movie, loop=-1 if self._playlist.length()==1 else None, vol = self._sound_vol) # Check for changes in the file search path (like USB drives added) # and rebuild the playlist. @@ -427,13 +434,13 @@ def run(self): # player to stop. self._print("player stopped") # Rebuild playlist and show countdown again (if OSD enabled). - playlist = self._build_playlist() + self._playlist = self._build_playlist() #refresh background image if self._copyloader: self._bgimage = self._load_bgimage() - self._prepare_to_run_playlist(playlist) + self._prepare_to_run_playlist(self._playlist) self._set_hardware_volume() - movie = playlist.get_next(self._is_random, self._resume_playlist) + movie = self._playlist.get_next(self._is_random, self._resume_playlist) # Give the CPU some time to do other tasks. low values increase "responsiveness to changes" and reduce the pause between files # but increase CPU usage diff --git a/README.md b/README.md index 148795b..928d7f7 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,9 @@ For a detailed tutorial visit: (but they might not always contain the latest version of pi_video_looper) ## Changelog +#### new in v1.0.12 + - added "back" keyboard shortcut to play previous file + #### v1.0.11 - fixed skip bug with image_player - fixed possible dependency issue @@ -131,6 +134,7 @@ Note: files with the same name always get overwritten. The following keyboard commands are active by default (can be disabled in the [video_looper.ini](https://github.com/adafruit/pi_video_looper/blob/master/assets/video_looper.ini)): * "ESC" - stops playback and exits video_looper * "k" - sKip - stops the playback of current file and plays next file +* "b" - Back - stops the playback of current file and plays previous file * "s" - Stop/Start - stops or starts playback of current file * "p" - Power off - stop playback and shutdown RPi