Initial commit: Add playlist downloader project with UI and core functionality
This commit is contained in:
@@ -0,0 +1,392 @@
|
||||
# Implementation Plan: Volume Normalization Modal
|
||||
|
||||
## Overview
|
||||
|
||||
This implementation plan breaks down the Volume Normalization Modal feature into discrete, actionable coding tasks organized by phase. Each task builds incrementally on previous work, with property-based tests validating correctness properties throughout. The implementation follows the existing codebase patterns (PyQt6 modals, Config module structure) and maintains backward compatibility with the current normalization behavior.
|
||||
|
||||
---
|
||||
|
||||
## Tasks
|
||||
|
||||
### Phase 1: Core Infrastructure - NormalizationSettings Class
|
||||
|
||||
- [x] 1.1 Create NormalizationSettings class in Config module
|
||||
- Add `NormalizationSettings` class to `src/core/config.py`
|
||||
- Define `PRESETS` dictionary with four presets: Quiet, Normal, Loud, Very Loud
|
||||
- Define `PARAM_RANGES` dictionary with validation ranges for I, TP, LRA parameters
|
||||
- Implement `get_preset_params(preset_name: str) -> dict` method
|
||||
- Implement `validate_parameters(params: dict) -> tuple[bool, str]` method
|
||||
- _Requirements: 2.2, 10.1, 10.2, 10.3, 10.4_
|
||||
|
||||
- [ ]* 1.2 Write property test for preset definitions
|
||||
- **Property 14: All Presets Valid**
|
||||
- **Validates: Requirements 10.1, 10.2, 10.3, 10.4**
|
||||
- Test that all preset parameters conform to FFmpeg loudnorm specifications
|
||||
- Verify I is between -23 and 0, TP is between -5 and 0, LRA is between 1 and 20
|
||||
|
||||
- [x] 1.3 Implement settings persistence in Config module
|
||||
- Add `load_settings() -> dict` class method to load from storage
|
||||
- Add `save_settings(preset: str, custom_params: dict = None) -> bool` class method
|
||||
- Add `get_default_settings() -> dict` class method returning Normal preset
|
||||
- Implement JSON-based storage in application config directory
|
||||
- Handle missing/corrupted config files gracefully with defaults
|
||||
- _Requirements: 4.1, 4.2, 4.3, 11.1, 11.2, 11.3, 11.4, 11.5, 12.1, 12.4_
|
||||
|
||||
- [ ]* 1.4 Write property test for settings persistence
|
||||
- **Property 8: Settings Persist Across Sessions**
|
||||
- **Validates: Requirements 4.3, 11.2**
|
||||
- Generate random valid settings, save them, simulate restart, verify loading
|
||||
- Test that saved structure contains required keys: current_preset, custom_parameters
|
||||
|
||||
- [ ]* 1.5 Write property test for configuration structure
|
||||
- **Property 15: Configuration Structure Correct**
|
||||
- **Validates: Requirements 11.2**
|
||||
- Verify saved configuration includes current_preset (string) and custom_parameters (dict)
|
||||
- Test with various preset and parameter combinations
|
||||
|
||||
- [ ] 1.6 Checkpoint - Ensure all tests pass
|
||||
- Ensure all Phase 1 tests pass, ask the user if questions arise.
|
||||
|
||||
---
|
||||
|
||||
### Phase 2: Modal Component - NormalizationModal Class
|
||||
|
||||
- [x] 2.1 Create NormalizationModal class structure
|
||||
- Create `src/ui/components/normalization_modal_qt.py`
|
||||
- Implement `NormalizationModal(QDialog)` class
|
||||
- Define `settings_applied` pyqtSignal(dict) for emitting settings changes
|
||||
- Implement `__init__(parent, config)` constructor
|
||||
- Set modal properties: fixed size 500x400, dark theme (#212121), centered
|
||||
- _Requirements: 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 9.1, 9.2, 9.3, 9.4, 9.5_
|
||||
|
||||
- [x] 2.2 Implement preset selection UI
|
||||
- Create "Presets" section with QGroupBox
|
||||
- Add radio buttons for: Quiet, Normal, Loud, Very Loud, Custom
|
||||
- Implement `_on_preset_selected(preset_name: str)` slot
|
||||
- Connect radio button signals to preset selection handler
|
||||
- Display preset descriptions in UI
|
||||
- _Requirements: 2.1, 2.2, 2.3, 2.6_
|
||||
|
||||
- [ ]* 2.3 Write property test for preset selection
|
||||
- **Property 1: Preset Selection Updates Parameters**
|
||||
- **Validates: Requirements 2.3**
|
||||
- Generate random preset selections, verify parameter fields update correctly
|
||||
- Test that selected preset values match expected preset parameters
|
||||
|
||||
- [x] 2.4 Implement custom parameter input fields
|
||||
- Create three input fields: I (Integrated Loudness), TP (True Peak), LRA (Loudness Range)
|
||||
- Use QDoubleSpinBox or QLineEdit with validators
|
||||
- Display parameter labels with units (LUFS, dBFS, LU)
|
||||
- Implement `_on_parameter_changed(param_name: str, value: str)` slot
|
||||
- Connect input field signals to parameter change handler
|
||||
- _Requirements: 3.1, 3.2, 3.5_
|
||||
|
||||
- [x] 2.5 Implement parameter validation and error display
|
||||
- Implement `_validate_parameters() -> tuple[bool, str]` method
|
||||
- Check for non-numeric input, display "Parameter must be a number" error
|
||||
- Check for out-of-range values, display range error message
|
||||
- Create error display area (red-tinted label) above buttons
|
||||
- Update Apply button enabled state based on validation
|
||||
- _Requirements: 3.3, 3.4, 8.1, 8.2, 8.3, 8.4_
|
||||
|
||||
- [ ]* 2.6 Write property test for parameter validation
|
||||
- **Property 5: Parameter Validation Enforces Ranges**
|
||||
- **Validates: Requirements 3.3, 3.4, 8.2, 8.3**
|
||||
- Generate random parameter values (in and out of range)
|
||||
- Verify validation result matches expected range constraints
|
||||
- Test boundary values: -23, 0 for I; -5, 0 for TP; 1, 20 for LRA
|
||||
|
||||
- [x] 2.7 Implement preset/custom field interaction
|
||||
- Implement `_enable_custom_editing(enabled: bool)` method
|
||||
- When non-Custom preset selected: disable input fields, show preset values
|
||||
- When Custom preset selected: enable input fields for editing
|
||||
- _Requirements: 2.4, 2.5, 3.2_
|
||||
|
||||
- [ ]* 2.8 Write property test for preset/custom interaction
|
||||
- **Property 2: Non-Custom Presets Disable Editing**
|
||||
- **Property 3: Custom Preset Enables Editing**
|
||||
- **Validates: Requirements 2.4, 2.5**
|
||||
- Test that non-Custom presets disable input fields
|
||||
- Test that Custom preset enables input fields
|
||||
|
||||
- [x] 2.9 Implement settings loading on modal open
|
||||
- Implement `_load_current_settings()` method
|
||||
- Load settings from Config module on modal initialization
|
||||
- Display current preset as pre-selected
|
||||
- Populate parameter fields with current values
|
||||
- _Requirements: 2.6, 4.4_
|
||||
|
||||
- [ ]* 2.10 Write property test for modal initialization
|
||||
- **Property 4: Modal Loads Current Settings**
|
||||
- **Validates: Requirements 2.6**
|
||||
- Save settings to Config, open modal, verify current preset is pre-selected
|
||||
- Test with various preset and parameter combinations
|
||||
|
||||
- [x] 2.11 Implement apply and cancel button logic
|
||||
- Implement `_on_apply()` method: validate, save to Config, emit signal, close
|
||||
- Implement `_on_cancel()` method: close without saving
|
||||
- Implement `_on_close()` method for X button: same as cancel
|
||||
- Add Apply button (blue #2196F3) and Cancel button (gray #757575)
|
||||
- _Requirements: 1.9, 1.10, 4.1_
|
||||
|
||||
- [ ]* 2.12 Write property test for apply/cancel behavior
|
||||
- **Property 6: Cancel Discards Changes**
|
||||
- **Property 7: Apply Saves Settings**
|
||||
- **Validates: Requirements 1.9, 1.10, 4.1**
|
||||
- Test that Cancel closes without saving changes
|
||||
- Test that Apply saves valid settings and emits signal
|
||||
|
||||
- [x] 2.13 Implement settings display summary
|
||||
- Add label showing current preset name
|
||||
- Add label showing current parameter values in readable format
|
||||
- Update display when settings are loaded or changed
|
||||
- _Requirements: 7.1, 7.2_
|
||||
|
||||
- [ ] 2.14 Checkpoint - Ensure all modal tests pass
|
||||
- Ensure all Phase 2 tests pass, ask the user if questions arise.
|
||||
|
||||
---
|
||||
|
||||
### Phase 3: Integration with DownloadTab
|
||||
|
||||
- [x] 3.1 Add Normalization Settings button to DownloadTab
|
||||
- Modify `src/ui/tabs/download_tab_qt.py`
|
||||
- Add "Normalization Settings" button to control panel
|
||||
- Position button near other download controls (Start, Stop, Browse)
|
||||
- Button should be enabled at all times
|
||||
- _Requirements: 6.1, 6.2, 6.4_
|
||||
|
||||
- [x] 3.2 Implement modal opening from DownloadTab
|
||||
- Implement `_open_normalization_modal()` method in DownloadTab
|
||||
- Create NormalizationModal instance with Config reference
|
||||
- Connect button click to modal opening
|
||||
- _Requirements: 6.3_
|
||||
|
||||
- [ ]* 3.3 Write property test for modal opening
|
||||
- **Property 11: Modal Opens on Button Click**
|
||||
- **Validates: Requirements 6.3**
|
||||
- Click button, verify modal appears and displays current settings
|
||||
|
||||
- [x] 3.4 Implement preset indicator in DownloadTab
|
||||
- Add preset indicator label showing current active preset
|
||||
- Display format: "Preset: {preset_name} (I={I}, TP={TP}, LRA={LRA})"
|
||||
- Update indicator when settings are applied
|
||||
- _Requirements: 7.4_
|
||||
|
||||
- [ ] 3.5 Implement preset indicator tooltip
|
||||
- Add tooltip to preset indicator showing full parameter details
|
||||
- Tooltip displays when user hovers over indicator
|
||||
- _Requirements: 7.5_
|
||||
|
||||
- [ ]* 3.6 Write property test for preset indicator
|
||||
- **Property 12: Preset Indicator Shows Current Preset**
|
||||
- **Validates: Requirements 7.4**
|
||||
- Change settings, verify indicator updates to show new preset
|
||||
|
||||
- [x] 3.7 Connect modal signals to DownloadTab
|
||||
- Implement `_on_normalization_settings_applied(settings: dict)` slot
|
||||
- Connect modal's `settings_applied` signal to this slot
|
||||
- Update preset indicator when settings change
|
||||
- _Requirements: 6.5, 6.6_
|
||||
|
||||
- [x] 3.8 Implement settings button always enabled
|
||||
- Ensure button remains enabled during downloads
|
||||
- Ensure button remains enabled when idle
|
||||
- _Requirements: 6.4_
|
||||
|
||||
- [ ]* 3.9 Write property test for button availability
|
||||
- **Property 10: Settings Button Always Enabled**
|
||||
- **Validates: Requirements 6.4**
|
||||
- Verify button is enabled in all application states
|
||||
|
||||
- [ ] 3.10 Checkpoint - Ensure all integration tests pass
|
||||
- Ensure all Phase 3 tests pass, ask the user if questions arise.
|
||||
|
||||
---
|
||||
|
||||
### Phase 4: Downloader Module Updates
|
||||
|
||||
- [x] 4.1 Modify normalize_volume to use Config settings
|
||||
- Update `src/core/downloader.py` normalize_volume method
|
||||
- Load current settings from NormalizationSettings.load_settings()
|
||||
- Extract custom_parameters from loaded settings
|
||||
- _Requirements: 5.1, 5.2_
|
||||
|
||||
- [x] 4.2 Add parameter validation before FFmpeg command
|
||||
- Call NormalizationSettings.validate_parameters() before processing
|
||||
- Log error and skip normalization if validation fails
|
||||
- _Requirements: 10.5_
|
||||
|
||||
- [x] 4.3 Update FFmpeg command construction
|
||||
- Construct loudnorm filter string using format: `loudnorm=I={I}:TP={TP}:LRA={LRA}`
|
||||
- Use parameters from Config instead of hardcoded values
|
||||
- _Requirements: 5.3_
|
||||
|
||||
- [x] 4.4 Add logging for parameter usage
|
||||
- Log which preset/parameters are being applied
|
||||
- Log validation failures with error details
|
||||
- Log FFmpeg command construction
|
||||
- _Requirements: 5.1_
|
||||
|
||||
- [ ]* 4.5 Write property test for downloader settings usage
|
||||
- **Property 9: Downloader Uses Configured Settings**
|
||||
- **Validates: Requirements 5.1, 5.2, 5.3**
|
||||
- Configure settings, initiate download, verify FFmpeg command uses correct parameters
|
||||
- Test with various preset and custom parameter combinations
|
||||
|
||||
- [x] 4.6 Ensure backward compatibility
|
||||
- Verify default settings match current hardcoded behavior (Normal preset)
|
||||
- Test that downloads work without any settings configured
|
||||
- _Requirements: 12.1, 12.3_
|
||||
|
||||
- [x] 4.7 Implement graceful failure handling
|
||||
- If normalization fails, download continues without normalization
|
||||
- Log failure details for debugging
|
||||
- _Requirements: 5.5_
|
||||
|
||||
- [ ]* 4.8 Write property test for default settings
|
||||
- **Property 13: Default Settings on First Run**
|
||||
- **Validates: Requirements 4.5, 12.1, 12.2**
|
||||
- Verify default settings are Normal preset with I=-14, TP=-1.5, LRA=11
|
||||
|
||||
- [ ] 4.9 Checkpoint - Ensure all downloader tests pass
|
||||
- Ensure all Phase 4 tests pass, ask the user if questions arise.
|
||||
|
||||
---
|
||||
|
||||
### Phase 5: Comprehensive Testing and Validation
|
||||
|
||||
- [ ] 5.1 Write unit tests for NormalizationSettings class
|
||||
- Test preset parameter retrieval for all presets
|
||||
- Test parameter validation with valid and invalid values
|
||||
- Test boundary values for all parameters
|
||||
- Test settings loading and saving
|
||||
- Test default settings initialization
|
||||
- _Requirements: 10.1, 10.2, 10.3, 10.4, 11.1, 11.2, 12.1_
|
||||
|
||||
- [ ] 5.2 Write unit tests for NormalizationModal class
|
||||
- Test modal initialization and UI layout
|
||||
- Test preset selection and field updates
|
||||
- Test custom parameter input and validation
|
||||
- Test apply/cancel button behavior
|
||||
- Test error message display
|
||||
- Test settings loading on open
|
||||
- _Requirements: 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 1.10, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 3.1, 3.2, 3.3, 3.4, 3.5, 8.1, 8.2, 8.3, 8.4_
|
||||
|
||||
- [ ] 5.3 Write unit tests for DownloadTab integration
|
||||
- Test button creation and positioning
|
||||
- Test modal opening from button click
|
||||
- Test preset indicator display and updates
|
||||
- Test tooltip display
|
||||
- Test settings application signal handling
|
||||
- _Requirements: 6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 7.4, 7.5_
|
||||
|
||||
- [ ] 5.4 Write unit tests for Downloader integration
|
||||
- Test normalize_volume uses Config settings
|
||||
- Test parameter validation before FFmpeg command
|
||||
- Test FFmpeg command construction with parameters
|
||||
- Test logging of parameter usage
|
||||
- Test graceful failure handling
|
||||
- _Requirements: 5.1, 5.2, 5.3, 5.5, 10.5_
|
||||
|
||||
- [ ] 5.5 Write edge case tests
|
||||
- Test with boundary parameter values (min/max for each parameter)
|
||||
- Test with missing config file (should use defaults)
|
||||
- Test with corrupted config file (should use defaults and log warning)
|
||||
- Test rapid preset switching
|
||||
- Test modal open/close cycles
|
||||
- Test settings changes during active downloads
|
||||
- _Requirements: 6.6, 11.5, 12.4_
|
||||
|
||||
- [ ] 5.6 Write error scenario tests
|
||||
- Test non-numeric input in parameter fields
|
||||
- Test out-of-range parameter values
|
||||
- Test config save failures
|
||||
- Test config load failures
|
||||
- Test FFmpeg command construction with invalid parameters
|
||||
- _Requirements: 8.1, 8.2, 8.3, 8.4, 8.5, 11.5_
|
||||
|
||||
- [ ] 5.7 Write integration tests for end-to-end flow
|
||||
- Test complete flow: open modal → select preset → apply → verify settings used in download
|
||||
- Test complete flow: open modal → select custom → enter parameters → apply → verify settings used
|
||||
- Test complete flow: change settings → verify indicator updates → verify download uses new settings
|
||||
- _Requirements: 1.1, 1.10, 4.1, 5.1, 5.2, 5.3, 6.3, 6.5, 7.4_
|
||||
|
||||
- [ ] 5.8 Verify all property-based tests pass
|
||||
- Run all 20 property-based tests defined in design document
|
||||
- Ensure each property test validates its corresponding requirement
|
||||
- Verify test coverage for all correctness properties
|
||||
- _Requirements: All_
|
||||
|
||||
- [ ] 5.9 Final checkpoint - Ensure all tests pass
|
||||
- Ensure all unit tests pass
|
||||
- Ensure all property-based tests pass
|
||||
- Ensure all integration tests pass
|
||||
- Ensure all edge case tests pass
|
||||
- Ensure all error scenario tests pass
|
||||
- Ask the user if questions arise.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
### Code Organization
|
||||
|
||||
- **NormalizationSettings**: Add to `src/core/config.py` as a new class
|
||||
- **NormalizationModal**: Create new file `src/ui/components/normalization_modal_qt.py`
|
||||
- **DownloadTab modifications**: Update `src/ui/tabs/download_tab_qt.py`
|
||||
- **Downloader modifications**: Update `src/core/downloader.py`
|
||||
|
||||
### Testing Framework
|
||||
|
||||
- Use Python's `unittest` or `pytest` for unit tests
|
||||
- Use `hypothesis` library for property-based tests
|
||||
- Tag each property test with: `Feature: volume-normalization-modal, Property {number}: {property_text}`
|
||||
- Minimum 100 iterations per property test
|
||||
|
||||
### Styling Consistency
|
||||
|
||||
- Match DeleteModal styling: #212121 background, #ffffff text
|
||||
- Apply button: #2196F3 (blue)
|
||||
- Cancel button: #757575 (gray)
|
||||
- Input fields: dark theme with white text
|
||||
- Font: 11pt for labels, 12pt for buttons
|
||||
|
||||
### Backward Compatibility
|
||||
|
||||
- Default to "Normal" preset (I=-14, TP=-1.5, LRA=11) if no settings exist
|
||||
- Existing normalize_volume behavior preserved
|
||||
- No breaking changes to public APIs
|
||||
- Graceful degradation if settings unavailable
|
||||
|
||||
### Configuration Storage
|
||||
|
||||
- Store in application config directory (platform-specific)
|
||||
- Windows: `%APPDATA%/dl_yt/config.json`
|
||||
- macOS: `~/Library/Application Support/dl_yt/config.json`
|
||||
- Linux: `~/.config/dl_yt/config.json`
|
||||
- JSON format with keys: `current_preset`, `custom_parameters`
|
||||
|
||||
### Error Handling
|
||||
|
||||
- Log all errors with context
|
||||
- Display user-friendly error messages in modal
|
||||
- Continue downloads even if normalization fails
|
||||
- Use defaults if config loading fails
|
||||
|
||||
---
|
||||
|
||||
## Acceptance Criteria Summary
|
||||
|
||||
All tasks must satisfy the following acceptance criteria:
|
||||
|
||||
1. Code follows existing codebase patterns and conventions
|
||||
2. All unit tests pass with 90%+ coverage
|
||||
3. All property-based tests pass (minimum 100 iterations each)
|
||||
4. All integration tests pass
|
||||
5. No breaking changes to existing functionality
|
||||
6. Settings persist correctly across application sessions
|
||||
7. Modal UI matches design specifications
|
||||
8. Error handling is robust and user-friendly
|
||||
9. Logging is comprehensive for debugging
|
||||
10. Documentation is clear and maintainable
|
||||
Reference in New Issue
Block a user