Implement threading, logging, and CJK font support
Major improvements to GUI stability and internationalization: - Fix GUI freezing by implementing threaded audio analysis - Add AudioAnalysisWorker thread for background processing - Progress signals with percentage updates - Thread-safe communication via Qt signals - Add comprehensive CLI logging system - 5 log levels: ERROR, WARN, INFO, DEBUG, TRACE - Command line control: --log-level, --log-file - Real-time feedback during analysis operations - Implement CJK font fallback system - FontManager with 3-tier fallback (custom → system → default) - Cross-platform CJK font detection (Windows/macOS/Linux) - Licensing-safe fonts/ directory with gitignored font files - Setup utility and comprehensive documentation - Fix numpy array formatting issue with BPM detection - Add progress indicators for long-running operations - Preserve fonts directory structure with placeholder file 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
"""
|
||||
Logging configuration for the Audio Mastering Toolkit.
|
||||
Provides CLI configurable logging with different verbosity levels.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import sys
|
||||
from typing import Optional
|
||||
|
||||
|
||||
def setup_logging(level: str = "INFO", log_to_file: bool = False) -> logging.Logger:
|
||||
"""
|
||||
Setup logging configuration for the application.
|
||||
|
||||
Args:
|
||||
level: Logging level (ERROR, WARN, INFO, DEBUG, TRACE)
|
||||
log_to_file: Whether to also log to file
|
||||
|
||||
Returns:
|
||||
Configured logger instance
|
||||
"""
|
||||
# Convert level string to logging constant
|
||||
level_map = {
|
||||
'ERROR': logging.ERROR,
|
||||
'WARN': logging.WARNING,
|
||||
'WARNING': logging.WARNING,
|
||||
'INFO': logging.INFO,
|
||||
'DEBUG': logging.DEBUG,
|
||||
'TRACE': 5 # Custom level below DEBUG
|
||||
}
|
||||
|
||||
# Add custom TRACE level
|
||||
logging.addLevelName(5, 'TRACE')
|
||||
|
||||
numeric_level = level_map.get(level.upper(), logging.INFO)
|
||||
|
||||
# Create formatter
|
||||
formatter = logging.Formatter(
|
||||
'%(asctime)s [%(levelname)s] %(name)s: %(message)s',
|
||||
datefmt='%H:%M:%S'
|
||||
)
|
||||
|
||||
# Setup console handler
|
||||
console_handler = logging.StreamHandler(sys.stdout)
|
||||
console_handler.setFormatter(formatter)
|
||||
console_handler.setLevel(numeric_level)
|
||||
|
||||
# Setup root logger
|
||||
root_logger = logging.getLogger()
|
||||
root_logger.setLevel(numeric_level)
|
||||
root_logger.handlers.clear() # Clear any existing handlers
|
||||
root_logger.addHandler(console_handler)
|
||||
|
||||
# Optional file logging
|
||||
if log_to_file:
|
||||
file_handler = logging.FileHandler('audio_analysis.log')
|
||||
file_handler.setFormatter(formatter)
|
||||
file_handler.setLevel(numeric_level)
|
||||
root_logger.addHandler(file_handler)
|
||||
|
||||
# Add trace method to all loggers
|
||||
def trace(self, message, *args, **kwargs):
|
||||
if self.isEnabledFor(5):
|
||||
self._log(5, message, args, **kwargs)
|
||||
|
||||
logging.Logger.trace = trace
|
||||
|
||||
# Create main application logger
|
||||
app_logger = logging.getLogger('audio_mastering')
|
||||
app_logger.info(f"Logging initialized at {level.upper()} level")
|
||||
|
||||
return app_logger
|
||||
|
||||
|
||||
def parse_log_args() -> tuple[str, bool]:
|
||||
"""
|
||||
Parse command line arguments for logging configuration.
|
||||
|
||||
Returns:
|
||||
Tuple of (log_level, log_to_file)
|
||||
"""
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(add_help=False) # Don't interfere with main arg parsing
|
||||
parser.add_argument('--log-level', '-l',
|
||||
choices=['ERROR', 'WARN', 'INFO', 'DEBUG', 'TRACE'],
|
||||
default='INFO',
|
||||
help='Set logging verbosity level')
|
||||
parser.add_argument('--log-file', action='store_true',
|
||||
help='Also log to audio_analysis.log file')
|
||||
|
||||
# Parse known args only (ignore others for main app)
|
||||
args, _ = parser.parse_known_args()
|
||||
|
||||
return args.log_level, args.log_file
|
||||
Reference in New Issue
Block a user