![]()
|
|
|
| import time import os import random import board import busio import pygame import cv2 from picamera2 import Picamera2 from adafruit_neotrellis.neotrellis import NeoTrellis from pygame.locals import FULLSCREEN # ========================= # PYGAME & AUDIO SETUP # ========================= pygame.init() pygame.mixer.init() screen = pygame.display.set_mode((0, 0), FULLSCREEN) clock = pygame.time.Clock() # ========================= # DIRECTORY SETUP # ========================= script_dir = os.path.dirname(os.path.realpath(__file__)) VIDEO_DIR = os.path.join(script_dir, "videos") PHOTO_DIR = os.path.join(script_dir, "photos") IMAGE_DIR = os.path.join(script_dir, "images") WARNING_IMAGE = os.path.join(IMAGE_DIR, "paowarning.png") PAOPROJECT_IMAGE = os.path.join(IMAGE_DIR, "paoeject.png") os.makedirs(PHOTO_DIR, exist_ok=True) # ========================= # STATE VARIABLES # ========================= playing_video = None playing_audio = None # Initialize Picamera2 once to suppress repeated init logs picam2 = Picamera2() picam2.configure(picam2.create_still_configuration()) picam2.start() # ========================= # HELPER FUNCTIONS # ========================= def play_audio_for_video(video_file): global playing_audio base_name = os.path.splitext(os.path.basename(video_file))[0] audio_file = os.path.join(VIDEO_DIR, f"{base_name}.mp3") if os.path.exists(audio_file): pygame.mixer.music.load(audio_file) pygame.mixer.music.play() playing_audio = audio_file print(f"Playing audio: {audio_file}") else: print(f"No audio found for {base_name}") def stop_audio(): global playing_audio if pygame.mixer.music.get_busy(): pygame.mixer.music.stop() playing_audio = None def stop_video(): """Stop currently playing video/audio immediately""" global playing_video if playing_video: playing_video.release() playing_video = None stop_audio() def take_photo(): """Take a photo with Picamera2 and save in photos folder with random filename""" while True: rand_num = random.randint(1000, 9999) photo_path = os.path.join(PHOTO_DIR, f"{rand_num}.jpg") if not os.path.exists(photo_path): break picam2.capture_file(photo_path) print(f"Photo saved: {photo_path}") return photo_path def play_video(video_file): cap = cv2.VideoCapture(video_file) if not cap.isOpened(): print("Error opening video:", video_file) return None while cap.isOpened(): ret, frame = cap.read() if not ret: break frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) frame_surface = pygame.surfarray.make_surface(frame) frame_surface = pygame.transform.rotate(frame_surface, -90) frame_surface = pygame.transform.flip(frame_surface, True, False) frame_surface = pygame.transform.scale(frame_surface, screen.get_size()) screen.blit(frame_surface, (0, 0)) pygame.display.update() for event in pygame.event.get(): if event.type == pygame.QUIT: stop_video() pygame.quit() return None trellis.sync() clock.tick(30) cap.release() stop_audio() return cap def show_image(image_path): """Display a single image fullscreen""" if os.path.exists(image_path): img = pygame.image.load(image_path) img = pygame.transform.scale(img, screen.get_size()) screen.blit(img, (0, 0)) pygame.display.update() print(f"Showing image: {image_path}") else: print(f"Image not found: {image_path}") def show_warning_image(): show_image(WARNING_IMAGE) # ========================= # BUTTON CALLBACK # ========================= def button_callback(event): global playing_video if event.edge != NeoTrellis.EDGE_RISING: return video_index = event.number # Stop any currently playing video/audio immediately stop_video() # Button 13: show paoproject.png if video_index == 12: show_image(PAOPROJECT_IMAGE) return # Button 16: take photo and display the newly taken photo if video_index == 15: new_photo = take_photo() show_image(new_photo) return # All other buttons: play video + audio video_file = os.path.join(VIDEO_DIR, f"{str(video_index+1).zfill(3)}.mp4") if os.path.exists(video_file): play_audio_for_video(video_file) playing_video = play_video(video_file) else: print(f"Video file not found: {video_file}") # ========================= # NEOTRELLIS SETUP # ========================= i2c = busio.I2C(board.SCL, board.SDA) trellis = NeoTrellis(i2c) for i in range(16): trellis.activate_key(i, NeoTrellis.EDGE_RISING) trellis.callbacks[i] = button_callback # ========================= # STARTUP # ========================= show_warning_image() for i in range(16): trellis.pixels[i] = (0, 0, 50) print("NeoTrellis controller ready!") # ========================= # MAIN LOOP # ========================= while True: trellis.sync() time.sleep(0.02) |