45 Commits

Author SHA1 Message Date
46c727ea75 Update frontend to modern responsive design (v2.0.0)
Modernized the web interface with a mobile-first responsive design:

- Added CSS custom properties (variables) for consistent theming
- Implemented responsive breakpoints (640px, 768px) for mobile/tablet/desktop
- Applied fluid typography using clamp() for automatic font scaling
- Enhanced animations (fade-in, slide-in, scale effects) for smooth UX
- Improved component styling with modern shadows and hover effects
- Added backdrop blur effects on modals
- Optimized touch targets (min 44px height) for mobile accessibility
- Updated button groups and layouts to stack on mobile
- Enhanced visual hierarchy with better spacing and typography
- Improved recordings grid with responsive card layout

Template version bumped from 1.9.2 to 2.0.0

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
v2.0.0
2025-10-30 10:01:28 +07:00
86b2770d3e Fix systemd service to allow sudo for shutdown/reboot commands
Disabled NoNewPrivileges security restriction to allow the service to
execute sudo commands for system shutdown and reboot. Also expanded PATH
to include /sbin and /usr/sbin directories.

Changes:
- Commented out NoNewPrivileges=true to allow sudo privilege escalation
- Added /sbin and /usr/sbin to PATH environment variable
- Keeps other security hardening (PrivateTmp, user/group isolation)

Why this is needed:
The NoNewPrivileges flag prevents any process from gaining additional
privileges, which blocks sudo even with proper sudoers configuration.
This is safe to disable for this use case because:
1. Service runs as specific user (berwn)
2. Sudoers file restricts to only /sbin/shutdown and /sbin/reboot
3. No other privilege escalation paths in the application

This fixes the issue where reboot works with 'make start' but not as
a systemd service.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
v1.9.2
2025-10-29 17:48:07 +07:00
416d437aef Fix shutdown command by using full path to /sbin/shutdown
Updated shutdown and reboot commands to use absolute paths to ensure
they work correctly with the sudoers configuration. Also updated the
sudoers file to allow shutdown with specific arguments.

Changes:
- Use /sbin/shutdown instead of just shutdown
- Use /sbin/reboot instead of just reboot
- Updated sudoers to allow both 'shutdown -h +1' and 'shutdown -h now'
- Ensures commands match sudoers whitelist exactly

The restart was working because reboot might be in PATH, but shutdown
needs the full path to match the sudoers entry.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 17:45:01 +07:00
aea52075f4 Fix JavaScript syntax errors by escaping emoji Unicode sequences
Replaced literal emoji characters in JavaScript strings with Unicode escape
sequences to prevent encoding issues that cause syntax errors. This resolves
the "Uncaught SyntaxError: Invalid or unexpected token" error at line 2572.

Changes:
- ⚠️ (U+26A0 U+FE0F) → \u26A0\uFE0F in confirm() dialogs
- 🔌 (U+1F50C) → \uD83D\uDD0C in shutdown alert
- 🔄 (U+1F504) → \uD83D\uDD04 in restart alert
- Template version updated to 1.9.2

The emojis still display correctly in the browser, but are now safely
encoded in the JavaScript source to prevent parsing errors.

Fixes: "shutdownSystem is not defined" and "restartSystem is not defined"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 17:41:41 +07:00
066abee508 Fix JavaScript syntax error with UTF-8 encoding
Fixed template generation to explicitly use UTF-8 encoding when writing
the HTML template file. This resolves JavaScript syntax errors caused by
emoji characters (⚠️, 🔌, 🔄) in the shutdown/restart confirmation dialogs.

Changes:
- Added encoding='utf-8' parameter to template file write operation
- Updated template version to 1.9.1 to force regeneration
- Ensures all special characters render correctly in browser

Fixes error: "Uncaught SyntaxError: Invalid or unexpected token"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 17:35:52 +07:00
112ab8c30a Add system shutdown/restart functionality via web interface
This commit adds the ability to safely shutdown or restart the Raspberry Pi
from the web interface, with proper sudo permissions and user confirmations.

Features:
- API endpoints for /api/system/shutdown and /api/system/restart
- System Control card in UI with shutdown and restart buttons
- JavaScript confirmation dialogs to prevent accidental shutdowns
- Shutdown has 1-minute delay, restart is immediate
- Auto-reload after restart (30 second delay)
- Sudoers file for passwordless sudo commands

Technical details:
- Uses subprocess.Popen() for non-blocking command execution
- Shutdown: 'sudo shutdown -h +1' (1 minute delay)
- Restart: 'sudo reboot' (immediate)
- Created wedding-phone-shutdown sudoers file
- Template version updated to 1.9.0

Installation required:
sudo cp wedding-phone-shutdown /etc/sudoers.d/wedding-phone-shutdown
sudo chmod 0440 /etc/sudoers.d/wedding-phone-shutdown

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 17:30:44 +07:00
63ce5b1703 Add recording sorting with multiple options
Added comprehensive sorting functionality for recordings:

Backend changes:
- Updated get_recordings() to accept sort_by and sort_order parameters
- Sort options: 'date', 'name', 'duration', 'size'
- Sort order: 'asc' (ascending) or 'desc' (descending)
- Added timestamp field to recordings for accurate date sorting
- Default sort: by date, descending (newest first)

Frontend changes (template v1.8.0):
- Added sort controls above recordings list
- Two dropdowns: sort field and sort direction
- Visual styling with emojis for each option:
  📅 Date - Sort by recording date/time
  📝 Name - Sort alphabetically by filename
  ⏱️ Duration - Sort by recording length
  💾 Size - Sort by file size
  ⬇️ Descending / ⬆️ Ascending
- updateSort() JavaScript function reloads page with params
- Preserves selected sort options via query params

URL parameters:
- ?sort=date&order=desc (default)
- ?sort=name&order=asc (alphabetical A-Z)
- ?sort=duration&order=desc (longest first)
- ?sort=size&order=asc (smallest first)

This makes it easy to find specific recordings or organize
them by different criteria depending on what you need.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 16:20:13 +07:00
13e1c6dd5c Fix systemd service to use uv with full path
Updated service to use uv run with absolute path to avoid
PATH issues in systemd environment.

Service file changes:
- ExecStart: Uses absolute path to uv (/home/berwn/.local/bin/uv)
- Runs: uv run --no-project python rotary_phone_web.py
- This ensures uv manages dependencies correctly

Install script improvements:
- Auto-detects uv location with 'which uv'
- Falls back to $HOME/.local/bin/uv if not in PATH
- Validates uv exists before proceeding
- Substitutes actual uv path into service file
- Shows detected uv path in output

This fixes:
  ModuleNotFoundError: No module named 'waitress'

Now uv properly manages the virtual environment and
dependencies are available to the service.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 16:16:08 +07:00
6198bff860 Fix systemd service to use python3 directly instead of uv
Changed service to run python3 directly instead of 'make start'
to avoid dependency on uv being installed system-wide.

Service file changes:
- ExecStart: /usr/bin/python3 rotary_phone_web.py (instead of make)
- User/Group: berwn (match actual user, not hardcoded pi)
- WorkingDirectory: /home/berwn/wedding-phone
- PATH includes user's .local/bin for any user-installed packages

Install script improvements:
- Automatically substitutes correct username
- Substitutes correct home directory in PATH
- Substitutes correct working directory
- More robust sed replacements with proper escaping

This fixes the error:
  make: uv: No such file or directory
  make: *** [Makefile:8: start] Error 127

Now the service works regardless of whether uv is installed,
as it uses system python3 which is always available.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 16:11:27 +07:00
1b1a40b094 Add auto-update for missing configuration settings
Implemented automatic config file updates to add missing settings
with default values on startup. This eliminates manual config
editing when upgrading to newer versions.

Features:
- Auto-updates config.json with missing settings
- Auto-updates user_config.json with missing user preferences
- Console logging shows which settings were added
- Preserves existing values - only adds missing keys
- Writes updated config back to file automatically
- Graceful error handling if write fails

System config (config.json):
- Comprehensive defaults for all sections
- GPIO, audio, paths, backup, web, system settings
- New settings like volume_greeting, volume_button, volume_beep

User config (user_config.json):
- Loop-based checking against default_config
- Automatic save when updates are detected
- Error logging for troubleshooting

Benefits:
- Seamless upgrades without manual config edits
- No breaking changes when new features are added
- Users see exactly what was added in console
- Backward compatible with old config files

Example console output:
  [CONFIG] Added missing setting: system.volume_beep = 70
  [CONFIG] Updated config.json with missing defaults
  [USER_CONFIG] Added missing setting: volume_button = 70
  [USER_CONFIG] Updated user_config.json with missing defaults

Updated README.md to document auto-update feature.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 16:02:50 +07:00
b219619f24 Add separate volume controls for greeting, button, and beep sounds
Added individual volume control for each sound type:
- Greeting volume (for welcome messages)
- Button sound volume (for extra button during recording)
- Beep volume (for recording start indicator)

Backend changes:
- Added volume_greeting, volume_button, volume_beep to config
- New getter/setter methods for each volume type
- API endpoints: /api/volume/greeting, /api/volume/button, /api/volume/beep
- Updated play_sound_file() with volume_override parameter
- Greeting, button, and beep playback now use their specific volumes

Frontend changes (template v1.7.0):
- Replaced single volume slider with three separate sliders
- Clean UI with labeled controls for each sound type
- Helper function setupVolumeSlider() for DRY code
- Real-time updates with debouncing (300ms)
- Visual feedback with gradient background

Config changes:
- Added volume_greeting: 70 (default)
- Added volume_button: 70 (default)
- Added volume_beep: 70 (default)
- Backward compatible with existing configs

This allows independent control of each sound's loudness,
useful when greeting needs to be louder than beep, etc.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 15:56:12 +07:00
e2218a0c9a Add comprehensive logging for extra button debugging
Added detailed console logging throughout button functionality:

Startup logging:
- Shows if button is enabled/disabled
- Displays GPIO pin number and pressed state
- Shows configured button sound file path

Button press detection:
- Logs when button is pressed in main loop
- Logs when button is pressed during recording
- Shows recording/playing state

Button sound playback:
- File path and existence check
- Audio file properties (rate, channels, width)
- Sample rate mismatch warnings
- Playback progress (chunk count)
- Volume level
- Detailed error messages with traceback

Recording loop enhancement:
- Added button checking INSIDE recording loop
- Previously button only checked in main loop
- Button now works during active recording

All logs prefixed with [BUTTON] for easy filtering.

This helps diagnose why button sound isn't playing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 15:50:21 +07:00
2ddba3f3e1 Replace multiple USB scripts with single interactive version
Consolidated all USB setup functionality into one script:
- setup_usb.sh (formerly setup_usb_interactive.sh)

Removed deprecated scripts:
- setup_usb_automount.sh
- setup_usb_final.sh
- old setup_usb.sh

New setup_usb.sh features:
- Interactive menu-driven interface
- Scans for all connected USB drives automatically
- Displays device info (label, size, UUID, filesystem)
- Let user select which drives to auto-mount
- Custom mount point names (usb0, usb1, backup, etc.)
- Creates systemd .mount and .automount units
- Handles cleanup and conflict resolution
- Proper permissions (uid/gid)
- Works with drives plugged in after boot

Updated README.md documentation to reflect new workflow.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 15:33:10 +07:00
7d5610d21d Fix UUID extraction to handle commented fstab lines
Modified grep logic to extract UUIDs even if the fstab
lines are already commented out from a previous run.

Uses sed to strip comment prefixes before extracting UUIDs.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 15:19:07 +07:00
4e46989ff6 Add complete USB auto-mount setup with cleanup
Created setup_usb_final.sh that handles all cleanup and setup
in one automated script to solve mount point conflicts.

Features:
- Stops and disables existing systemd mount units
- Unmounts any active USB mounts
- Extracts UUIDs from existing fstab entries
- Comments out fstab entries to prevent conflicts
- Creates timestamped fstab backup
- Creates systemd .mount and .automount units
- Enables and starts auto-mount
- Proper error handling and user feedback

This solves the "Path is already a mount point" error
that occurs when trying to set up systemd automount
while drives are already mounted via fstab.

Usage:
  sudo ./setup_usb_final.sh

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 15:15:37 +07:00
81a3318a5f Add systemd-based USB auto-mount setup script
Created setup_usb_automount.sh to solve fstab auto-mount issues
with modern systemd-based Raspberry Pi OS.

Features:
- Creates systemd .mount and .automount units
- Extracts UUIDs from existing /etc/fstab automatically
- Allows manual UUID entry if not found
- Auto-mounts when USB drives are accessed (on-demand)
- Works even if USB drives are plugged in after boot
- Proper user permissions (uid/gid)
- Easy enable/disable via systemctl

This solves the issue where fstab entries don't auto-mount
because USB drives aren't present at boot time or systemd
has different mounting priorities.

Usage:
  sudo ./setup_usb_automount.sh

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 15:11:17 +07:00
ad34461d27 Improve setup_usb.sh with automatic fstab updates
- Added automatic /etc/fstab modification option
  - Creates timestamped backup before modifying
  - Checks if UUID entries already exist
  - Appends new entries only if not present
  - Provides clear feedback for each step

- Enhanced user prompts with better guidance
- Added test instructions after fstab update

Previously the script only displayed the fstab entries
for manual addition. Now it can automatically add them
with a single confirmation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 13:23:25 +07:00
7cce795a43 Add rename functionality for recordings
- Added /rename/<filename> API endpoint
  - Accepts new_name in JSON body
  - Automatically appends .wav extension if missing
  - Uses secure_filename() for safety
  - Checks for existing files to prevent overwrites
  - Backs up renamed file to USB if backup enabled

- Updated web interface (template v1.6.0)
  - Added "Rename" button to each recording
  - Added renameRecording() JavaScript function
  - Uses prompt dialog for name input
  - Pre-fills current name (without .wav extension)
  - Reloads page after successful rename

This allows users to assign guest names to recordings
for easier organization (e.g., "John_Smith.wav").

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 13:14:58 +07:00
73ca1e6935 Fix file path bug in resample_audio.py
Changed from os.rename() to shutil.copy2() when creating backups.
This prevents the "No such file or directory" error that occurred
when trying to write the resampled file after the original was renamed.

Now the script:
- Copies original to .backup (instead of renaming)
- Reads from .backup file
- Writes resampled audio to original filename

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 13:09:09 +07:00
30ac7e89e9 Add audio resampling utility and scipy dependency
- Created resample_audio.py utility script
  - Automatically reads target sample rate from config.json
  - Resamples all WAV files in sounds directory
  - Creates .backup files before modifying originals
  - Handles both mono and stereo audio
  - Uses scipy.signal.resample for high-quality resampling

- Added scipy>=1.7.0 dependency to pyproject.toml
- Updated Makefile sync command to include scipy
- Updated README.md with sample rate troubleshooting section
- Updated config example in README to show 48kHz default
- Added beep_sound configuration to README system section

This resolves sample rate mismatch errors when audio files
don't match the configured rate in config.json.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 13:02:39 +07:00
52b8348a03 Change default sample rate to 48kHz and add validation
Changes:
- Update default sample rate from 44.1kHz to 48kHz (more professional standard)
- Add sample rate validation in play_sound_file()
- Display clear warning when uploaded file doesn't match configured rate
- Update default sound generation (dial tone & beep) to use configured RATE
- Prevent playback of incompatible sample rates (avoids ALSA errors)

Error Handling:
- Check file sample rate before attempting playback
- Print warning with actual vs expected sample rate
- Return False and skip playback if mismatch detected
- User-friendly error message with resampling instructions

This fixes the "Invalid sample rate" error when playing files with
non-matching sample rates. Users must now resample their audio files
to match the configured rate (default 48kHz).

To resample audio files:
ffmpeg -i input.wav -ar 48000 output.wav

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 12:55:13 +07:00
fbe9bb2f9a Redesign UI with dropdown sound selection
Major UI Overhaul:
- Replace individual buttons with dropdown selectors
- New "Sound Assignment" card with 3 dropdowns:
  * Greeting Sound (plays on pickup)
  * Button Sound (plays when button pressed)
  * Recording Beep (plays before recording)
- Rename "Greeting Messages" to "Available Sounds"
- Show sound usage badges (🔘📣) in sound list
- Cleaner, more intuitive interface

Benefits:
- Easier to see which sound is assigned where
- One click to change assignments
- Less clutter with fewer buttons
- Shows duration in dropdown options
- Better visual hierarchy

Template v1.5.0 - will auto-regenerate on restart

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 12:50:18 +07:00
4f6398858e Add customizable recording beep sound feature
Backend:
- Add beep_sound and beep_enabled configuration options
- Generate default 1000Hz beep (0.5s) on first run
- Add get/set methods for beep sound and enabled state
- Play beep after greeting, before recording starts
- Add /set_beep_sound and /api/beep_enabled endpoints

Frontend:
- Add "Recording Beep" toggle checkbox in settings
- Add "📣 Set Beep" button for each greeting sound
- Show beep status indicator on sounds
- Real-time enable/disable with visual feedback
- Template v1.4.0

Configuration:
- beep_sound: WAV filename for beep (default: "beep.wav")
- beep_enabled: true/false to enable/disable beep

This gives guests a clear audio cue that recording has started.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 12:43:30 +07:00
b0f1514457 Fix f-string syntax error in template generation
- Split template writing into two parts to avoid f-string parsing issues
- Write version comment separately using f-string
- Write rest of template using regular string (avoids escaping CSS/JS braces)
- Fixes SyntaxError: f-string: expecting '=', or '!', or ':', or '}'

The issue occurred because CSS contains { } braces and % characters that
f-strings try to interpret. Now only the version comment uses f-string.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 12:32:20 +07:00
4282b0f7ee Add automatic template versioning system
- Add TEMPLATE_VERSION constant (1.3.0) to track UI changes
- Create check_template_version() to compare embedded vs current version
- Embed version marker as HTML comment in generated template
- Auto-regenerate template when version mismatch detected
- Show clear status messages: "Template up-to-date" or "regenerating"
- Document versioning system in CLAUDE.md with usage guidelines

Benefits:
- No manual template deletion required when code updates
- Users automatically get latest UI features on restart
- Clear version tracking for template changes
- Prevents stale template issues

To update template: increment TEMPLATE_VERSION when HTML/CSS/JS changes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 12:28:34 +07:00
c68c8d2885 Add download all recordings as ZIP feature
- Add /download_all endpoint to create in-memory ZIP archive
- Include zipfile and io imports for ZIP creation
- Add "Download All as ZIP" button in web interface (only shows when recordings exist)
- ZIP filename includes timestamp: wedding_recordings_YYYYMMDD_HHMMSS.zip
- Only includes .wav files from recordings directory
- Update API documentation in README.md
- Document feature in CLAUDE.md

Allows users to quickly backup all guest recordings in a single download.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 12:24:17 +07:00
72e39f9515 Add production WSGI server and CLAUDE.md documentation
- Replace Flask development server with Waitress production WSGI server
- Add waitress>=2.1.0 dependency to pyproject.toml and Makefile
- Configure 4-thread server for better performance and stability
- Create comprehensive CLAUDE.md guide for future development
- Document architecture, deployment, testing, and common patterns
- Update README.md with production-ready feature and dependencies

Eliminates Flask development server warning and provides production-grade
web serving suitable for Raspberry Pi deployment.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 12:18:19 +07:00
6ff7664f31 Comprehensive documentation update - v1.2.0
**CHANGELOG.md Created:**
- Complete version history from 1.0.0 to 1.2.0
- Detailed changelog with all features, changes, fixes
- API endpoints documentation
- Configuration changes documentation
- Upgrade notes from 1.0.0 to 1.2.0
- Known issues and future enhancements

**README.md Enhanced:**
- Added Quick Start section at top
- Added comprehensive Table of Contents
- Updated Python version requirement (3.7 -> 3.8)
- Added UV and Make to software requirements
- Added new API endpoints (backup, delay)
- Expanded Contributing section with guidelines
- Added Version History section (current: v1.2.0)
- Enhanced License section with clear permissions
- Added Credits and Technologies Used sections
- Added Support & Community section
- Added proper closing with emoji
- Updated file structure with CHANGELOG.md
- Better file descriptions in structure

**Documentation Improvements:**
- Clear upgrade path from 1.0.0 to 1.2.0
- All new features documented
- All configuration changes documented
- Better organization with TOC
- More professional presentation
- Complete feature list
- Development guidelines for contributors

**Version Information:**
- Current version: 1.2.0
- Major features: USB backup, systemd service, UV support
- Breaking changes: Python 3.8+ required
- New scripts: setup_usb.sh, install_service.sh
- New commands: make start, make test, make sync

**Key Highlights:**
-  Professional documentation structure
-  Easy to navigate with TOC
-  Quick Start for new users
-  Complete changelog for upgrading
-  Clear contribution guidelines
-  Proper version tracking

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 17:19:31 +07:00
42041006b7 Fix USB backup permission issues
**Problem:**
- USB drives mounted as root were not writable by regular user
- Caused "Permission denied" errors on backup
- Required running application as root (not secure)

**Solution:**
- Better permission error messages with fix suggestions
- Try to create backup directory first (more flexible)
- Show helpful error: "run sudo chown -R \$USER /media/usb0"

**USB Setup Script (setup_usb.sh):**
- Interactive USB drive mounting
- Automatically detects USB devices
- Mounts with user ownership (uid/gid)
- Tests write permissions
- Shows free space
- Offers to add to /etc/fstab
- Color-coded output

**Documentation Updates:**
- Added 3 methods for mounting with permissions
- Recommended method: mount with uid/gid options
- Added fstab auto-mount example
- Added quick setup script example
- Clear instructions for each method

**Usage:**
```bash
# Easiest method
sudo ./setup_usb.sh

# Or manual mounting
sudo mount -o uid=$(id -u),gid=$(id -g) /dev/sda1 /media/usb0

# Or fix existing mount
sudo chown -R $USER /media/usb0
```

**Security:**
- No need to run wedding phone as root
- User-owned USB mount points
- Proper permission checking
- Clear error messages

**Web Interface:**
- Shows helpful permission error messages
- Includes fix command in error text
- Better UX for permission issues

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 17:04:21 +07:00
d0bbaf6d4e Fix UV build issues by removing build system
**Issues Fixed:**
- Removed hatchling build-backend (not needed for scripts)
- Changed to --no-project mode (no editable install)
- UV now runs scripts directly without building

**Makefile Updated:**
- Uses 'uv run --no-project' to skip build
- Added 'make sync' to install dependencies
- Simplified dependency installation
- No more build errors

**Install Script Updated:**
- Uses 'make sync' instead of 'uv pip install -e .'
- Faster installation, no build step

**Usage:**
```bash
# Install dependencies
make sync

# Run the system (no build needed)
make start

# Everything just works!
```

**Why This Works:**
- No build system = no build errors
- Direct script execution via UV
- Dependencies installed separately
- Simpler, more reliable

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 16:59:03 +07:00
bdeeb879cd Fix UV configuration and add Makefile
**Issues Fixed:**
- Removed [tool.uv.scripts] (not supported by UV)
- Updated requires-python from >=3.7 to >=3.8 (Flask requirement)
- Removed tool.uv.dev-dependencies (deprecated)

**Makefile Added:**
- make start - Run the wedding phone system
- make test - Run audio tests
- make install - Install dependencies
- make clean - Clean temporary files
- make help - Show available commands

**Service Updated:**
- Changed ExecStart from 'uv run start' to 'make start'
- Uses Makefile for proper UV execution

**Documentation Updated:**
- Primary method now uses Make commands
- Added UV direct commands as alternative
- Updated file structure to include Makefile

**Usage:**
```bash
# Recommended
make start

# Alternative
uv run python rotary_phone_web.py

# Service uses make internally
sudo systemctl start wedding-phone
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 16:54:37 +07:00
81731ce4a4 Add UV run support and systemd service installer
**UV Integration:**
- Updated pyproject.toml with [tool.uv.scripts]
- Added 'uv run start' to launch wedding phone
- Added 'uv run test' to run audio tests
- Refactored main code into main() function
- Added proper entry point for package installation

**Systemd Service:**
- Created wedding-phone.service template
- Service runs with UV for dependency management
- Automatic restart on failure
- Proper security hardening (NoNewPrivileges, PrivateTmp)
- GPIO and audio group access configured

**Service Installer:**
- Created install_service.sh automated installer
- Auto-detects project path and user
- Checks for UV installation and dependencies
- Configures service file with correct paths
- Option to enable and start immediately
- Provides helpful command reference

**Installer Features:**
- Validates config.json exists (creates from example if missing)
- Installs UV dependencies automatically
- Updates service file paths dynamically
- Color-coded output for clarity
- Error checking at each step
- Clean installation process

**Usage:**
```bash
# Run directly with UV
uv run start

# Install as system service
./install_service.sh

# Service management
sudo systemctl start wedding-phone
sudo systemctl stop wedding-phone
sudo journalctl -u wedding-phone -f
```

**Documentation:**
- Updated README with UV commands
- Added service installation guide
- Removed old manual systemd instructions
- Added service management commands
- Updated file structure documentation

**Benefits:**
- Easier to run (single command)
- Automatic startup on boot
- Better dependency management
- Professional service integration
- Simplified installation process

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 16:52:08 +07:00
d07cb82772 Add USB backup system with CRC32 verification
**USB Backup Features:**
- Automatic backup to multiple USB drives
- CRC32 checksum verification for data integrity
- Configurable backup paths in config.json
- Backup on write (recordings and greeting uploads)
- Corrupted backups automatically deleted
- Web interface for monitoring and testing

**Configuration:**
- Added backup section to config.example.json
- enabled: Enable/disable USB backup
- usb_paths: Array of USB mount points
- verify_crc: Enable CRC32 verification
- backup_on_write: Backup immediately after file write

**CRC32 Implementation:**
- calculate_crc32(): Compute file checksum
- 64KB chunk reading for memory efficiency
- Source and destination file verification
- Automatic cleanup of failed copies

**Backup Functions:**
- backup_file_to_usb(): Backup with verification
- get_usb_backup_status(): Check drive status
- Mount detection, write test, free space check
- Preserves directory structure on USB

**Web Interface:**
- USB Backup card with drive status display
- Green/Yellow/Red status indicators
- Free space monitoring
- Test backup button
- Real-time status refresh
- Detailed error reporting

**Integration:**
- Recordings backed up after save
- Greetings backed up after upload
- Backup results logged to console
- Non-blocking backup execution

**API Endpoints:**
- GET /api/backup/status - Drive status
- POST /api/backup/test - Test backup

**Documentation:**
- Complete USB backup guide in README
- Mount instructions for USB drives
- CRC verification explanation
- Backup directory structure
- Web interface usage guide

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 16:28:32 +07:00
7e26373fe9 Add immediate stop on hook and abort incomplete recordings
**Immediate Hook Detection:**
- Playback now checks GPIO pin directly instead of status variable
- Recording checks GPIO pin in every loop iteration
- Both stop immediately when handset is placed back on hook
- No delays or waiting for status updates

**Abort Incomplete Recordings:**
- Added minimum recording duration (1 second)
- Recordings shorter than 1 second are automatically deleted
- Aborted recordings (hook hung up during recording) are not saved
- Failed recordings are cleaned up automatically
- Prevents saving empty or accidental recordings

**Behavior:**
- Pick up handset → Greeting plays
- Hang up during greeting → Greeting stops immediately, no recording
- Hang up during recording < 1s → Recording aborted, file deleted
- Hang up during recording > 1s → Recording saved normally
- Clean state after each hang up, ready for next call

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 15:53:56 +07:00
9ea6a5e3a6 Fix extra button sound playback and add status indicator
**Button Sound Playback Fix:**
- Use separate PyAudio instance for button sound during recording
- Allows simultaneous audio input (recording) and output (button sound)
- Button sound plays through speaker/handset for guest to hear
- Button sound is NOT captured in the recording file
- Only works during recording phase (not during greeting)

**Button Status Indicator:**
- Added button status display in Phone Status card
- Shows "Button ready" or "Button sound playing..."
- Yellow highlight when button sound is playing
- Status updates dynamically via refresh
- Only visible when extra button is enabled

**Technical Details:**
- Separate audio_playback instance prevents stream conflicts
- Recording uses input stream, button uses output stream
- Both operate on same HiFiBerry device simultaneously
- Status API now includes extra_button_playing flag

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 15:45:30 +07:00
4d608555cc Change extra button to only work during recording phase
- Extra button now only responds during actual recording
- Does not work during greeting playback or when on-hook
- Updated logic from checking off-hook status to checking recording status
- Updated README to reflect recording-only behavior

This allows guests to add sound effects to their recorded message
without interrupting the initial greeting.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 15:41:25 +07:00
3b08c5f88b Fix greeting delay slider not appearing in web interface
- Delete old templates directory to force regeneration
- Templates are auto-generated on first run only
- Add note to README about regenerating templates
- Solution: Delete templates/ and restart script to get new features

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 15:39:17 +07:00
2717edd71e Add web interface control for greeting delay
- Move greeting_delay from system config to user runtime config
- Add GET/POST API endpoints at /api/greeting_delay
- Add delay slider to web interface (0-10 seconds range)
- Implement debounced slider updates (300ms delay)
- Update visual gradient on slider movement
- Display current delay value in seconds
- Allow greeting delay adjustment without editing config files

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 15:34:58 +07:00
38eff5c2c8 Fix extra button to only work when OFF-hook and add greeting delay
Breaking Behavior Change:
- Extra button NOW only works when handset is OFF-hook (during call)
- Previous: worked when on-hook (idle) - REVERSED
- Reason: Button is for guests to trigger during their call/recording

New Feature - Greeting Delay:
- Add greeting_delay_seconds to config.json (0-10 seconds)
- Delays greeting playback after handset pickup
- Gives guests time to position phone comfortably
- Default: 0 (plays immediately, backward compatible)

Extra Button Logic:
- Only responds when phone_status == "off_hook"
- Ignored when phone is on-hook (idle)
- Can be pressed during greeting or recording
- Plays entire sound without interruption
- Useful for: "Press button to hear special message"

Greeting Delay Use Cases:
- Wedding: Give guests moment to settle in
- Events: Time to position phone comfortably
- Accessibility: Extra time for elderly guests
- Professional: Pause before message delivery

Configuration:
{
  "system": {
    "greeting_delay_seconds": 2,  // 2 second pause
    "extra_button_sound": "surprise.wav"
  }
}

Console Output:
- "Extra button ignored - phone is on hook" (when idle)
- "Waiting X seconds before greeting..." (delay active)
- "=== Extra button pressed ===" (during call)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 15:15:05 +07:00
4205b5d09d Fix extra button sound playback and add on-hook restriction
Bug Fixes:
- Extra button now plays sound completely (was stopping immediately)
- Added check_hook_status parameter to play_sound_file()
- Button sounds play with check_hook_status=False (always complete)
- Greeting sounds play with check_hook_status=True (stop if hung up)

Behavior Changes:
- Extra button ONLY works when phone is on-hook (not in use)
- Prevents button from interfering with active calls
- Clear console message when button pressed during call
- Sound plays completely without hook status interruption

Technical Details:
- Modified play_sound_file() to accept check_hook_status parameter
- Changed while loop condition from "and" to conditional break
- Added on-hook check in play_extra_button_sound()
- Greeting playback still stops if handset hung up mid-message

This ensures:
✓ Button sounds always play completely
✓ Button only works when phone not in use
✓ Greeting playback can still be interrupted by hanging up
✓ No audio conflicts between button and phone calls

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 15:11:15 +07:00
2dde7d8e43 Add extra GPIO button support with custom sound playback
Features:
- Configurable extra button on any GPIO pin
- Upload and select custom sound for button press
- Non-blocking button operation (separate thread)
- Debounced to prevent double-triggers (0.5s)
- Works independently from phone handset
- Can be pressed anytime, even during recording

Configuration:
- gpio.extra_button_enabled: Enable/disable feature
- gpio.extra_button_pin: GPIO pin number (default: 27)
- gpio.extra_button_pressed_state: "LOW" or "HIGH"
- system.extra_button_sound: Default sound file

Web Interface:
- Display active button sound in alert
- "🔘 Set Button" action on greeting items
- Visual indicator (🔘) for active button sound
- Upload any WAV file and assign to button
- Play/preview button sounds in browser

Backend:
- RotaryPhone.play_extra_button_sound() method
- RotaryPhone.set_extra_button_sound() method
- Thread-based playback to not block main loop
- /set_extra_button_sound API endpoint
- Extra button sound tracked in user_config.json

Documentation:
- Extra button setup in README
- Configuration examples
- GPIO pin configuration
- Operation workflow

Use Cases:
- Play special message on button press
- Sound effects for wedding games
- Multiple interaction points
- Custom audio triggers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 14:57:31 +07:00
ef0373e60b Add external configuration file system
Breaking Changes:
- Configuration now via config.json instead of editing Python code
- Remove all hardcoded paths (no more /home/berwn)
- Separate system config (config.json) from runtime config (user_config.json)

Features:
- config.example.json with all configurable options
- GPIO pin and state configuration
- Audio device index configuration
- Customizable paths (relative or absolute)
- Web port and upload size settings
- No code editing required for deployment

Configuration Structure:
- gpio: hook_pin, hook_pressed_state
- audio: device_index, chunk_size, channels, sample_rate, max_record_seconds
- paths: base_dir, recordings_dir, sounds_dir
- web: port, max_upload_size_mb
- system: active_greeting, default_volume

Script automatically:
- Checks for config.json on startup
- Provides helpful error if missing
- Uses relative paths by default
- Loads test_complete.py config from same file

Updated Documentation:
- Complete configuration guide in README
- Setup instructions without hardcoded paths
- Troubleshooting for config errors
- Device index discovery command

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 14:48:43 +07:00
1657a242fd Add UV package management and volume control feature
Features:
- Add pyproject.toml for UV package management
- Volume control with real-time slider (0-100%)
- Backend volume adjustment with numpy audio scaling
- Volume setting persists in config.json
- Debounced API calls for smooth slider interaction
- Enhanced audio playback with volume multiplier
- Update README with UV installation instructions
- Add volume control documentation

API Changes:
- GET /api/volume - Get current volume setting
- POST /api/volume - Set volume level

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 14:43:57 +07:00
753b1bddfa Add .gitignore and comprehensive README
Changes:
- Add .gitignore to exclude __pycache__, .claude/, and data directories
- Remove cached files and Claude config from repository
- Create detailed README.md with:
  - Project overview and features
  - Installation and setup instructions
  - Usage guide for web interface and phone operation
  - Hardware and software requirements
  - Troubleshooting section
  - API documentation
  - Auto-start configuration

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 14:39:56 +07:00
80c45389b2 Add rotary phone web interface with multiple greeting support
Features:
- Web interface for managing rotary phone system
- Support for multiple greeting messages with selector
- Direct audio playback in browser for recordings and greetings
- Upload multiple WAV files at once
- Set active greeting that plays when phone is picked up
- HiFiBerry DAC+ADC Pro audio configuration
- GPIO-based handset detection and audio recording
- Real-time status monitoring with auto-refresh

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 14:37:20 +07:00