Skip to content

Commit 04dc17a

Browse files
authored
Refactor entrypoints and initialization throughout (#128)
1 parent 491f978 commit 04dc17a

25 files changed

Lines changed: 92 additions & 196 deletions

main.py

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
from voxkit.config.app_config import AppConfig, get_app_config, get_profile_config_path
1313
from voxkit.config.logging_config import setup_logging
1414

15-
# Disable Qt emoji support to prevent crashes in frozen builds
16-
15+
# Minimal early config so frozen-env messages below are emitted before
16+
# setup_logging() runs in main(); setup_logging() will reconfigure handlers.
17+
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s: %(message)s")
18+
log = logging.getLogger("voxkit.main")
1719

1820
# CRITICAL: Must be at the top for frozen apps using multiprocessing
1921
if __name__ == "__main__":
@@ -55,10 +57,10 @@
5557
if conda_bin:
5658
existing_path = os.environ.get('PATH', '/usr/bin:/bin:/usr/sbin:/sbin')
5759
minimal_env['PATH'] = f"{conda_bin}:{existing_path}"
58-
print(f"[FROZEN] Added conda to PATH: {conda_bin}")
60+
log.info("[FROZEN] Added conda to PATH: %s", conda_bin)
5961
else:
6062
minimal_env['PATH'] = os.environ.get('PATH', '/usr/bin:/bin:/usr/sbin:/sbin')
61-
print("[FROZEN] Warning: conda not found in standard locations. MFA alignment may fail.")
63+
log.warning("[FROZEN] conda not found in standard locations. MFA alignment may fail.")
6264

6365
# PyInstaller-specific: Add Qt plugin paths
6466
if getattr(sys, '_MEIPASS', None):
@@ -67,30 +69,26 @@
6769
if os.path.exists(qt_plugins):
6870
minimal_env['QT_PLUGIN_PATH'] = qt_plugins
6971
minimal_env['QT_QPA_PLATFORM_PLUGIN_PATH'] = os.path.join(qt_plugins, 'platforms')
70-
72+
7173
# Additional Qt environment for frozen apps
7274
minimal_env['QT_AUTO_SCREEN_SCALE_FACTOR'] = '1'
7375
minimal_env['QT_LOGGING_RULES'] = '*.debug=false;qt.qpa.*=false'
74-
75-
print(f"[FROZEN] Qt plugins directory: {qt_plugins}")
76-
print(f"[FROZEN] Bundle directory: {bundle_dir}")
76+
77+
log.info("[FROZEN] Qt plugins directory: %s", qt_plugins)
78+
log.info("[FROZEN] Bundle directory: %s", bundle_dir)
7779

7880
# IMPORTANT: Don't clear os.environ - preserve system environment
7981
# Just add/override our minimal required variables
8082
for key, value in minimal_env.items():
8183
if value:
8284
os.environ[key] = value
83-
84-
print("[FROZEN] Environment configured for frozen app")
85-
8685

86+
log.info("[FROZEN] Environment configured for frozen app")
8787

8888
from PyQt6.QtWidgets import QApplication
8989
from voxkit.config import STARTUP_SCRIPT
90-
from voxkit.gui import AlignmentGUI
90+
from voxkit.gui import VoxKitGUI
9191
from voxkit.gui.workers.startup import execute_startup_script
92-
from pathlib import Path
93-
9492

9593
def main():
9694
# Initialize logging as early as possible so startup work is captured.
@@ -108,7 +106,6 @@ def main():
108106
from voxkit.gui.components.log_handler import get_gui_log_handler
109107
get_gui_log_handler()
110108

111-
log = logging.getLogger("voxkit.main")
112109
log.info("VoxKit starting (frozen=%s)", bool(getattr(sys, "frozen", False)))
113110

114111
app = QApplication(sys.argv)
@@ -128,14 +125,13 @@ def main():
128125
app_config = AppConfig.from_yaml(profile_path / "app_info.yaml")
129126
pipeline_config = PipelineConfig.from_yaml(profile_path / "pipeline_definitions.yaml")
130127

131-
window = AlignmentGUI(pipeline_config=pipeline_config, app_config=app_config)
128+
window = VoxKitGUI(pipeline_config=pipeline_config, app_config=app_config)
132129
window.show()
133130
log.info("Main window shown, entering Qt event loop")
134131
sys.exit(app.exec())
135132

136133

137134
if __name__ == "__main__":
138135
# Prevent multiprocessing from spawning new app windows in frozen builds
139-
multiprocessing.freeze_support()
140136
multiprocessing.set_start_method('spawn', force=True)
141137
main()

src/voxkit/__init__.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
1-
"""VoxKit - Speech Analysis and Forced Alignment Toolkit.
2-
3-
A desktop application bridging AI/ML research and clinical speech-language
4-
pathology. Provides accessible interfaces to forced alignment engines and
5-
flexible dataset analysis tools.
1+
"""Modules for VoxKit; Provides accessible interfaces to forced alignment engines and
2+
flexible dataset analysis and management tools.
63
74
Subpackages
85
-----------
9-
- **engines**: Speech toolkit backends (MFA, Faster-Whisper)
6+
- **engines**: Speech toolkit backends (MFA, W2TG. FasterWhisper, etc.)
107
- **analyzers**: Dataset metadata extraction
118
- **storage**: Persistence for datasets, models, and alignments
129
- **gui**: PyQt6 desktop interface
1310
- **config**: Application and pipeline configuration
1411
"""
1512

16-
__version__ = "0.1.0"
17-
__author__ = "Beckett Frey @beckettfrey.com"
13+
__version__ = "0.4.0"
14+
__author__ = "Beckett Frey - code@beckettfrey.com"
1815

1916
# Import subpackages for pdoc discoverability (not re-exported in __all__)
2017
from . import analyzers, config, engines, gui, storage

src/voxkit/analyzers/__init__.py

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
1-
"""VoxKit Analyzers Module.
2-
3-
Analyzers observe datasets and link metadata in flexible, abstract ways. They
4-
extract structured information at registration time, producing CSV summaries
1+
"""Analyzers observe datasets and link metadata. They
2+
extract structured information at registration time (ingestion), producing CSV summaries
53
that can be visualized within VoxKit without rescanning the filesystem.
64
75
API
86
---
97
- **AnalyzerManager.list_analyzers**: List registered analyzer IDs
108
- **AnalyzerManager.get_analyzer**: Retrieve analyzer instance by ID
119
- **AnalyzerManager.get_analyzers**: Get all registered analyzers
12-
- **DatasetAnalyzer**: Abstract base class for all analyzers
1310
1411
Available Analyzers
1512
-------------------
16-
**DefaultAnalyzer** (``default_analyzer.py``)
13+
**DefaultAnalyzer**
1714
Extracts speaker count and audio file counts per speaker directory.
1815
Includes a bar chart visualization for quick dataset overview.
1916
@@ -28,7 +25,7 @@
2825
2926
Notes
3027
-----
31-
- Analyzers run during dataset registration
28+
- Analyzers run during dataset registration (ingestion)
3229
- Each analyzer's ``name`` property serves as its unique identifier
3330
- Output is a list of dicts where keys become CSV column headers
3431
- Custom visualizations can be provided via the ``visualize`` method
@@ -78,7 +75,4 @@ def get_analyzer(self, analyzer_id: str) -> DatasetAnalyzer:
7875

7976
__all__ = [
8077
"ManageAnalyzers",
81-
"AnalyzerManager",
82-
"DatasetAnalyzer",
83-
"DefaultAnalyzer",
8478
]

src/voxkit/config/__init__.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
1-
"""VoxKit configuration module.
1+
"""This module provides access to configurable info about the application.
22
3-
This module provides access to application and pipeline configurations.
3+
Configurations
4+
--------------
5+
- App config: application metadata and provenance (``app_config``).
6+
- Pipeline config: pipeline steps and UI wiring (``pipeline_config``).
7+
- Startup config: launch-time constants and defaults (``startup_config``).
8+
- Logging config: rotating file logger setup (``logging_config``).
9+
10+
Only ``app_config`` and ``pipeline_config`` are dynamic post-build; they are
11+
loaded from YAML files under the active profile and can change without a
12+
rebuild. ``startup_config`` and ``logging_config`` are baked in at build time.
413
514
Profile System
615
--------------
@@ -19,6 +28,11 @@
1928
get_profile_config_path,
2029
resolve_config_file,
2130
)
31+
from voxkit.config.logging_config import (
32+
LOG_FILE,
33+
reset_logging,
34+
setup_logging,
35+
)
2236
from voxkit.config.pipeline_config import (
2337
PipelineConfig,
2438
PipelineStep,
@@ -55,4 +69,8 @@
5569
"Defaults",
5670
"Mode",
5771
"STARTUP_SCRIPT",
72+
# Logging config
73+
"LOG_FILE",
74+
"setup_logging",
75+
"reset_logging",
5876
]

src/voxkit/engines/__init__.py

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,28 @@
1-
"""VoxKit Engines Module.
2-
3-
Engines are speech toolkit backends that perform alignment, training, and
4-
transcription operations. Each engine provides one or more tools with
5-
configurable settings.
1+
"""Engines are speech toolkit backends. Each engine provides one or more tools
2+
where each tool is a unit of functionality (e.g. alignment, training, transcription).
63
74
API
85
---
96
- **EngineManager.list_engines**: List registered engine IDs
107
- **EngineManager.get_engine**: Retrieve engine instance by ID
118
- **EngineManager.get_tool_providers**: Get engines providing a specific tool type
12-
- **AlignmentEngine**: Abstract base class for all engines
13-
- **ToolType**: Literal type for tool categories ("train", "align", "transcribe")
9+
- **ToolType**: Literal type for compatible tool types
1410
1511
Available Engines
1612
-----------------
17-
**MFAEngine** (``mfa_engine.py``)
13+
**MFAEngine**
1814
Montreal Forced Aligner integration. Provides alignment using pretrained
1915
acoustic models and training via model adaptation.
16+
Tools: ``alignment``, ``training``
2017
21-
**FasterWhisperEngine** (``faster_whisper_engine.py``)
22-
Faster-Whisper integration for transcription. Produces .lab label files
23-
from audio using CTranslate2 backend.
18+
**W2TGEngine**
19+
Wav2TextGrid integration using Wav2Vec 2.0 models.
20+
Tools: ``alignment``, ``training``
2421
25-
**W2TGEngine** (``w2tg_engine.py``) [disabled]
26-
Wav2TextGrid integration using Wav2Vec 2.0 models. Supports both
27-
alignment and from-scratch training.
22+
**FasterWhisperEngine**
23+
Faster-Whisper integration for transcription. Produces .lab transcript files
24+
from audio using CTranslate2 backend.
25+
Tools: ``transcription``
2826
2927
Storage Structure
3028
-----------------
@@ -60,7 +58,7 @@ class EngineManager:
6058
"""
6159
Manager class for registered engines.
6260
63-
Provides a unified interface to list and retrieve registered alignment engines.
61+
Provides a unified interface to list and retrieve engines.
6462
6563
Methods:
6664
list_engines(): Return a list of registered engine IDs.
@@ -99,11 +97,4 @@ def get_tool_providers(self, tool: ToolType) -> dict[str, AlignmentEngine]:
9997
faster_whisper = FasterWhisperEngine(id="FASTERWHISPERENGINE")
10098
engines = EngineManager({mfa.id: mfa, faster_whisper.id: faster_whisper, w2tg.id: w2tg})
10199

102-
__all__ = [
103-
"engines",
104-
"EngineManager",
105-
"AlignmentEngine",
106-
"ToolType",
107-
"MFAEngine",
108-
"FasterWhisperEngine",
109-
]
100+
__all__ = ["engines", "ToolType"]

src/voxkit/gui/__init__.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
"""VoxKit GUI Module.
2-
3-
PyQt6-based graphical user interface for the VoxKit desktop application.
1+
"""PyQt6-based graphical user interface for interacting with datasets using tools.
2+
Designed for ease of use and extensibility.
43
54
API
65
---
7-
- **AlignmentGUI**: Main application window with toolbar navigation
6+
- **VoxKitGUI**: Main application window with toolbar navigation
87
98
Submodules
109
----------
@@ -167,13 +166,13 @@
167166
"""
168167

169168

170-
class AlignmentGUI(QMainWindow):
169+
class VoxKitGUI(QMainWindow):
171170
def __init__(
172171
self,
173172
app_config: Optional[AppConfig] = None,
174173
pipeline_config: Optional[PipelineConfig] = None,
175174
):
176-
"""Initialize the AlignmentGUI.
175+
"""Initialize the VoxKitGUI.
177176
178177
Args:
179178
app_config: Application configuration. If None, loads default from config files.
@@ -186,7 +185,7 @@ def __init__(
186185
self.pipeline_config = pipeline_config or get_pipeline_config()
187186

188187
logger.info(
189-
"AlignmentGUI initialized: app=%s version=%s",
188+
"VoxKitGUI initialized: app=%s version=%s",
190189
self.app_config.app_name,
191190
self.app_config.version,
192191
)
@@ -450,4 +449,4 @@ def _open_log_viewer(self) -> None:
450449
self._log_viewer.activateWindow()
451450

452451

453-
__all__ = ["AlignmentGUI"]
452+
__all__ = ["VoxKitGUI"]

src/voxkit/gui/components/__init__.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
"""Components Module.
2-
3-
Reusable PyQt6 widgets used throughout the VoxKit application.
1+
"""Reusable PyQt6 widgets taiored functionally and stylistically for the VoxKit application.
42
53
API
64
---
@@ -10,6 +8,9 @@
108
- **GripSplitter**: QSplitter with visible grip handle for intuitive resizing
119
- **HuggingFaceButton**: Branded button with HuggingFace logo
1210
- **LoadingDialog**: Splash screen / loading dialog with animated spinner
11+
- **LogViewerDialog**: Dialog for viewing live application logs
12+
- **QObjectLogHandler**: Qt-aware logging handler that emits records as Qt signals
13+
- **get_gui_log_handler**: Accessor for the singleton GUI log handler
1314
- **ModelSelectionPanel**: Combined engine and model selection panel
1415
- **MultiColumnComboBox**: QComboBox with multi-column dropdown table display
1516
- **OverlayWidget**: Semi-transparent overlay for modal blur effects
@@ -29,6 +30,7 @@
2930
from .grip_splitter import GripSplitter
3031
from .huggingface_button import HuggingFaceButton
3132
from .loading_dialog import LoadingDialog
33+
from .log_handler import QObjectLogHandler, get_gui_log_handler
3234
from .log_viewer_dialog import LogViewerDialog
3335
from .model_selection_panel import ModelSelectionPanel
3436
from .overlay_effects import OverlayWidget
@@ -45,5 +47,7 @@
4547
"ModelSelectionPanel",
4648
"MultiColumnComboBox",
4749
"OverlayWidget",
50+
"QObjectLogHandler",
4851
"ToggleSwitch",
52+
"get_gui_log_handler",
4953
]

src/voxkit/gui/components/animate_stack.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
1-
"""Animated Stack Module.
2-
3-
QStackedWidget with smooth slide transition animations.
4-
5-
API
6-
---
7-
- **AnimatedStackedWidget**: Stacked widget with animated page transitions
8-
"""
1+
"""QStackedWidget with smooth slide transition animations."""
92

103
from PyQt6.QtCore import QEasingCurve, QPoint, QPropertyAnimation
114
from PyQt6.QtWidgets import QStackedWidget

src/voxkit/gui/components/column_dropdown.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
1-
"""Column Dropdown Module.
2-
3-
QComboBox with multi-column table dropdown display.
4-
5-
API
6-
---
7-
- **MultiColumnComboBox**: ComboBox with tabular dropdown (single selection)
8-
"""
1+
"""QComboBox with multi-column table dropdown display."""
92

103
import sys
114

src/voxkit/gui/components/csv_viewer_dialog.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
1-
"""CSV Viewer Dialog Module.
2-
3-
Modal dialog for viewing CSV files in a formatted table.
4-
5-
API
6-
---
7-
- **CSVViewerDialog**: Dialog that displays CSV data with blur background effect
8-
"""
1+
"""Modal dialog for viewing CSV files in a formatted table."""
92

103
import csv
114
import os

0 commit comments

Comments
 (0)