video control & random start
This commit is contained in:
214
video_player.py
214
video_player.py
@@ -12,6 +12,8 @@ import logging
|
||||
import threading
|
||||
import queue
|
||||
import subprocess
|
||||
import argparse
|
||||
import random
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
import vlc
|
||||
@@ -244,6 +246,49 @@ class VideoPlayer:
|
||||
self.logger.error(f"Error playing channel {channel_number}: {e}")
|
||||
return False
|
||||
|
||||
def play_random_video(self) -> bool:
|
||||
"""Play a random video from the available channels"""
|
||||
if not self.channels:
|
||||
self.logger.error("No channels available for random playback")
|
||||
return False
|
||||
|
||||
try:
|
||||
# Get a random channel number
|
||||
random_channel = random.choice(list(self.channels.keys()))
|
||||
self.logger.info(f"Selected random channel: {random_channel}")
|
||||
return self.play_channel(random_channel)
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error playing random video: {e}")
|
||||
return False
|
||||
|
||||
def play_video_by_index(self, index: int) -> bool:
|
||||
"""Play video by folder index (0-based)"""
|
||||
video_files = self.scan_video_folder()
|
||||
|
||||
if not video_files:
|
||||
self.logger.error("No video files found")
|
||||
return False
|
||||
|
||||
if index < 0 or index >= len(video_files):
|
||||
self.logger.warning(f"Index {index} out of range (0-{len(video_files)-1})")
|
||||
return False
|
||||
|
||||
try:
|
||||
video_file = video_files[index]
|
||||
media = self.vlc_instance.media_new(str(video_file))
|
||||
self.vlc_player.set_media(media)
|
||||
self.vlc_player.play()
|
||||
|
||||
self.current_channel = None # Not a channel-based playback
|
||||
self.logger.info(f"Playing video by index {index}: {video_file.name}")
|
||||
|
||||
# Wait for media to start playing
|
||||
time.sleep(0.5)
|
||||
return True
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error playing video by index {index}: {e}")
|
||||
return False
|
||||
|
||||
def setup_gpio(self):
|
||||
"""Setup GPIO for IR receiver"""
|
||||
try:
|
||||
@@ -413,9 +458,15 @@ class VideoPlayer:
|
||||
self.logger.info("Power toggle - shutting down")
|
||||
self.running = False
|
||||
|
||||
def start(self):
|
||||
"""Start the video player"""
|
||||
self.logger.info("Starting video player...")
|
||||
def start(self, startup_mode: str = "default", channel_number: int = None, video_index: int = None):
|
||||
"""Start the video player with specified mode
|
||||
|
||||
Args:
|
||||
startup_mode: "default", "random", "channel", or "index"
|
||||
channel_number: Channel number to play (for channel mode)
|
||||
video_index: Video index to play (for index mode)
|
||||
"""
|
||||
self.logger.info(f"Starting video player in {startup_mode} mode...")
|
||||
self.running = True
|
||||
|
||||
# Initialize VLC
|
||||
@@ -440,20 +491,32 @@ class VideoPlayer:
|
||||
ir_thread = threading.Thread(target=self.process_ir_commands, daemon=True)
|
||||
ir_thread.start()
|
||||
|
||||
# Play default channel
|
||||
if self.default_channel in self.channels:
|
||||
self.play_channel(self.default_channel)
|
||||
else:
|
||||
# Play first available channel
|
||||
first_channel = min(self.channels.keys())
|
||||
self.play_channel(first_channel)
|
||||
# Play based on startup mode
|
||||
success = False
|
||||
if startup_mode == "random":
|
||||
success = self.play_random_video()
|
||||
elif startup_mode == "channel" and channel_number is not None:
|
||||
success = self.play_channel(channel_number)
|
||||
elif startup_mode == "index" and video_index is not None:
|
||||
success = self.play_video_by_index(video_index)
|
||||
else: # default mode
|
||||
if self.default_channel in self.channels:
|
||||
success = self.play_channel(self.default_channel)
|
||||
else:
|
||||
# Play first available channel
|
||||
first_channel = min(self.channels.keys())
|
||||
success = self.play_channel(first_channel)
|
||||
|
||||
self.logger.info("Video player started successfully")
|
||||
return True
|
||||
if success:
|
||||
self.logger.info("Video player started successfully")
|
||||
else:
|
||||
self.logger.error("Failed to start video playback")
|
||||
|
||||
return success
|
||||
|
||||
def run(self):
|
||||
def run(self, startup_mode: str = "default", channel_number: int = None, video_index: int = None):
|
||||
"""Main run loop"""
|
||||
if not self.start():
|
||||
if not self.start(startup_mode, channel_number, video_index):
|
||||
return
|
||||
|
||||
try:
|
||||
@@ -485,8 +548,97 @@ class VideoPlayer:
|
||||
GPIO.cleanup()
|
||||
self.logger.info("Cleanup complete")
|
||||
|
||||
def parse_arguments():
|
||||
"""Parse command line arguments"""
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Raspberry Pi Video Player with IR Remote Control",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
Examples:
|
||||
python3 video_player.py # Start with default channel
|
||||
python3 video_player.py --random # Start with random video
|
||||
python3 video_player.py --channel 5 # Start with channel 5
|
||||
python3 video_player.py --index 2 # Start with video at index 2 (0-based)
|
||||
python3 video_player.py --list-channels # List available channels
|
||||
python3 video_player.py --list-videos # List available videos with indices
|
||||
"""
|
||||
)
|
||||
|
||||
# Startup mode arguments (mutually exclusive)
|
||||
mode_group = parser.add_mutually_exclusive_group()
|
||||
mode_group.add_argument(
|
||||
'--random',
|
||||
action='store_true',
|
||||
help='Start with a random video'
|
||||
)
|
||||
mode_group.add_argument(
|
||||
'--channel',
|
||||
type=int,
|
||||
metavar='N',
|
||||
help='Start with specific channel number'
|
||||
)
|
||||
mode_group.add_argument(
|
||||
'--index',
|
||||
type=int,
|
||||
metavar='N',
|
||||
help='Start with video at specific index (0-based)'
|
||||
)
|
||||
|
||||
# Information arguments
|
||||
parser.add_argument(
|
||||
'--list-channels',
|
||||
action='store_true',
|
||||
help='List available channels and exit'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--list-videos',
|
||||
action='store_true',
|
||||
help='List available videos with indices and exit'
|
||||
)
|
||||
|
||||
# Configuration arguments
|
||||
parser.add_argument(
|
||||
'--config',
|
||||
type=str,
|
||||
default='config.json',
|
||||
help='Path to configuration file (default: config.json)'
|
||||
)
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
def list_channels(player):
|
||||
"""List available channels"""
|
||||
if not player.channels:
|
||||
print("No channels available")
|
||||
return
|
||||
|
||||
print("Available channels:")
|
||||
print("-" * 50)
|
||||
for channel_num in sorted(player.channels.keys()):
|
||||
channel = player.channels[channel_num]
|
||||
print(f"Channel {channel_num}: {channel['name']}")
|
||||
print(f" Path: {channel['path']}")
|
||||
print()
|
||||
|
||||
def list_videos(player):
|
||||
"""List available videos with indices"""
|
||||
video_files = player.scan_video_folder()
|
||||
|
||||
if not video_files:
|
||||
print("No video files found")
|
||||
return
|
||||
|
||||
print("Available videos (with indices):")
|
||||
print("-" * 50)
|
||||
for i, video_file in enumerate(video_files):
|
||||
print(f"Index {i}: {video_file.name}")
|
||||
print(f" Path: {video_file}")
|
||||
print()
|
||||
|
||||
def main():
|
||||
"""Main entry point"""
|
||||
args = parse_arguments()
|
||||
|
||||
# Check if running as root (needed for GPIO access)
|
||||
if os.geteuid() != 0:
|
||||
print("This script must be run as root for GPIO access")
|
||||
@@ -502,9 +654,37 @@ def main():
|
||||
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
||||
continue
|
||||
|
||||
# Create and run video player
|
||||
player = VideoPlayer()
|
||||
player.run()
|
||||
# Create video player
|
||||
player = VideoPlayer(args.config)
|
||||
|
||||
# Handle list commands
|
||||
if args.list_channels:
|
||||
# Load channels first
|
||||
if not player.load_channel_mapping():
|
||||
player.create_channels()
|
||||
list_channels(player)
|
||||
return
|
||||
|
||||
if args.list_videos:
|
||||
list_videos(player)
|
||||
return
|
||||
|
||||
# Determine startup mode and parameters
|
||||
startup_mode = "default"
|
||||
channel_number = None
|
||||
video_index = None
|
||||
|
||||
if args.random:
|
||||
startup_mode = "random"
|
||||
elif args.channel is not None:
|
||||
startup_mode = "channel"
|
||||
channel_number = args.channel
|
||||
elif args.index is not None:
|
||||
startup_mode = "index"
|
||||
video_index = args.index
|
||||
|
||||
# Run video player
|
||||
player.run(startup_mode, channel_number, video_index)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user