soulsync/main.py
Broque Thomas 8dd433fc3b fix
2025-07-09 13:55:18 -07:00

196 lines
No EOL
6.5 KiB
Python

#!/usr/bin/env python3
import sys
import asyncio
from pathlib import Path
from PyQt6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, QWidget, QStackedWidget
from PyQt6.QtCore import QThread, pyqtSignal, QTimer
from PyQt6.QtGui import QFont, QPalette, QColor
from config.settings import config_manager
from utils.logging_config import setup_logging, get_logger
from core.spotify_client import SpotifyClient
from core.plex_client import PlexClient
from core.soulseek_client import SoulseekClient
from ui.sidebar import ModernSidebar
from ui.pages.dashboard import DashboardPage
from ui.pages.sync import SyncPage
from ui.pages.downloads import DownloadsPage
from ui.pages.artists import ArtistsPage
from ui.pages.settings import SettingsPage
logger = get_logger("main")
class ServiceStatusThread(QThread):
status_updated = pyqtSignal(str, bool)
def __init__(self, spotify_client, plex_client, soulseek_client):
super().__init__()
self.spotify_client = spotify_client
self.plex_client = plex_client
self.soulseek_client = soulseek_client
self.running = True
def run(self):
while self.running:
try:
# Check Spotify authentication
spotify_status = self.spotify_client.is_authenticated()
self.status_updated.emit("spotify", spotify_status)
# Check Plex connection
plex_status = self.plex_client.is_connected()
self.status_updated.emit("plex", plex_status)
# Check Soulseek connection (simplified check to avoid event loop issues)
soulseek_status = self.soulseek_client.is_configured()
self.status_updated.emit("soulseek", soulseek_status)
self.msleep(3000) # Check every 3 seconds
except Exception as e:
logger.error(f"Error checking service status: {e}")
self.msleep(5000)
def stop(self):
self.running = False
self.quit()
self.wait()
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.spotify_client = SpotifyClient()
self.plex_client = PlexClient()
self.soulseek_client = SoulseekClient()
self.status_thread = None
self.init_ui()
self.setup_status_monitoring()
def init_ui(self):
self.setWindowTitle("NewMusic - Music Sync & Manager")
self.setGeometry(100, 100, 1400, 900)
# Set dark theme palette
self.setStyleSheet("""
QMainWindow {
background: #121212;
}
""")
# Create central widget
central_widget = QWidget()
self.setCentralWidget(central_widget)
# Main layout
main_layout = QHBoxLayout(central_widget)
main_layout.setContentsMargins(0, 0, 0, 0)
main_layout.setSpacing(0)
# Create sidebar
self.sidebar = ModernSidebar()
self.sidebar.page_changed.connect(self.change_page)
main_layout.addWidget(self.sidebar)
# Create stacked widget for pages
self.stacked_widget = QStackedWidget()
# Create and add pages
self.dashboard_page = DashboardPage()
self.sync_page = SyncPage(self.spotify_client, self.plex_client)
self.downloads_page = DownloadsPage()
self.artists_page = ArtistsPage()
self.settings_page = SettingsPage()
self.stacked_widget.addWidget(self.dashboard_page)
self.stacked_widget.addWidget(self.sync_page)
self.stacked_widget.addWidget(self.downloads_page)
self.stacked_widget.addWidget(self.artists_page)
self.stacked_widget.addWidget(self.settings_page)
main_layout.addWidget(self.stacked_widget)
# Set dashboard as default page
self.change_page("dashboard")
def setup_status_monitoring(self):
# Start status monitoring thread
self.status_thread = ServiceStatusThread(
self.spotify_client,
self.plex_client,
self.soulseek_client
)
self.status_thread.status_updated.connect(self.update_service_status)
self.status_thread.start()
def change_page(self, page_id: str):
page_map = {
"dashboard": 0,
"sync": 1,
"downloads": 2,
"artists": 3,
"settings": 4
}
if page_id in page_map:
self.stacked_widget.setCurrentIndex(page_map[page_id])
logger.info(f"Changed to page: {page_id}")
def update_service_status(self, service: str, connected: bool):
self.sidebar.update_service_status(service, connected)
# Force a refresh of the Spotify client if needed
if service == "spotify" and not connected:
try:
self.spotify_client._setup_client()
except Exception as e:
logger.error(f"Error refreshing Spotify client: {e}")
def closeEvent(self, event):
logger.info("Closing application...")
# Stop status monitoring thread
if self.status_thread:
self.status_thread.stop()
# Close Soulseek client
try:
loop = asyncio.get_event_loop()
loop.run_until_complete(self.soulseek_client.close())
except Exception as e:
logger.error(f"Error closing Soulseek client: {e}")
event.accept()
def main():
logging_config = config_manager.get_logging_config()
log_level = logging_config.get('level', 'INFO')
log_file = logging_config.get('path', 'logs/newmusic.log')
setup_logging(level=log_level, log_file=log_file)
logger.info("Starting NewMusic application")
if not config_manager.config_path.exists():
logger.error("Configuration file not found. Please check config/config.json")
sys.exit(1)
app = QApplication(sys.argv)
app.setApplicationName("NewMusic")
app.setApplicationVersion("1.0.0")
main_window = MainWindow()
main_window.show()
try:
sys.exit(app.exec())
except KeyboardInterrupt:
logger.info("Application interrupted by user")
sys.exit(0)
except Exception as e:
logger.error(f"Unexpected error: {e}")
sys.exit(1)
if __name__ == "__main__":
main()