/
op1x
/
MPPlus
Обзор
Документация
Войти
/
op1x
/
MPPlus
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
main.py
314 строк
12 KB
Op1x
финалочка
13 ноя 2025, 01:01
13 ноя 2025, 01:01
aae47e2
Код
Авторство
О чём код?
import sys import random import os from PyQt6.QtGui import QIcon from PyQt6.QtCore import Qt, QUrl from PyQt6.QtWidgets import ( QApplication, QWidget, QFileDialog, QListWidgetItem) from PyQt6.QtMultimedia import QMediaPlayer, QAudioOutput from install_window import InstallWindow from PyQt6 import uic from database import TrackDatabase # ← импортируем из track_db.py, не из себя! class MyWidget(QWidget): def __init__(self, playlist, current_index): super().__init__() self.current_dir = os.path.dirname(os.path.abspath(__file__)) self.db = TrackDatabase(os.path.join(self.current_dir, "tracks.db")) ui_path = os.path.join(self.current_dir, "templates", "design.ui") uic.loadUi(ui_path, self) self.player = QMediaPlayer() self.audio_output = QAudioOutput() self.player.setAudioOutput(self.audio_output) self._is_seeking = False self.playlist = [] self.current_index = 0 self.is_replay = False self.is_shuffle = False # Подключаем сигналы self.like_button.clicked.connect(self.like_track) self.loadtracks_button.clicked.connect(self.open_folder) self.install_button.clicked.connect(self.open_install_window) self.pause_button.clicked.connect(self.toggle_play) self.previoustrack_button.clicked.connect(self.prev_track) self.nexttrack_button.clicked.connect(self.next_track) self.repeat_button.clicked.connect(self.toggle_replay) self.random_button.clicked.connect(self.toggle_shuffle) self.tracktime_slider.sliderPressed.connect(self.on_slider_pressed) self.tracktime_slider.sliderReleased.connect(self.on_slider_released) self.tracktime_slider.sliderMoved.connect(self.on_slider_moved) self.volume_slider.valueChanged.connect(self.on_volume_changed) self.player.positionChanged.connect(self.on_position_changed) self.player.durationChanged.connect(self.on_duration_changed) self.player.mediaStatusChanged.connect(self.on_media_status_changed) self.albumsList.itemClicked.connect(self.on_album_clicked) self.tracktime_slider.setRange(0, 0) self.volume_slider.setRange(0, 100) self.volume_slider.setValue(80) self.volume_slider.setMinimumWidth(150) self.audio_output.setVolume(0.8) self.queue_list.doubleClicked.connect(self.on_queue_double_clicked) self.setup_icons() self.load_playlists() self.add_favourite_album_item() def setup_icons(self): icons_dir = os.path.join(self.current_dir, "icons") def get_icon(name): path = os.path.join(icons_dir, name) return QIcon(path) if os.path.exists(path) else QIcon() self.pause_button.setIcon(get_icon("white-stop.png")) self.previoustrack_button.setIcon(get_icon("white-previous.png")) self.nexttrack_button.setIcon(get_icon("white-next.png")) self.repeat_button.setIcon(get_icon("white-repeat.png")) self.random_button.setIcon(get_icon("white-shuffle.png")) self.like_button.setIcon(get_icon("white-like.png")) # Убираем текст self.pause_button.setText("") self.previoustrack_button.setText("") self.nexttrack_button.setText("") self.repeat_button.setText("") self.random_button.setText("") self.like_button.setText("") def load_playlists(self): playlists_dir = os.path.join(self.current_dir, "playlists") self.albumsList.clear() for folder_name in os.listdir(playlists_dir): folder_path = os.path.join(playlists_dir, folder_name) if os.path.isdir(folder_path): item = QListWidgetItem(folder_name) item.setData(Qt.ItemDataRole.UserRole, folder_path) self.albumsList.addItem(item) def add_favourite_album_item(self): item = QListWidgetItem("Favourite Tracks") item.setData(Qt.ItemDataRole.UserRole, "FAVOURITE_TRACKS") self.albumsList.insertItem(0, item) def on_album_clicked(self, item): folder_path = item.data(Qt.ItemDataRole.UserRole) if folder_path == "FAVOURITE_TRACKS": liked_tracks = self.db.get_liked_tracks() if not liked_tracks: self.nowplaying_label.setText("Нет лайкнутых треков") self.playlist = [] self.original_playlist = [] # ← сохраняем пустой оригинальный self.update_queue_list() return self.playlist = liked_tracks.copy() # ← копируем self.original_playlist = liked_tracks.copy() # ← сохраняем оригинал if self.is_shuffle: self.shuffle_playlist_except_current() self.current_index = 0 self.update_queue_list() return if os.path.exists(folder_path): track_paths = [ os.path.join(folder_path, f) for f in os.listdir(folder_path) if f.lower().endswith(('.mp3', '.wav', '.ogg', '.flac', '.webm')) ] if not track_paths: self.nowplaying_label.setText("Нет поддерживаемых треков") return self.db.add_tracks(track_paths) self.playlist = track_paths.copy() self.original_playlist = track_paths.copy() # ← сохраняем оригинал if self.is_shuffle: self.shuffle_playlist_except_current() self.current_index = 0 self.update_queue_list() def update_queue_list(self): self.queue_list.clear() for track_path in self.playlist: track_name = os.path.basename(track_path) item = QListWidgetItem(track_name) item.setData(Qt.ItemDataRole.UserRole, track_path) self.queue_list.addItem(item) if 0 <= self.current_index < self.queue_list.count(): self.queue_list.setCurrentRow(self.current_index) def on_queue_double_clicked(self, model_index): index = model_index.row() if 0 <= index < len(self.playlist): self.current_index = index self.load_track() def open_folder(self): folder = QFileDialog.getExistingDirectory(self, "Выберите папку с музыкой") if folder: track_paths = [ os.path.join(folder, f) for f in os.listdir(folder) if f.lower().endswith(('.mp3', '.wav', '.ogg', '.flac', '.webm')) ] if not track_paths: self.nowplaying_label.setText("Нет поддерживаемых треков") return self.db.add_tracks(track_paths) self.playlist = track_paths.copy() self.original_playlist = track_paths.copy() # ← сохраняем оригинал if self.is_shuffle: self.shuffle_playlist_except_current() self.current_index = 0 self.update_queue_list() def open_install_window(self): self.install_window = InstallWindow() self.install_window.show() def load_track(self): if not self.playlist or self.current_index >= len(self.playlist): return track_path = self.playlist[self.current_index] self.player.setSource(QUrl.fromLocalFile(track_path)) self.nowplaying_label.setText(os.path.basename(track_path)) self.player.play() liked = self.db.is_liked(track_path) icons_dir = os.path.join(self.current_dir, "icons") icon_name = "white-like-on.png" if liked else "white-like.png" self.like_button.setIcon(QIcon(os.path.join(icons_dir, icon_name))) def shuffle_playlist_except_current(self): if len(self.playlist) <= 1: return current_track = self.playlist[self.current_index] other_tracks = [t for t in self.playlist if t != current_track] random.shuffle(other_tracks) self.playlist = [current_track] + other_tracks self.update_queue_list() def like_track(self): if not self.playlist or self.current_index >= len(self.playlist): return track_path = self.playlist[self.current_index] new_liked = self.db.toggle_like(track_path) icons_dir = os.path.join(self.current_dir, "icons") icon_name = "white-like-on.png" if new_liked else "white-like.png" self.like_button.setIcon(QIcon(os.path.join(icons_dir, icon_name))) current_item = self.albumsList.currentItem() if current_item and current_item.data(Qt.ItemDataRole.UserRole) == "FAVOURITE_TRACKS": if not new_liked: for i in range(self.queue_list.count()): item = self.queue_list.item(i) if item.data(Qt.ItemDataRole.UserRole) == track_path: self.queue_list.takeItem(i) break else: self.update_queue_list() def toggle_play(self): state = self.player.playbackState() icon_path = "white-play.png" if state == QMediaPlayer.PlaybackState.PlayingState else "white-stop.png" self.pause_button.setIcon(QIcon(os.path.join(self.current_dir, "icons", icon_path))) self.player.play() if state != QMediaPlayer.PlaybackState.PlayingState else self.player.pause() def prev_track(self): if not self.playlist: return self.current_index = (self.current_index - 1) % len(self.playlist) self.load_track() def next_track(self): if not self.playlist: return if self.is_replay: self.player.setPosition(0) else: self.current_index = (self.current_index + 1) % len(self.playlist) self.load_track() def toggle_replay(self): self.is_replay = not self.is_replay icon_path = "white-repeat-on.png" if self.is_replay else "white-repeat.png" self.repeat_button.setIcon(QIcon(os.path.join(self.current_dir, "icons", icon_path))) def toggle_shuffle(self): self.is_shuffle = not self.is_shuffle icon_path = "white-shuffle-on.png" if self.is_shuffle else "white-shuffle.png" self.random_button.setIcon(QIcon(os.path.join(self.current_dir, "icons", icon_path))) if self.is_shuffle and self.playlist: self.shuffle_playlist_except_current() elif not self.is_shuffle and hasattr(self, 'original_playlist') and self.original_playlist: current_track = self.playlist[self.current_index] try: self.current_index = self.original_playlist.index(current_track) except ValueError: self.current_index = 0 self.playlist = self.original_playlist.copy() self.update_queue_list() def on_duration_changed(self, duration): self.tracktime_slider.setRange(0, duration) self.update_time_labels(self.player.position(), duration) def on_position_changed(self, position): if not self._is_seeking: self.tracktime_slider.setValue(position) self.update_time_labels(position, self.player.duration()) def on_media_status_changed(self, status): from PyQt6.QtMultimedia import QMediaPlayer if status == QMediaPlayer.MediaStatus.EndOfMedia: self.next_track() def on_slider_pressed(self): self._is_seeking = True def on_slider_released(self): self._is_seeking = False self.player.setPosition(self.tracktime_slider.value()) def on_slider_moved(self, value): self.update_time_labels(value, self.player.duration()) def on_volume_changed(self, value): self.audio_output.setVolume(value / 100.0) def ms_to_timestamp(self, ms): if ms <= 0: return "00:00" s = ms // 1000 m, s = divmod(s, 60) h, m = divmod(m, 60) return f"{h:02d}:{m:02d}:{s:02d}" if h else f"{m:02d}:{s:02d}" def update_time_labels(self, pos_ms, dur_ms): self.nowtracktime_label.setText(self.ms_to_timestamp(pos_ms)) self.alltracktime_label.setText(self.ms_to_timestamp(dur_ms)) if __name__ == '__main__': app = QApplication(sys.argv) ex = MyWidget(playlist=[], current_index=0) ex.show() sys.exit(app.exec())