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_())