diff --git a/sounds/default/autocomplete.ogg b/sounds/default/autocomplete.ogg new file mode 100644 index 0000000..de2e207 Binary files /dev/null and b/sounds/default/autocomplete.ogg differ diff --git a/sounds/default/autocomplete_end.ogg b/sounds/default/autocomplete_end.ogg new file mode 100644 index 0000000..4a96edd Binary files /dev/null and b/sounds/default/autocomplete_end.ogg differ diff --git a/sounds/default/boost.ogg b/sounds/default/boost.ogg new file mode 100644 index 0000000..45c00af Binary files /dev/null and b/sounds/default/boost.ogg differ diff --git a/sounds/default/error.ogg b/sounds/default/error.ogg new file mode 100644 index 0000000..9a1da99 Binary files /dev/null and b/sounds/default/error.ogg differ diff --git a/sounds/default/mention.ogg b/sounds/default/mention.ogg new file mode 100644 index 0000000..4cc55dc Binary files /dev/null and b/sounds/default/mention.ogg differ diff --git a/sounds/default/notification.ogg b/sounds/default/notification.ogg new file mode 100644 index 0000000..5ff96e8 Binary files /dev/null and b/sounds/default/notification.ogg differ diff --git a/sounds/default/pack.json b/sounds/default/pack.json new file mode 100644 index 0000000..d1cd39e --- /dev/null +++ b/sounds/default/pack.json @@ -0,0 +1,21 @@ +{ + "name": "Default", + "description": "Clean, accessible default sounds for Bifrost", + "author": "Bifrost Development Team", + "version": "1.0", + "sounds": { + "private_message": "private_message.ogg", + "mention": "mention.ogg", + "boost": "boost.ogg", + "reply": "reply.ogg", + "post_sent": "post_sent.ogg", + "timeline_update": "timeline_update.ogg", + "notification": "notification.ogg", + "autocomplete": "autocomplete.ogg", + "autocomplete_end": "autocomplete_end.ogg", + "startup": "startup.ogg", + "shutdown": "shutdown.ogg", + "success": "success.ogg", + "error": "error.ogg" + } +} \ No newline at end of file diff --git a/sounds/default/post_sent.ogg b/sounds/default/post_sent.ogg new file mode 100644 index 0000000..f7aaab5 Binary files /dev/null and b/sounds/default/post_sent.ogg differ diff --git a/sounds/default/private_message.ogg b/sounds/default/private_message.ogg new file mode 100644 index 0000000..d0d2f50 Binary files /dev/null and b/sounds/default/private_message.ogg differ diff --git a/sounds/default/reply.ogg b/sounds/default/reply.ogg new file mode 100644 index 0000000..60d7de0 Binary files /dev/null and b/sounds/default/reply.ogg differ diff --git a/sounds/default/shutdown.ogg b/sounds/default/shutdown.ogg new file mode 100644 index 0000000..0c1ee9b Binary files /dev/null and b/sounds/default/shutdown.ogg differ diff --git a/sounds/default/startup.ogg b/sounds/default/startup.ogg new file mode 100644 index 0000000..6047c79 Binary files /dev/null and b/sounds/default/startup.ogg differ diff --git a/sounds/default/success.ogg b/sounds/default/success.ogg new file mode 100644 index 0000000..9b9e725 Binary files /dev/null and b/sounds/default/success.ogg differ diff --git a/sounds/default/timeline_update.ogg b/sounds/default/timeline_update.ogg new file mode 100644 index 0000000..02f2146 Binary files /dev/null and b/sounds/default/timeline_update.ogg differ diff --git a/src/audio/sound_manager.py b/src/audio/sound_manager.py index 62fee62..8e54c12 100644 --- a/src/audio/sound_manager.py +++ b/src/audio/sound_manager.py @@ -8,6 +8,7 @@ import json import wave import numpy as np import logging +import shutil from pathlib import Path from typing import Dict, List, Optional from threading import Thread @@ -138,43 +139,73 @@ class SoundManager: self.sound_packs[pack_dir.name] = pack def create_default_pack(self): - """Create default sound pack if it doesn't exist""" + """Create default sound pack if it doesn't exist by copying from bundled pack""" default_dir = self.settings.get_sounds_dir() / "default" default_dir.mkdir(parents=True, exist_ok=True) pack_file = default_dir / "pack.json" if not pack_file.exists(): + # Try to copy from bundled default pack + bundled_pack_dir = self._find_bundled_default_pack() + if bundled_pack_dir and bundled_pack_dir.exists(): + self.logger.info(f"Copying bundled default sound pack from {bundled_pack_dir}") + try: + # Copy all files from bundled pack + for file_path in bundled_pack_dir.iterdir(): + if file_path.is_file(): + shutil.copy2(file_path, default_dir / file_path.name) + self.logger.info("Successfully copied bundled default sound pack") + return + except Exception as e: + self.logger.warning(f"Failed to copy bundled pack: {e}, creating minimal fallback") + + # Fallback: create minimal pack.json (no actual sound files) + self.logger.info("Creating minimal fallback default pack") pack_data = { "name": "Default", "description": "Default system sounds", "author": "Bifrost", "version": "1.0", "sounds": { - "private_message": "private_message.wav", - "direct_message": "direct_message.wav", - "mention": "mention.wav", - "boost": "boost.wav", - "reply": "reply.wav", - "favorite": "favorite.wav", - "follow": "follow.wav", - "unfollow": "unfollow.wav", - "post_sent": "post_sent.wav", - "post": "post.wav", - "timeline_update": "timeline_update.wav", - "notification": "notification.wav", - "startup": "startup.wav", - "shutdown": "shutdown.wav", - "success": "success.wav", - "error": "error.wav", - "expand": "expand.wav", - "collapse": "collapse.wav", - "autocomplete": "autocomplete.wav", - "autocomplete_end": "autocomplete_end.wav" + "private_message": "private_message.ogg", + "mention": "mention.ogg", + "boost": "boost.ogg", + "reply": "reply.ogg", + "post_sent": "post_sent.ogg", + "timeline_update": "timeline_update.ogg", + "notification": "notification.ogg", + "startup": "startup.ogg", + "shutdown": "shutdown.ogg", + "success": "success.ogg", + "error": "error.ogg", + "autocomplete": "autocomplete.ogg", + "autocomplete_end": "autocomplete_end.ogg" } } with open(pack_file, 'w') as f: json.dump(pack_data, f, indent=2) + + def _find_bundled_default_pack(self) -> Optional[Path]: + """Find the bundled default sound pack directory""" + # Look for bundled sounds relative to this file + current_file = Path(__file__) + + # Try different potential locations relative to the source + potential_paths = [ + # From src/audio/sound_manager.py to sounds/default/ + current_file.parent.parent.parent / "sounds" / "default", + # From installed location + current_file.parent.parent / "sounds" / "default", + # Current working directory + Path.cwd() / "sounds" / "default" + ] + + for path in potential_paths: + if path.exists() and (path / "pack.json").exists(): + return path + + return None def load_current_pack(self): """Load the currently selected sound pack"""