- Replace the Python/Docker setup with a Rust workspace and Tauri frontend - Add core crates for archive, audio, MIDI, plugin, and desktop UI layers - Refresh the app scaffolding, build config, and documentation
216 lines
9.1 KiB
Python
216 lines
9.1 KiB
Python
# Path: Fbrowser.py
|
|
# Sample Music Browser & Ogranizer: Main.py
|
|
|
|
# Importing Libraries
|
|
import sys
|
|
import os
|
|
from ScanOrg import organizer, file_scanner, DirectoryFilterProxyModel, FileFilterProxyModel
|
|
|
|
from PyQt5.QtGui import QStandardItem , QStandardItemModel
|
|
from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QTreeView, QMessageBox, QSlider, QWidget, QFileSystemModel, QSplitter, QHBoxLayout, QFileDialog
|
|
from PyQt5.QtMultimedia import QMediaPlaylist, QMediaPlayer, QMediaContent, QAudioFormat, QAudioDeviceInfo, QAudio
|
|
from PyQt5.QtCore import QDir, QSortFilterProxyModel, Qt, QUrl #QAbstractItemModel, QAbstractProxyModel, QModelIndex, QItemSelectionModel, QItemSelection, QItemSelectionRange, QItemSelectionModel, QItemSelection, QItemSelectionRange
|
|
|
|
|
|
"""
|
|
# Audio Format
|
|
audio_format = QAudioFormat()
|
|
audio_format.setSampleRate(44100)
|
|
audio_format.setChannelCount(2)
|
|
audio_format.setSampleSize(16)
|
|
audio_format.setCodec('audio/pcm')
|
|
audio_format.setByteOrder(QAudioFormat.LittleEndian)
|
|
audio_format.setSampleType(QAudioFormat.SignedInt)
|
|
# Audio Device Info
|
|
device_info = QAudioDeviceInfo.defaultOutputDevice()
|
|
if not device_info.isFormatSupported(audio_format):
|
|
print('Raw audio format not supported by backend, cannot play audio.')
|
|
audio_format = device_info.nearestFormat(audio_format)
|
|
|
|
"""
|
|
|
|
|
|
# Sample Music Browser Main Class
|
|
class SampleMusicBrowser(QWidget):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.organizer = organizer()
|
|
self.file_model = QStandardItemModel()
|
|
self.player = QMediaPlayer()
|
|
self.playlist = QMediaPlaylist()
|
|
self.player.setPlaylist(self.playlist)
|
|
self.tree_model = QFileSystemModel()
|
|
|
|
self.init_ui()
|
|
|
|
self.folder_contents_view.setEditTriggers(QTreeView.NoEditTriggers)
|
|
self.player.error.connect(self.player_error)
|
|
self.player.mediaStatusChanged.connect(self.player_media_status_changed)
|
|
self.player.setAudioRole(QAudio.MusicRole)
|
|
|
|
def player_error(self, error):
|
|
if error == QMediaPlayer.NoError:
|
|
return
|
|
print('Error: ' + self.player.errorString())
|
|
|
|
def player_media_status_changed(self, status):
|
|
if status == QMediaPlayer.NoMedia:
|
|
return
|
|
print('Media Status: ' + str(status))
|
|
|
|
def init_ui(self):
|
|
layout = QHBoxLayout()
|
|
label = QLabel('Sample Music Browser')
|
|
layout.addWidget(label)
|
|
button = QPushButton('Exit')
|
|
button.clicked.connect(self.show_exit_popup)
|
|
layout.addWidget(button)
|
|
self.file_tree = QTreeView()
|
|
self.file_tree.setHeaderHidden(True)
|
|
self.file_tree.clicked.connect(self.change_directory)
|
|
self.folder_contents_view = QTreeView()
|
|
self.folder_contents_view.setHeaderHidden(False)
|
|
self.folder_contents_view.setRootIsDecorated(False)
|
|
self.folder_contents_view.setSortingEnabled(True)
|
|
splitter = QSplitter()
|
|
splitter.addWidget(self.file_tree)
|
|
splitter.addWidget(self.folder_contents_view)
|
|
layout.addWidget(splitter)
|
|
self.current_dir_label = QLabel()
|
|
layout.addWidget(self.current_dir_label)
|
|
up_dir_button = QPushButton('Up Directory')
|
|
up_dir_button.clicked.connect(self.go_up_directory)
|
|
layout.addWidget(up_dir_button)
|
|
back_button = QPushButton('Back')
|
|
back_button.clicked.connect(self.go_back_directory)
|
|
layout.addWidget(back_button)
|
|
forward_button = QPushButton('Forward')
|
|
forward_button.clicked.connect(self.go_forward_directory)
|
|
layout.addWidget(forward_button)
|
|
self.setLayout(layout)
|
|
self.setWindowTitle('Samples are life!')
|
|
path = QFileDialog.getExistingDirectory(self, 'Select Directory')
|
|
if path:
|
|
self.populate_file_tree(path)
|
|
play_button = QPushButton('Play')
|
|
play_button.clicked.connect(self.player.play)
|
|
layout.addWidget(play_button)
|
|
pause_button = QPushButton('Pause')
|
|
pause_button.clicked.connect(self.player.pause)
|
|
layout.addWidget(pause_button)
|
|
stop_button = QPushButton('Stop')
|
|
stop_button.clicked.connect(self.player.stop)
|
|
layout.addWidget(stop_button)
|
|
self.player.stateChanged.connect(self.player_state_changed)
|
|
self.player.positionChanged.connect(self.player_position_changed)
|
|
self.player.durationChanged.connect(self.player_duration_changed)
|
|
self.player.setVolume(50)
|
|
volume_slider = QSlider(Qt.Horizontal)
|
|
volume_slider.setRange(0, 100)
|
|
volume_slider.setValue(50)
|
|
volume_slider.valueChanged.connect(self.player.setVolume)
|
|
layout.addWidget(volume_slider)
|
|
self.playlist.currentIndexChanged.connect(self.playlist_current_index_changed)
|
|
self.playlist.currentMediaChanged.connect(self.playlist_current_media_changed)
|
|
self.playlist.mediaInserted.connect(self.playlist_media_inserted)
|
|
self.playlist.mediaRemoved.connect(self.playlist_media_removed)
|
|
self.playlist.setPlaybackMode(QMediaPlaylist.Loop)
|
|
self.folder_contents_view.doubleClicked.connect(self.play_file)
|
|
|
|
def directory_loaded(self, path):
|
|
self.file_tree.setRootIndex(self.directory_model.mapFromSource(self.model.index(path)))
|
|
self.folder_contents_view.setRootIndex(self.file_filter_model.mapFromSource(self.list_model.index(path)))
|
|
|
|
def populate_file_tree(self, path):
|
|
try:
|
|
self.tree_model.setRootPath(path)
|
|
self.file_tree.setModel(self.tree_model)
|
|
self.directory_model = DirectoryFilterProxyModel()
|
|
self.directory_model.setSourceModel(self.tree_model)
|
|
self.file_tree.setModel(self.directory_model)
|
|
self.file_tree.setRootIndex(self.directory_model.mapFromSource(self.tree_model.index(path)))
|
|
self.list_model = QFileSystemModel()
|
|
self.list_model.setRootPath(path)
|
|
self.file_filter_model = FileFilterProxyModel()
|
|
self.file_filter_model.setSourceModel(self.list_model)
|
|
self.folder_contents_view.setModel(self.file_filter_model)
|
|
self.folder_contents_view.setRootIndex(self.file_filter_model.mapFromSource(self.list_model.index(path)))
|
|
self.current_dir_label.setText(path)
|
|
except Exception as e:
|
|
print(f"Error Populating File Tree: {e}")
|
|
|
|
|
|
def show_exit_popup(self):
|
|
reply = QMessageBox.question(self, 'Exit', 'Are you sure you want to exit?',
|
|
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
|
|
if reply == QMessageBox.Yes:
|
|
sys.exit()
|
|
|
|
def play_file(self, index):
|
|
index = self.file_filter_model.mapToSource(index)
|
|
file_path = self.list_model.filePath(index)
|
|
media = QMediaContent(QUrl.fromLocalFile(file_path))
|
|
self.playlist.addMedia(media)
|
|
self.player.play()
|
|
|
|
def player_state_changed(self, state):
|
|
if state == QMediaPlayer.StoppedState:
|
|
self.playlist.setCurrentIndex(0)
|
|
|
|
def player_position_changed(self, position):
|
|
pass
|
|
def player_duration_changed(self, duration):
|
|
pass
|
|
def playlist_current_index_changed(self, index):
|
|
pass
|
|
def playlist_current_media_changed(self, media):
|
|
pass
|
|
def playlist_media_inserted(self, start, end):
|
|
pass
|
|
def playlist_media_removed(self, start, end):
|
|
pass
|
|
|
|
def change_directory(self, index):
|
|
index = self.directory_model.mapToSource(index)
|
|
try:
|
|
file_path = self.tree_model.filePath(index)
|
|
self.list_model.setRootPath(file_path)
|
|
self.current_dir_label.setText(file_path)
|
|
self.folder_contents_view.setRootIndex(self.file_filter_model.mapFromSource(self.list_model.index(file_path)))
|
|
except Exception as e:
|
|
print(f"Error Changing Dirs.: {e}")
|
|
|
|
def go_up_directory(self):
|
|
index = self.folder_contents_view.rootIndex()
|
|
index = self.file_filter_model.mapToSource(index)
|
|
index = self.file_model.index(index)
|
|
index = index.parent()
|
|
index = self.file_filter_model.mapFromSource(index)
|
|
self.folder_contents_view.setRootIndex(index)
|
|
self.current_dir_label.setText(self.model.filePath(index))
|
|
|
|
def go_back_directory(self):
|
|
index = self.folder_contents_view.rootIndex()
|
|
index = self.file_filter_model.mapToSource(index)
|
|
index = self.file_model.index(index)
|
|
index = index.parent()
|
|
index = self.file_filter_model.mapFromSource(index)
|
|
self.folder_contents_view.setRootIndex(index)
|
|
self.current_dir_label.setText(self.model.filePath(index))
|
|
|
|
def go_forward_directory(self):
|
|
index = self.folder_contents_view.rootIndex()
|
|
index = self.file_filter_model.mapToSource(index)
|
|
index = self.file_model.index(index)
|
|
index = index.parent()
|
|
index = self.file_filter_model.mapFromSource(index)
|
|
self.folder_contents_view.setRootIndex(index)
|
|
self.current_dir_label.setText(self.model.filePath(index))
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
app = QApplication(sys.argv)
|
|
sampleMusicBrowser = SampleMusicBrowser()
|
|
sampleMusicBrowser.show()
|
|
sys.exit(app.exec_()) |