"""Sound and music management.""" import time import pygame from pathlib import Path from typing import Optional from multiprocessing import Queue class SoundManager: """Manages sound effects and music in a separate process.""" def __init__(self): self.sounds = {} self.music_file: Optional[str] = None self.effects_dir = Path(__file__).parent / 'effects' self.music_dir = Path(__file__).parent / 'music' def initialize(self) -> None: """Initialize pygame mixer.""" pygame.mixer.init() self._load_effects() self._load_music() def _load_effects(self) -> None: """Load all sound effects.""" effect_files = { 'eat': 'bing.mp3', 'wall': 'wall.mp3', 'self': 'cut.mp3', 'over': 'over.mp3', 'start': 'start2.mp3', } for effect_name, filename in effect_files.items(): effect_path = self.effects_dir / filename try: if effect_path.exists(): self.sounds[effect_name] = pygame.mixer.Sound(str(effect_path)) except pygame.error as e: print(f"Warning: Could not load effect {filename}: {e}") def _load_music(self) -> None: """Load background music.""" # Try different music files in order of preference music_options = ['bubbles.ogg', 'QonsVivaEveryone.mp3'] for filename in music_options: music_path = self.music_dir / filename if music_path.exists(): self.music_file = str(music_path) break def play_effect(self, effect_name: str) -> None: """Play a sound effect.""" if effect_name in self.sounds: try: self.sounds[effect_name].play() except pygame.error as e: print(f"Warning: Could not play effect {effect_name}: {e}") def start_music(self) -> None: """Start playing background music.""" if self.music_file: try: pygame.mixer.music.load(self.music_file) pygame.mixer.music.set_volume(0.5) pygame.mixer.music.play(-1) except pygame.error as e: print(f"Warning: Could not play music: {e}") def stop_music(self) -> None: """Stop playing music.""" pygame.mixer.music.stop() def pause_music(self) -> None: """Pause music.""" pygame.mixer.music.pause() def unpause_music(self) -> None: """Resume music.""" pygame.mixer.music.unpause() def process_queue(self, sound_queue: Queue) -> None: """Main loop for processing sound commands from the queue.""" self.initialize() while True: if not sound_queue.empty(): command = sound_queue.get() # Handle various commands if command in self.sounds: self.play_effect(command) elif command == 'music.start': self.start_music() elif command == 'music.stop': self.stop_music() elif command == 'music.pause': self.pause_music() elif command == 'music.unpause': self.unpause_music() elif command == 'quit': break time.sleep(0.1)