musicpom/main.py
2024-01-19 20:55:09 -05:00

171 lines
7.1 KiB
Python

import DBA
from ui import Ui_MainWindow
from PyQt5.QtWidgets import QMainWindow, QApplication
import qdarktheme
from PyQt5.QtCore import QUrl, QTimer, QFile, QTextStream
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent, QAudioProbe
from PyQt5.QtGui import QStandardItem, QStandardItemModel
from utils import scan_for_music
from utils import initialize_library_database
from utils import AudioVisualizer
from pyqtgraph import mkBrush
from components import MusicTable
class ApplicationWindow(QMainWindow, Ui_MainWindow):
def __init__(self, qapp):
super(ApplicationWindow, self).__init__()
self.setupUi(self)
self.setWindowTitle('MusicPom')
self.selected_song_filepath = None
self.current_song_filepath = None
self.current_song_metadata = None
self.qapp = qapp
print(f'ApplicationWindow self.qapp: {self.qapp}')
self.tableView.load_qapp(self.qapp)
global stopped
stopped = False
# Initialization
self.player = QMediaPlayer() # Audio player
self.probe = QAudioProbe() # Get audio data
self.timer = QTimer(self) # Audio timing things
# self.model = QStandardItemModel() # Table library listing
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.setSource(self.player)
self.probe.audioBufferProbed.connect(self.process_probe)
# Slider Timer (realtime playback feedback horizontal bar)
self.timer.start(150) # 150ms update interval solved problem with drag seeking halting playback
self.timer.timeout.connect(self.move_slider)
# Graphics plot
self.PlotWidget.setXRange(0,100,padding=0) # x axis range
self.PlotWidget.setYRange(0,0.3,padding=0) # y axis range
self.PlotWidget.getAxis('bottom').setTicks([]) # Remove x-axis ticks
self.PlotWidget.getAxis('bottom').setLabel('') # Remove x-axis label
self.PlotWidget.setLogMode(False,False)
# Remove y-axis labels and decorations
self.PlotWidget.getAxis('left').setTicks([]) # Remove y-axis ticks
self.PlotWidget.getAxis('left').setLabel('') # Remove y-axis label
# Connections
# ! 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(lambda: self.player.setPosition(self.playbackSlider.value())) # Move slidet to adjust playback time
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.pauseButton.clicked.connect(self.on_pause_clicked)
self.previousButton.clicked.connect(self.on_previous_clicked) # Click to previous song
self.nextButton.clicked.connect(self.on_next_clicked) # Click to next song
# self.tableView.clicked.connect(self.set_clicked_cell_filepath)
self.actionPreferences.triggered.connect(self.actionPreferencesClicked) # Open preferences menu
self.actionScanLibraries.triggered.connect(self.scan_libraries) # Scan library
self.actionClearDatabase.triggered.connect(initialize_library_database) # Clear database
self.tableView.doubleClicked.connect(self.play_audio_file) # Double click to play song
def play_audio_file(self):
"""Start playback of selected track & moves playback slider"""
self.current_song_metadata = self.tableView.get_current_song_metadata() # get metadata
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
# FIXME when i change tinytag to something else
artist = self.current_song_metadata.artist
album = self.current_song_metadata.album
title = self.current_song_metadata.title
# edit labels
self.artistLabel.setText(artist)
self.albumLabel.setText(album)
self.titleLabel.setText(title)
def update_audio_visualization(self):
"""Handles upading points on the pyqtgraph visual"""
self.clear_audio_visualization()
self.y = self.audio_visualizer.get_amplitudes()
self.x = [i for i in range(len(self.y))]
self.PlotWidget.plot(self.x, self.y, fillLevel=0, fillBrush=mkBrush('b'))
self.PlotWidget.show()
def clear_audio_visualization(self):
self.PlotWidget.clear()
def move_slider(self):
"""Handles moving the playback slider"""
if stopped:
return
else:
# Update the slider
if self.player.state() == QMediaPlayer.PlayingState:
self.playbackSlider.setMinimum(0)
self.playbackSlider.setMaximum(self.player.duration())
slider_position = self.player.position()
self.playbackSlider.setValue(slider_position)
current_minutes, current_seconds = divmod(slider_position / 1000, 60)
duration_minutes, duration_seconds = divmod(self.player.duration() / 1000, 60)
self.startTimeLabel.setText(f"{int(current_minutes):02d}:{int(current_seconds):02d}")
self.endTimeLabel.setText(f"{int(duration_minutes):02d}:{int(duration_seconds):02d}")
def volume_changed(self):
"""Handles volume changes"""
try:
self.current_volume = self.volumeSlider.value()
self.player.setVolume(self.current_volume)
except Exception as e:
print(f"Changing volume error: {e}")
def on_play_clicked(self):
"""Updates the Play & Pause buttons when clicked"""
if self.player.state() == QMediaPlayer.PlayingState:
self.player.pause()
self.playButton.setText("▶️")
else:
if self.player.state() == QMediaPlayer.PausedState:
self.player.play()
self.playButton.setText("⏸️")
else:
self.play_audio_file()
self.playButton.setText("⏸️")
def on_previous_clicked(self):
""""""
print('previous')
def on_next_clicked(self):
print('next')
def actionPreferencesClicked(self):
print('preferences')
def scan_libraries(self):
scan_for_music()
# refresh datatable
def process_probe(self, buff):
buff.startTime()
self.update_audio_visualization()
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
print(f'main.py app: {app}')
qdarktheme.setup_theme()
ui = ApplicationWindow(app)
ui.show()
sys.exit(app.exec_())