import RPi.GPIO as GPIO import os import time import mpv import random # Import random module to handle random video selection import subprocess # Set up GPIO pins for Buttons and LEDs GPIO.setmode(GPIO.BCM) BUTTON_PIN_1 = 14 BUTTON_PIN_2 = 15 BUTTON_PIN_3 = 18 BUTTON_PIN_4 = 23 BUTTON_PIN_5 = 24 BUTTON_PIN_6 = 25 BUTTON_PIN_7 = 8 LED_PIN_1 = 2 LED_PIN_2 = 3 LED_PIN_3 = 4 LED_PIN_4 = 17 LED_PIN_5 = 27 LED_PIN_6 = 22 LED_PIN_7 = 10 buttons = [BUTTON_PIN_1, BUTTON_PIN_2, BUTTON_PIN_3, BUTTON_PIN_4, BUTTON_PIN_5, BUTTON_PIN_6, BUTTON_PIN_7] leds = [LED_PIN_1, LED_PIN_2, LED_PIN_3, LED_PIN_4, LED_PIN_5, LED_PIN_6, LED_PIN_7] # Set up buttons and LEDs for button in buttons: GPIO.setup(button, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Buttons connect to GND when pressed for led in leds: GPIO.setup(led, GPIO.OUT) # Define the video and button actions (using custom video names here) video_folder = "/home/ezn/sorgin" video_paths = { 1: {"video": "0000-Herensugea.mp4", "leds": [LED_PIN_1], "buttons": [BUTTON_PIN_1], "next_videos": [2], "duration": 184}, 2: {"video": "0001-Herensugea.mp4", "leds": [LED_PIN_1], "buttons": [BUTTON_PIN_1], "next_videos": [3], "duration": 221}, 3: {"video": "0003-Herensugea.mp4", "leds": [LED_PIN_2, LED_PIN_3, LED_PIN_4, LED_PIN_5], "buttons": [BUTTON_PIN_2, BUTTON_PIN_3, BUTTON_PIN_4, BUTTON_PIN_5], "next_videos": [4, 15, 27, 39], "duration": 153}, 4: {"video": "0101-Tartalo.mp4", "leds": [LED_PIN_6, LED_PIN_4], "buttons": [BUTTON_PIN_6, BUTTON_PIN_4], "next_videos": [6, 26], "duration": 337}, 5: {"video": "0102B-Xarma.mp4", "leds": [LED_PIN_5, LED_PIN_2], "buttons": [BUTTON_PIN_5, BUTTON_PIN_2], "next_videos": [41, 7], "duration": 249}, 6: {"video": "0102-Xarma.mp4", "leds": [LED_PIN_2], "buttons": [BUTTON_PIN_2], "next_videos": [7], "duration": 328}, 7: {"video": "0103-Xarma-Tartalo.mp4", "leds": [LED_PIN_5, LED_PIN_3], "buttons": [BUTTON_PIN_5, BUTTON_PIN_3], "next_videos": [8, 32], "duration": 280}, 8: {"video": "0104-IpariSuri-Maider.mp4", "leds": [LED_PIN_3, LED_PIN_6], "buttons": [BUTTON_PIN_3, BUTTON_PIN_6], "next_videos": [44, 10], "duration": 263}, 9: {"video": "0105E-EYES-IpariSuri.mp4", "leds": [LED_PIN_2, LED_PIN_7], "buttons": [BUTTON_PIN_2, BUTTON_PIN_7], "next_videos": [19, 11], "duration": 312}, 10: {"video": "0105-IpariSuri-Maider-Xarma-Tartalo.mp4", "leds": [LED_PIN_5, LED_PIN_2, LED_PIN_7], "buttons": [BUTTON_PIN_5, BUTTON_PIN_2, BUTTON_PIN_7], "next_videos": [9, 19, 11], "duration": 254}, 11: {"video": "0106-Mairu.mp4", "leds": [LED_PIN_4, LED_PIN_7], "buttons": [BUTTON_PIN_4, BUTTON_PIN_7], "next_videos": [12, 22], "duration": 346}, 12: {"video": "0107-Mairu-Oxik.mp4", "leds": [LED_PIN_1], "buttons": [BUTTON_PIN_1], "next_videos": [13], "duration": 430}, 13: {"video": "0199-END.mp4", "leds": [], "buttons": [], "next_videos": [], "duration": 266}, 14: {"video": "0201B-Maider.mp4", "leds": [LED_PIN_5], "buttons": [BUTTON_PIN_5], "next_videos": [16], "duration": 387}, 15: {"video": "0201-Maider.mp4", "leds": [LED_PIN_3, LED_PIN_6], "buttons": [BUTTON_PIN_3, BUTTON_PIN_6], "next_videos": [16, 5], "duration": 396}, 16: {"video": "0202-MaiderIpariSuri.mp4", "leds": [LED_PIN_2, LED_PIN_7], "buttons": [BUTTON_PIN_2, BUTTON_PIN_7], "next_videos": [17, 28], "duration": 296}, 17: {"video": "0203-Tartalo.mp4", "leds": [LED_PIN_5], "buttons": [BUTTON_PIN_5], "next_videos": [18], "duration": 262}, 18: {"video": "0204-Tartalo-IpariSuri-Maider.mp4", "leds": [LED_PIN_2, LED_PIN_5], "buttons": [BUTTON_PIN_2, BUTTON_PIN_5], "next_videos": [19, 34], "duration": 284}, 19: {"video": "0205-Oxik.mp4", "leds": [LED_PIN_2, LED_PIN_7], "buttons": [BUTTON_PIN_2, BUTTON_PIN_7], "next_videos": [20, 43], "duration": 385}, 20: {"video": "0206-Oxik-Tartalo.mp4", "leds": [LED_PIN_7, LED_PIN_5], "buttons": [BUTTON_PIN_7, BUTTON_PIN_5], "next_videos": [21, 35], "duration": 293}, 21: {"video": "0207-XarmaMairu.mp4", "leds": [LED_PIN_3], "buttons": [BUTTON_PIN_3], "next_videos": [22], "duration": 303}, 22: {"video": "0208-ALL.mp4", "leds": [LED_PIN_1, LED_PIN_7], "buttons": [BUTTON_PIN_1, BUTTON_PIN_7], "next_videos": [25, 23], "duration": 420}, 23: {"video": "0208E-EYES-Mairu.mp4", "leds": [LED_PIN_1, LED_PIN_5], "buttons": [BUTTON_PIN_1, BUTTON_PIN_5], "next_videos": [25, 24], "duration": 341}, 24: {"video": "0208E-EYES-Xarma.mp4", "leds": [LED_PIN_1], "buttons": [BUTTON_PIN_1], "next_videos": [25], "duration": 367}, 25: {"video": "0299-END.mp4", "leds": [], "buttons": [], "next_videos": [], "duration": 249}, 26: {"video": "0301B-Oxik.mp4", "leds": [LED_PIN_6, LED_PIN_7], "buttons": [BUTTON_PIN_6, BUTTON_PIN_7], "next_videos": [5, 29], "duration": 311}, 27: {"video": "0301-Oxik.mp4", "leds": [LED_PIN_7, LED_PIN_6], "buttons": [BUTTON_PIN_7, BUTTON_PIN_6], "next_videos": [30, 40], "duration": 286}, 28: {"video": "0302B-Mairu.mp4", "leds": [LED_PIN_4], "buttons": [BUTTON_PIN_4], "next_videos": [31], "duration": 256}, 29: {"video": "0302C-Mairu.mp4", "leds": [LED_PIN_2, LED_PIN_4], "buttons": [BUTTON_PIN_2, BUTTON_PIN_4], "next_videos": [43, 31], "duration": 215}, 30: {"video": "0302-Mairu.mp4", "leds": [LED_PIN_4], "buttons": [BUTTON_PIN_4], "next_videos": [31], "duration": 261}, 31: {"video": "0303-Oxik-Mairu.mp4", "leds": [LED_PIN_6, LED_PIN_2], "buttons": [BUTTON_PIN_6, BUTTON_PIN_2], "next_videos": [32, 43], "duration": 214}, 32: {"video": "0304-Xarma-Tartalo-Maider.mp4", "leds": [LED_PIN_4, LED_PIN_3], "buttons": [BUTTON_PIN_4, BUTTON_PIN_3], "next_videos": [34, 44], "duration": 304}, 33: {"video": "0305E-EYES-Tartalo.mp4", "leds": [LED_PIN_6, LED_PIN_5], "buttons": [BUTTON_PIN_6, BUTTON_PIN_5], "next_videos": [21, 35], "duration": 371}, 34: {"video": "0305-Xarma-Tartalo-Maider-Mairu-Oxik.mp4", "leds": [LED_PIN_6, LED_PIN_5, LED_PIN_2], "buttons": [BUTTON_PIN_6, BUTTON_PIN_5, BUTTON_PIN_2], "next_videos": [21, 35, 33], "duration": 296}, 35: {"video": "0306-IpariSuri.mp4", "leds": [LED_PIN_5, LED_PIN_3], "buttons": [BUTTON_PIN_5, BUTTON_PIN_3], "next_videos": [45, 36], "duration": 321}, 36: {"video": "0307-ALL.mp4", "leds": [LED_PIN_3, LED_PIN_1], "buttons": [BUTTON_PIN_3, BUTTON_PIN_1], "next_videos": [37, 38], "duration": 374}, 37: {"video": "0307E-EYES-Maider.mp4", "leds": [LED_PIN_1], "buttons": [BUTTON_PIN_1], "next_videos": [38], "duration": 350}, 38: {"video": "0399-END.mp4", "leds": [], "buttons": [], "next_videos": [], "duration": 244}, 39: {"video": "0401-IpariSuri.mp4", "leds": [LED_PIN_2, LED_PIN_6], "buttons": [BUTTON_PIN_2, BUTTON_PIN_6], "next_videos": [17, 40], "duration": 274}, 40: {"video": "0402-Xarma.mp4", "leds": [LED_PIN_2, LED_PIN_5], "buttons": [BUTTON_PIN_2, BUTTON_PIN_5], "next_videos": [5, 41], "duration": 326}, 41: {"video": "0403-Xarma-IpariSuri.mp4", "leds": [LED_PIN_7, LED_PIN_5], "buttons": [BUTTON_PIN_7, BUTTON_PIN_5], "next_videos": [43, 8], "duration": 299}, 42: {"video": "0404E-EYES-Oxik.mp4", "leds": [LED_PIN_7, LED_PIN_3, LED_PIN_4], "buttons": [BUTTON_PIN_7, BUTTON_PIN_3, BUTTON_PIN_4], "next_videos": [11, 44, 20], "duration": 229}, 43: {"video": "0404-Oxik-Tartalo-Mairu.mp4", "leds": [LED_PIN_1, LED_PIN_7, LED_PIN_3, LED_PIN_2], "buttons": [BUTTON_PIN_1, BUTTON_PIN_7, BUTTON_PIN_3, BUTTON_PIN_2], "next_videos": [42, 11, 44, 20], "duration": 237}, 44: {"video": "0405-Maider.mp4", "leds": [LED_PIN_5, LED_PIN_3], "buttons": [BUTTON_PIN_5, BUTTON_PIN_3], "next_videos": [36, 45], "duration": 409}, 45: {"video": "0406-MaiderIpariSuri.mp4", "leds": [LED_PIN_1], "buttons": [BUTTON_PIN_1], "next_videos": [46], "duration": 280}, 46: {"video": "0499-END.mp4", "leds": [], "buttons": [], "next_videos": [], "duration": 216}, } # Initialize mpv player player = mpv.MPV(ytdl=True, keep_open=True, fullscreen=True) # Function to play a video using mpv def play_video(video_name, loop=False): video_path = os.path.join(video_folder, video_name) if os.path.exists(video_path): print(f"Now playing {video_name}") player.play(video_path) player.loop = loop time.sleep(0.5) # Small delay to ensure the video is properly loaded while not player.idle: time.sleep(0.1) else: print(f"Video {video_name} not found.") # Function to activate buttons and LEDs for the next video def activate_next_buttons_and_leds(buttons_to_enable, leds_to_enable): for button in buttons: GPIO.setup(button, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) for led in leds: GPIO.output(led, GPIO.LOW) for button in buttons_to_enable: GPIO.setup(button, GPIO.IN, pull_up_down=GPIO.PUD_UP) for led in leds_to_enable: GPIO.output(led, GPIO.HIGH) # Function to activate buttons and LEDs before the video ends def activate_before_video_ends(video_info): video_duration = video_info["duration"] if video_info["video"] == "0000-Herensugea.mp4": return time_to_activate = video_duration - 120 print(f"Activating buttons/LEDs at {time_to_activate} seconds.") time.sleep(time_to_activate) activate_next_buttons_and_leds(video_info["buttons"], video_info["leds"]) # Function to wait for button press and transition to next video no_press_count = 0 # Function to handle the video chain def wait_for_button_press(video_info): service_name = "sorgin" global no_press_count last_button_press = None timeout = video_info["duration"] - 30 start_time = time.time() print(f"Waiting for button press from {video_info['buttons']}...") while True: # Check for button presses pressed_button = None for button in video_info["buttons"]: if GPIO.input(button) == GPIO.LOW: # Button pressed if last_button_press != button: last_button_press = button pressed_button = button print(f"Button {button} pressed.") no_press_count = 0 time.sleep(0.5) # Debounce delay (0.5 seconds) break # Exit loop after a button is pressed if pressed_button: # Find the index of the pressed button in the video_info['buttons'] button_index = video_info["buttons"].index(pressed_button) # Now select the next video based on this index if button_index < len(video_info["next_videos"]): next_video_id = video_info["next_videos"][button_index] # Use the index of the button press handle_video_chain(next_video_id) # Play the correct next video return # If no button was pressed, handle timeout elapsed_time = time.time() - start_time if elapsed_time >= timeout: print(f"Timeout reached after {elapsed_time:.2f} seconds.") no_press_count += 1 if no_press_count >= 2: print("Two consecutive timeouts. Restarting from Video 1.") no_press_count = 0 print(f"Restarting service: {service_name}") subprocess.run(["sudo", "systemctl", "restart", service_name], check=True) print(f"Service {service_name} restarted successfully.") exit() else: # Handle transition to the next video after timeout if video_info["next_videos"]: next_video_id = random.choice(video_info["next_videos"]) # Randomly choose from next_videos handle_video_chain(next_video_id) else: print("No next video available. Restarting from Video 1.") print(f"Restarting service: {service_name}") subprocess.run(["sudo", "systemctl", "restart", service_name], check=True) print(f"Service {service_name} restarted successfully.") exit() time.sleep(0.1) # Small delay to reduce CPU usage # Function to deactivate all buttons and LEDs def deactivate_all_buttons_and_leds(): print("Deactivating all buttons and LEDs...") # Deactivate all buttons for button in buttons: GPIO.setup(button, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # Turn off all LEDs for led in leds: GPIO.output(led, GPIO.LOW) time.sleep(0.1) # Ensure all GPIO changes take effect print("All buttons and LEDs deactivated.") # Function to handle the video chain def handle_video_chain(video_id): video_info = video_paths.get(video_id) if not video_info: print(f"Error: Video with ID {video_id} not found.") return print(f"Playing video: {video_info['video']}") if video_id == 1: play_video(video_info["video"], loop=True) else: play_video(video_info["video"], loop=False) deactivate_all_buttons_and_leds() activate_before_video_ends(video_info) wait_for_button_press(video_info) # Function to start looping Video 0000-Herensugea.mp4 def loop_video(): print("Starting Video 0000-Herensugea.mp4...") # Initially turn off all LEDs for led in leds: GPIO.output(led, GPIO.LOW) video_name = "0000-Herensugea.mp4" video_path = os.path.join(video_folder, video_name) if not os.path.exists(video_path): print(f"Error: {video_name} not found.") return print(f"Looping video {video_name} until Button 1 is pressed.") player.play(video_path) player.loop = True # Enable infinite looping GPIO.output(LED_PIN_1, GPIO.HIGH) # Activate LED 1 GPIO.setup(BUTTON_PIN_1, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Enable Button 1 print("Button 1 and LED 1 activated.") try: while True: # Monitor BUTTON_PIN_1 if GPIO.input(BUTTON_PIN_1) == GPIO.LOW: # Button pressed print("Button 1 pressed. Exiting loop...") player.stop() # Stop the player handle_video_chain(2) # Transition to the next video return time.sleep(0.1) # Small delay to reduce CPU usage except Exception as e: print(f"Error during looping: {e}") finally: player.stop() # Ensure the player stops when exiting # Function to reset GPIO pins and states def reset_gpio_pins(): for button in buttons: GPIO.setup(button, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Reset buttons to input mode with pull-up for led in leds: GPIO.output(led, GPIO.LOW) # Turn off all LEDs # Main function to run the system def start_system(): try: loop_video() # Start with the looping video except KeyboardInterrupt: print("Program interrupted, cleaning up GPIO.") GPIO.cleanup() except Exception as e: print(f"Unexpected error: {e}") GPIO.cleanup() if __name__ == "__main__": start_system()