137 lines
4.4 KiB
Python
137 lines
4.4 KiB
Python
import os
|
|
import subprocess
|
|
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QPushButton, QLabel, QFileDialog, QSlider, QListWidget
|
|
from PyQt6.QtCore import Qt, QUrl
|
|
from PyQt6.QtMultimedia import QMediaPlayer, QAudioOutput
|
|
|
|
DEFAULT_SOUNDFONT = '/home/stan/Documents/Dev/Tests/MidPlay/SoundFonts/FinalFantasyVI.sf2'
|
|
|
|
class MidPlay(QWidget):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.current_file = None
|
|
self.current_soundfont = DEFAULT_SOUNDFONT
|
|
self.process = None
|
|
self.media_player = QMediaPlayer()
|
|
self.audio_output = QAudioOutput()
|
|
self.media_player.setAudioOutput(self.audio_output)
|
|
self.playlist = []
|
|
self.current_index = 0
|
|
self.current_volume = 50
|
|
self.init_ui()
|
|
|
|
def init_ui(self):
|
|
layout = QVBoxLayout()
|
|
|
|
self.playlist_widget = QListWidget()
|
|
self.playlist_widget.itemDoubleClicked.connect(self.play_selected)
|
|
layout.addWidget(self.playlist_widget)
|
|
|
|
self.play_button = QPushButton("Play")
|
|
self.play_button.clicked.connect(self.play)
|
|
layout.addWidget(self.play_button)
|
|
|
|
self.stop_button = QPushButton("Stop")
|
|
self.stop_button.clicked.connect(self.stop)
|
|
layout.addWidget(self.stop_button)
|
|
|
|
self.next_button = QPushButton("Next")
|
|
self.next_button.clicked.connect(self.play_next)
|
|
layout.addWidget(self.next_button)
|
|
|
|
self.volume_slider = QSlider(Qt.Orientation.Horizontal)
|
|
self.volume_slider.setRange(0, 100)
|
|
self.volume_slider.setValue(self.current_volume)
|
|
self.volume_slider.valueChanged.connect(self.set_volume)
|
|
layout.addWidget(self.volume_slider)
|
|
|
|
self.status_label = QLabel("No file loaded")
|
|
layout.addWidget(self.status_label)
|
|
|
|
self.setLayout(layout)
|
|
|
|
def add_to_playlist(self, file_path):
|
|
self.playlist.append(file_path)
|
|
self.playlist_widget.addItem(os.path.basename(file_path))
|
|
if not self.current_file:
|
|
self.current_file = file_path
|
|
self.play()
|
|
|
|
def play_selected(self, item):
|
|
index = self.playlist_widget.row(item)
|
|
self.current_index = index
|
|
self.current_file = self.playlist[index]
|
|
self.play()
|
|
|
|
def play(self):
|
|
if not self.current_file:
|
|
self.status_label.setText("No file selected")
|
|
return
|
|
|
|
self.stop() # Stop any current playback
|
|
|
|
if self.current_file.lower().endswith(('.mid', '.midi')):
|
|
self.play_midi()
|
|
else:
|
|
self.play_audio()
|
|
|
|
def play_midi(self):
|
|
self.media_player.stop()
|
|
command = [
|
|
"fluidsynth",
|
|
"-a", "pulseaudio",
|
|
"-g", str(self.current_volume / 50),
|
|
self.current_soundfont,
|
|
self.current_file
|
|
]
|
|
self.process = subprocess.Popen(command)
|
|
self.status_label.setText(f"Playing MIDI: {os.path.basename(self.current_file)}")
|
|
|
|
def play_audio(self):
|
|
if self.process:
|
|
self.process.terminate()
|
|
self.process = None
|
|
|
|
self.media_player.setSource(QUrl.fromLocalFile(self.current_file))
|
|
self.media_player.play()
|
|
self.status_label.setText(f"Playing Audio: {os.path.basename(self.current_file)}")
|
|
self.media_player.mediaStatusChanged.connect(self.handle_media_status_change)
|
|
|
|
def stop(self):
|
|
if self.process:
|
|
self.process.terminate()
|
|
self.process = None
|
|
self.media_player.stop()
|
|
self.status_label.setText("Playback stopped")
|
|
|
|
def set_volume(self, value):
|
|
self.current_volume = value
|
|
self.audio_output.setVolume(value / 50)
|
|
if self.process and self.current_file.lower().endswith(('.mid', '.midi')):
|
|
self.update_midi_volume()
|
|
|
|
def update_midi_volume(self):
|
|
pass
|
|
|
|
def play_next(self):
|
|
if self.playlist:
|
|
self.current_index = (self.current_index + 1) % len(self.playlist)
|
|
self.current_file = self.playlist[self.current_index]
|
|
self.play()
|
|
|
|
def handle_media_status_change(self, status):
|
|
if status == QMediaPlayer.MediaStatus.EndOfMedia:
|
|
self.play_next()
|
|
|
|
def closeEvent(self, event):
|
|
self.stop()
|
|
super().closeEvent(event)
|
|
|
|
def showUI(self):
|
|
self.setWindowTitle("MidPlay")
|
|
super().show()
|
|
|
|
def close(self):
|
|
self.stop()
|
|
super().close()
|