From bd2fa1cab050ee390c9487ff8840ac950296b25d Mon Sep 17 00:00:00 2001 From: Keith Edmunds Date: Fri, 3 Nov 2023 09:08:06 +0000 Subject: [PATCH] Initialise FadeCurve in a thread Stops a UI delay of half a second or so when marking a track 'next' --- app/classes.py | 67 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/app/classes.py b/app/classes.py index af60a0e..ad776b8 100644 --- a/app/classes.py +++ b/app/classes.py @@ -2,32 +2,34 @@ from dataclasses import dataclass from datetime import datetime, timedelta from typing import Optional -from PyQt6.QtCore import pyqtSignal, QObject +from PyQt6.QtCore import pyqtSignal, QObject, QThread import numpy as np import pyqtgraph as pg # type: ignore from config import Config -from dbconfig import scoped_session -from models import PlaylistRows +from dbconfig import scoped_session, Session +from models import PlaylistRows, Tracks import helpers class FadeCurve: GraphWidget = None - def __init__(self, track): + def __init__( + self, track_path: str, track_fade_at: int, track_silence_at: int + ) -> None: """ Set up fade graph array """ - audio = helpers.get_audio_segment(track.path) + audio = helpers.get_audio_segment(track_path) if not audio: return None # Start point of curve is Config.FADE_CURVE_MS_BEFORE_FADE # milliseconds before fade starts to silence - self.start_ms = max(0, track.fade_at - Config.FADE_CURVE_MS_BEFORE_FADE - 1) - self.end_ms = track.silence_at + self.start_ms = max(0, track_fade_at - Config.FADE_CURVE_MS_BEFORE_FADE - 1) + self.end_ms = track_silence_at self.audio_segment = audio[self.start_ms : self.end_ms] self.graph_array = np.array(self.audio_segment.get_array_of_samples()) @@ -106,7 +108,7 @@ class PlaylistTrack: self.duration: Optional[int] = None self.end_time: Optional[datetime] = None self.fade_at: Optional[int] = None - self.fade_curve: Optional[FadeCurve] = None + self.fade_graph: Optional[FadeCurve] = None self.fade_length: Optional[int] = None self.path: Optional[str] = None self.playlist_id: Optional[int] = None @@ -139,7 +141,6 @@ class PlaylistTrack: self.duration = track.duration self.end_time = None self.fade_at = track.fade_at - self.fade_graph = FadeCurve(track) # TODO: speed this line up self.path = track.path self.playlist_id = plr.playlist_id self.plr_id = plr.id @@ -153,6 +154,22 @@ class PlaylistTrack: if track.silence_at and track.fade_at: self.fade_length = track.silence_at - track.fade_at + # Initialise and add FadeCurve in a thread as it's slow + # Import in separate thread + self.fadecurve_thread = QThread() + self.worker = AddFadeCurve( + self, + track_path=track.path, + track_fade_at=track.fade_at, + track_silence_at=track.silence_at, + ) + self.worker.moveToThread(self.fadecurve_thread) + self.fadecurve_thread.started.connect(self.worker.run) + self.worker.finished.connect(self.fadecurve_thread.quit) + self.worker.finished.connect(self.worker.deleteLater) + self.fadecurve_thread.finished.connect(self.fadecurve_thread.deleteLater) + self.fadecurve_thread.start() + def start(self) -> None: """ Called when track starts playing @@ -163,6 +180,38 @@ class PlaylistTrack: self.end_time = self.start_time + timedelta(milliseconds=self.duration) +class AddFadeCurve(QObject): + """ + Initialising a fade curve introduces a noticeable delay so carry out in + a thread. + """ + + finished = pyqtSignal() + + def __init__( + self, + playlist_track: PlaylistTrack, + track_path: str, + track_fade_at: int, + track_silence_at: int, + ): + super().__init__() + self.playlist_track = playlist_track + self.track_path = track_path + self.track_fade_at = track_fade_at + self.track_silence_at = track_silence_at + + def run(self): + """ + Create fade curve and add to PlaylistTrack object + """ + + self.playlist_track.fade_graph = FadeCurve( + self.track_path, self.track_fade_at, self.track_silence_at + ) + self.finished.emit() + + @helpers.singleton class CurrentTrack(PlaylistTrack): pass