From f466821ece5073d449d3ea79aff8e75f05ffd456 Mon Sep 17 00:00:00 2001 From: tsi-billypom Date: Tue, 30 Jul 2024 15:45:00 -0400 Subject: [PATCH] typing and reorganization --- components/AudioVisualizer.py | 5 +- new.py | 181 ++++++++++++++++------------------ utils/__init__.py | 2 +- utils/fft_analyser.py | 5 - utils/set_id3_tag.py | 2 +- 5 files changed, 92 insertions(+), 103 deletions(-) diff --git a/components/AudioVisualizer.py b/components/AudioVisualizer.py index 7a8f7cd..118a0b4 100644 --- a/components/AudioVisualizer.py +++ b/components/AudioVisualizer.py @@ -1,8 +1,8 @@ -from PyQt5 import QtWidgets import numpy as np - +from PyQt5 import QtWidgets from utils import FFTAnalyser + class AudioVisualizer(QtWidgets.QWidget): """_Audio Visualizer component_ @@ -12,6 +12,7 @@ class AudioVisualizer(QtWidgets.QWidget): Returns: _type_: _description_ """ + def __init__(self, media_player): super().__init__() self.media_player = media_player diff --git a/new.py b/new.py index 11d1622..c67de53 100644 --- a/new.py +++ b/new.py @@ -10,7 +10,6 @@ from mutagen.id3 import ID3 from mutagen.id3._frames import APIC from configparser import ConfigParser import DBA -from ui import Ui_MainWindow from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtWidgets import ( QFileDialog, @@ -33,34 +32,32 @@ from components import ( ) -class MainWindow(QMainWindow, Ui_MainWindow): +class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() global stopped stopped = False - # Initialization + # Vars self.setupUi(self) self.setWindowTitle("MusicPom") - self.selected_song_filepath = None - self.current_song_filepath = None - self.current_song_metadata = None - self.current_song_album_art = None - self.album_art_scene = QGraphicsScene() - self.config = configparser.ConfigParser() + self.selected_song_filepath: str | None = None + self.current_song_filepath: str | None = None + self.current_song_metadata: ID3 | dict | None = None + self.current_song_album_art: bytes | None = None + self.album_art_scene: QGraphicsScene = QGraphicsScene() + self.config: ConfigParser = configparser.ConfigParser() + self.player: QMediaPlayer = QMediaPlayer() # Audio player object + self.probe: QAudioProbe = QAudioProbe() # Gets audio data + self.audio_visualizer: AudioVisualizer = AudioVisualizer(self.player) + self.current_volume: int = 50 + # Initialization self.config.read("config.ini") - self.player = QMediaPlayer() # Audio player object - self.audio_visualizer = AudioVisualizer(self.player) - self.current_volume = 50 self.player.setVolume(self.current_volume) - # Audio probe for processing audio signal in real time - # Provides faster updates than move_slider - self.probe = QAudioProbe() # Gets audio data self.probe.setSource(self.player) self.probe.audioBufferProbed.connect(self.process_probe) - # Slider Timer (realtime playback feedback horizontal bar) - self.timer = QTimer(self) # Audio timing things + self.timer: QTimer = QTimer(self) # Audio timing things self.timer.start( 150 ) # 150ms update interval solved problem with drag seeking halting playback @@ -84,42 +81,39 @@ class MainWindow(QMainWindow, Ui_MainWindow): # |_____________| # FIXME: moving the slider while playing is happening frequently causes playback to halt - the pyqtgraph is also affected by this - # self.playbackSlider.sliderMoved[int].connect( + # so it must be affecting our QMediaPlayer as well + # self.playbackSlider.sliderMoved[int].connect( # lambda: self.player.setPosition(self.playbackSlider.value()) # ) - self.playbackSlider.sliderReleased[int].connect( + self.playbackSlider.sliderReleased.connect( lambda: self.player.setPosition(self.playbackSlider.value()) ) # maybe sliderReleased works better than sliderMoved self.volumeSlider.sliderMoved[int].connect( lambda: self.volume_changed() ) # Move slider to adjust volume - self.playButton.clicked.connect(self.on_play_clicked) # Click to play/pause - self.previousButton.clicked.connect( - self.on_previous_clicked - ) # Click to previous song - self.nextButton.clicked.connect(self.on_next_clicked) # Click to next song + # Playback controls + self.playButton.clicked.connect(self.on_play_clicked) + self.prevButton.clicked.connect(self.on_previous_clicked) + self.nextButton.clicked.connect(self.on_next_clicked) # FILE MENU self.actionOpenFiles.triggered.connect(self.open_files) # Open files window # EDIT MENU - # VIEW MENU self.actionPreferences.triggered.connect( self.open_preferences ) # Open preferences menu + # VIEW MENU # QUICK ACTIONS MENU self.actionScanLibraries.triggered.connect(self.scan_libraries) self.actionDeleteLibrary.triggered.connect(self.clear_database) self.actionDeleteDatabase.triggered.connect(self.delete_database) - ## tableView triggers - self.tableView.doubleClicked.connect( - self.play_audio_file - ) # Listens for the double click event, then plays the song - self.tableView.enterKey.connect( - self.play_audio_file - ) # Listens for the enter key event, then plays the song - self.tableView.playPauseSignal.connect( - self.on_play_clicked - ) # Spacebar toggle play/pause signal - # albumGraphicsView + ## Music Table | self.tableView triggers + # Listens for the double click event, then plays the song + self.tableView.doubleClicked.connect(self.play_audio_file) + # Listens for the enter key event, then plays the song + self.tableView.enterKey.connect(self.play_audio_file) + # Spacebar for toggle play/pause + self.tableView.playPauseSignal.connect(self.on_play_clicked) + # Album Art | self.albumGraphicsView self.albumGraphicsView.albumArtDropped.connect( self.set_album_art_for_selected_songs ) @@ -141,8 +135,10 @@ class MainWindow(QMainWindow, Ui_MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(1152, 894) MainWindow.setStatusTip("") + # Main self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") + # self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.centralwidget) self.verticalLayout_3.setObjectName("verticalLayout_3") self.hLayoutHead = QtWidgets.QHBoxLayout() @@ -262,12 +258,12 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.verticalLayout_3.addLayout(self.hLayoutMusicTable) self.hLayoutControls = QtWidgets.QHBoxLayout() self.hLayoutControls.setObjectName("hLayoutControls") - self.previousButton = QtWidgets.QPushButton(self.centralwidget) + self.prevButton = QtWidgets.QPushButton(self.centralwidget) font = QtGui.QFont() font.setPointSize(28) - self.previousButton.setFont(font) - self.previousButton.setObjectName("previousButton") - self.hLayoutControls.addWidget(self.previousButton) + self.prevButton.setFont(font) + self.prevButton.setObjectName("prevButton") + self.hLayoutControls.addWidget(self.prevButton) self.playButton = QtWidgets.QPushButton(self.centralwidget) font = QtGui.QFont() font.setPointSize(28) @@ -342,7 +338,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.startTimeLabel.setText(_translate("MainWindow", "00:00")) self.slashLabel.setText(_translate("MainWindow", "/")) self.endTimeLabel.setText(_translate("MainWindow", "00:00")) - self.previousButton.setText(_translate("MainWindow", "⏮️")) + self.prevButton.setText(_translate("MainWindow", "⏮️")) self.playButton.setText(_translate("MainWindow", "▶️")) self.nextButton.setText(_translate("MainWindow", "⏭️")) self.menuFile.setTitle(_translate("MainWindow", "File")) @@ -372,39 +368,6 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.config.write(configfile) super().closeEvent(a0) - def play_audio_file(self) -> None: - """Start playback of tableView.current_song_filepath track & moves playback slider""" - self.current_song_metadata = ( - self.tableView.get_current_song_metadata() - ) # get metadata - self.current_song_album_art = self.tableView.get_current_song_album_art() - url = QUrl.fromLocalFile( - self.tableView.get_current_song_filepath() - ) # read the file - content = QMediaContent(url) # load the audio content - self.player.setMedia(content) # what content to play - self.player.play() # play - self.move_slider() # mover - - # assign metadata - artist = ( - self.current_song_metadata["TPE1"][0] - if "artist" in self.current_song_metadata - else None - ) - album = ( - self.current_song_metadata["TALB"][0] - if "album" in self.current_song_metadata - else None - ) - title = self.current_song_metadata["TIT2"][0] - # edit labels - self.artistLabel.setText(artist) - self.albumLabel.setText(album) - self.titleLabel.setText(title) - # set album artwork - self.load_album_art(self.current_song_album_art) - def load_album_art(self, album_art_data) -> None: """Displays the album art for the currently playing track in the GraphicsView""" if self.current_song_album_art: @@ -494,6 +457,56 @@ class MainWindow(QMainWindow, Ui_MainWindow): except Exception as e: print(f"Error processing {file}: {e}") + def play_audio_file(self) -> None: + """Start playback of tableView.current_song_filepath track & moves playback slider""" + self.current_song_metadata = self.tableView.get_current_song_metadata() + self.current_song_album_art = self.tableView.get_current_song_album_art() + # read the file + url = QUrl.fromLocalFile(self.tableView.get_current_song_filepath()) + content = QMediaContent(url) # load the audio content + self.player.setMedia(content) # what content to play + self.player.play() # play + self.move_slider() # mover + + # assign metadata + artist = ( + self.current_song_metadata["TPE1"][0] + if "artist" in self.current_song_metadata + else None + ) + album = ( + self.current_song_metadata["TALB"][0] + if "album" in self.current_song_metadata + else None + ) + title = self.current_song_metadata["TIT2"][0] + # edit labels + self.artistLabel.setText(artist) + self.albumLabel.setText(album) + self.titleLabel.setText(title) + # set album artwork + self.load_album_art(self.current_song_album_art) + + def on_play_clicked(self) -> None: + """Updates the Play & Pause buttons when clicked""" + if self.player.state() == QMediaPlayer.State.PlayingState: + self.player.pause() + self.playButton.setText("▶️") + else: + if self.player.state() == QMediaPlayer.State.PausedState: + self.player.play() + self.playButton.setText("⏸️") + else: + self.play_audio_file() + self.playButton.setText("⏸️") + + def on_previous_clicked(self) -> None: + """""" + print("previous") + + def on_next_clicked(self) -> None: + print("next") + def update_audio_visualization(self) -> None: """Handles upading points on the pyqtgraph visual""" self.clear_audio_visualization() @@ -535,26 +548,6 @@ class MainWindow(QMainWindow, Ui_MainWindow): except Exception as e: print(f"Changing volume error: {e}") - def on_play_clicked(self) -> None: - """Updates the Play & Pause buttons when clicked""" - if self.player.state() == QMediaPlayer.State.PlayingState: - self.player.pause() - self.playButton.setText("▶️") - else: - if self.player.state() == QMediaPlayer.State.PausedState: - self.player.play() - self.playButton.setText("⏸️") - else: - self.play_audio_file() - self.playButton.setText("⏸️") - - def on_previous_clicked(self) -> None: - """""" - print("previous") - - def on_next_clicked(self) -> None: - print("next") - def open_files(self) -> None: """Opens the open files window""" open_files_window = QFileDialog( diff --git a/utils/__init__.py b/utils/__init__.py index 3f0a03f..39387ec 100644 --- a/utils/__init__.py +++ b/utils/__init__.py @@ -1,3 +1,4 @@ +from .fft_analyser import FFTAnalyser from .id3_timestamp_to_datetime import id3_timestamp_to_datetime from .initialize_db import initialize_db from .safe_get import safe_get @@ -7,6 +8,5 @@ from .set_id3_tag import set_id3_tag from .delete_and_create_library_database import delete_and_create_library_database from .update_song_in_library import update_song_in_library from .scan_for_music import scan_for_music -from .fft_analyser import FFTAnalyser from .add_files_to_library import add_files_to_library from .handle_year_and_date_id3_tag import handle_year_and_date_id3_tag diff --git a/utils/fft_analyser.py b/utils/fft_analyser.py index ab024eb..f16dfcb 100644 --- a/utils/fft_analyser.py +++ b/utils/fft_analyser.py @@ -1,14 +1,9 @@ # Credit # https://github.com/ravenkls/MilkPlayer/blob/master/audio/fft_analyser.py -# std import time import os - -# qt from PyQt5 import QtCore - -# other from pydub import AudioSegment import numpy as np from scipy.ndimage.filters import gaussian_filter1d diff --git a/utils/set_id3_tag.py b/utils/set_id3_tag.py index 7a0bb0b..a744a8e 100644 --- a/utils/set_id3_tag.py +++ b/utils/set_id3_tag.py @@ -1,5 +1,5 @@ import logging -from components.ErrorDialog import ErrorDialog +from components import ErrorDialog from utils.handle_year_and_date_id3_tag import handle_year_and_date_id3_tag from mutagen.id3 import ID3 from mutagen.id3._util import ID3NoHeaderError