Compare commits

...

2 Commits

Author SHA1 Message Date
Keith Edmunds
4ec1c0e09c Fade graph no longer lagging 2024-06-02 14:31:14 +01:00
Keith Edmunds
0361d25c7b WIP: fade graph working, slightly laggy 2024-06-02 13:33:57 +01:00
2 changed files with 52 additions and 38 deletions

View File

@ -2,23 +2,19 @@
# Standard library imports # Standard library imports
from os.path import basename from os.path import basename
from time import sleep from typing import List, Optional
from typing import cast, List, Optional
import argparse import argparse
import datetime as dt import datetime as dt
import os import os
import shutil import shutil
import subprocess import subprocess
import sys import sys
import threading
# PyQt imports # PyQt imports
from PyQt6.QtCore import ( from PyQt6.QtCore import (
pyqtSignal, pyqtSignal,
QDate, QDate,
QEvent,
QObject, QObject,
QSize,
Qt, Qt,
QThread, QThread,
QTime, QTime,
@ -27,10 +23,7 @@ from PyQt6.QtCore import (
from PyQt6.QtGui import ( from PyQt6.QtGui import (
QCloseEvent, QCloseEvent,
QColor, QColor,
QFont,
QMouseEvent,
QPalette, QPalette,
QResizeEvent,
) )
from PyQt6.QtWidgets import ( from PyQt6.QtWidgets import (
QApplication, QApplication,
@ -42,8 +35,6 @@ from PyQt6.QtWidgets import (
QListWidgetItem, QListWidgetItem,
QMainWindow, QMainWindow,
QMessageBox, QMessageBox,
QProgressBar,
QPushButton,
) )
# Third party imports # Third party imports
@ -176,7 +167,6 @@ class Window(QMainWindow, Ui_MainWindow):
self.widgetFadeVolume.hideAxis("left") self.widgetFadeVolume.hideAxis("left")
self.widgetFadeVolume.setDefaultPadding(0) self.widgetFadeVolume.setDefaultPadding(0)
self.widgetFadeVolume.setBackground(Config.FADE_CURVE_BACKGROUND) self.widgetFadeVolume.setBackground(Config.FADE_CURVE_BACKGROUND)
FadeCurve.GraphWidget = self.widgetFadeVolume
self.active_tab = lambda: self.tabPlaylist.currentWidget() self.active_tab = lambda: self.tabPlaylist.currentWidget()
self.active_proxy_model = lambda: self.tabPlaylist.currentWidget().model() self.active_proxy_model = lambda: self.tabPlaylist.currentWidget().model()
@ -999,7 +989,7 @@ class Window(QMainWindow, Ui_MainWindow):
): ):
return return
log.info(f"play_next({position=})") log.debug(f"play_next({position=})")
# If there is no next track set, return. # If there is no next track set, return.
if track_sequence.next is None: if track_sequence.next is None:
@ -1035,6 +1025,13 @@ class Window(QMainWindow, Ui_MainWindow):
# Play (new) current track # Play (new) current track
track_sequence.current.play(position) track_sequence.current.play(position)
# Show closing volume graph
if track_sequence.current.fade_graph:
track_sequence.current.fade_graph.GraphWidget = self.widgetFadeVolume
track_sequence.current.fade_graph.plot()
else:
log.error("No fade_graph")
# Disable play next controls # Disable play next controls
self.catch_return_key = True self.catch_return_key = True
self.show_status_message("Play controls: Disabled", 0) self.show_status_message("Play controls: Disabled", 0)
@ -1475,23 +1472,8 @@ class Window(QMainWindow, Ui_MainWindow):
Called every 10ms Called every 10ms
""" """
return if track_sequence.current:
# Update volume fade curve track_sequence.current.update_fade_graph()
if (
track_sequence.current.fade_graph_start_updates is None
or track_sequence.current.fade_graph_start_updates > dt.datetime.now()
):
return
if (
track_sequence.current.track_id
and track_sequence.current.fade_graph
and track_sequence.current.start_time
):
play_time = (
dt.datetime.now() - track_sequence.current.start_time
).total_seconds() * 1000
track_sequence.current.fade_graph.tick(play_time)
def tick_500ms(self) -> None: def tick_500ms(self) -> None:
""" """

View File

@ -43,13 +43,13 @@ class _AddFadeCurve(QObject):
def __init__( def __init__(
self, self,
track_player: _TrackManager, track_manager: _TrackManager,
track_path: str, track_path: str,
track_fade_at: int, track_fade_at: int,
track_silence_at: int, track_silence_at: int,
): ):
super().__init__() super().__init__()
self.track_player = track_player self.track_manager = track_manager
self.track_path = track_path self.track_path = track_path
self.track_fade_at = track_fade_at self.track_fade_at = track_fade_at
self.track_silence_at = track_silence_at self.track_silence_at = track_silence_at
@ -63,7 +63,7 @@ class _AddFadeCurve(QObject):
if not fc: if not fc:
log.error(f"Failed to create FadeCurve for {self.track_path=}") log.error(f"Failed to create FadeCurve for {self.track_path=}")
else: else:
self.track_player.fade_graph = fc self.track_manager.fade_graph = fc
self.finished.emit() self.finished.emit()
@ -84,8 +84,10 @@ class _FadeCurve:
# Start point of curve is Config.FADE_CURVE_MS_BEFORE_FADE # Start point of curve is Config.FADE_CURVE_MS_BEFORE_FADE
# milliseconds before fade starts to silence # milliseconds before fade starts to silence
self.start_ms = max(0, track_fade_at - Config.FADE_CURVE_MS_BEFORE_FADE - 1) self.start_ms: int = max(
self.end_ms = track_silence_at 0, track_fade_at - Config.FADE_CURVE_MS_BEFORE_FADE - 1
)
self.end_ms: int = track_silence_at
self.audio_segment = audio[self.start_ms : self.end_ms] self.audio_segment = audio[self.start_ms : self.end_ms]
self.graph_array = np.array(self.audio_segment.get_array_of_samples()) self.graph_array = np.array(self.audio_segment.get_array_of_samples())
@ -287,11 +289,19 @@ class _Music:
self._adjust_by_ms(ms) self._adjust_by_ms(ms)
def play(self, path: str, position: Optional[float]) -> None: def play(
self,
path: str,
start_time: dt.datetime,
position: Optional[float] = None,
) -> None:
""" """
Start playing the track at path. Start playing the track at path.
Log and return if path not found. Log and return if path not found.
start_time ensures our version and our caller's version of
the start time is the same
""" """
log.info(f"Music[{self.name}].play({path=}, {position=}") log.info(f"Music[{self.name}].play({path=}, {position=}")
@ -308,7 +318,7 @@ class _Music:
if position: if position:
self.player.set_position(position) self.player.set_position(position)
self.start_dt = dt.datetime.now() self.start_dt = start_time
# For as-yet unknown reasons. sometimes the volume gets # For as-yet unknown reasons. sometimes the volume gets
# reset to zero within 200mS or so of starting play. This # reset to zero within 200mS or so of starting play. This
@ -423,6 +433,8 @@ class _TrackManager:
if not self.player.is_playing(): if not self.player.is_playing():
self.start_time = None self.start_time = None
if self.fade_graph:
self.fade_graph.clear()
self.signals.track_ended_signal.emit() self.signals.track_ended_signal.emit()
def drop3db(self, enable: bool) -> None: def drop3db(self, enable: bool) -> None:
@ -453,10 +465,11 @@ class _TrackManager:
def play(self, position: Optional[float] = None) -> None: def play(self, position: Optional[float] = None) -> None:
"""Play track""" """Play track"""
self.player.play(self.path, position)
now = dt.datetime.now() now = dt.datetime.now()
self.start_time = now self.start_time = now
self.player.play(self.path, start_time=now, position=position)
self.end_time = self.start_time + dt.timedelta(milliseconds=self.duration) self.end_time = self.start_time + dt.timedelta(milliseconds=self.duration)
# Calculate time fade_graph should start updating # Calculate time fade_graph should start updating
@ -510,6 +523,25 @@ class _TrackManager:
return self.silence_at - self.time_playing() return self.silence_at - self.time_playing()
def update_fade_graph(self) -> None:
"""
Update fade graph
"""
if (
not self.is_playing()
or not self.fade_graph_start_updates
or not self.fade_graph
):
return
now = dt.datetime.now()
if self.fade_graph_start_updates > now:
return
self.fade_graph.tick(self.time_playing())
class MainTrackManager(_TrackManager): class MainTrackManager(_TrackManager):
""" """