Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions PP_lab5/annotation.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
relative_path,absolute_path
sounds\Bueno.mp3,D:\Учеба\Лабы\ПП\PP_lab5\sounds\Bueno.mp3
sounds\Короткая музыкальная отбивка.mp3,D:\Учеба\Лабы\ПП\PP_lab5\sounds\Короткая музыкальная отбивка.mp3
sounds\Может вам подойдет такое.mp3,D:\Учеба\Лабы\ПП\PP_lab5\sounds\Может вам подойдет такое.mp3
"sounds\Музыка для Сна, Музыка для Релаксации - Кузнечики (zaycev.net).mp3","D:\Учеба\Лабы\ПП\PP_lab5\sounds\Музыка для Сна, Музыка для Релаксации - Кузнечики (zaycev.net).mp3"
sounds\Музыкальная отбивка для перехода между сценами.mp3,D:\Учеба\Лабы\ПП\PP_lab5\sounds\Музыкальная отбивка для перехода между сценами.mp3
sounds\Рассказ истории.mp3,D:\Учеба\Лабы\ПП\PP_lab5\sounds\Рассказ истории.mp3
134 changes: 134 additions & 0 deletions PP_lab5/main_window.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import os
import sys
from pathlib import Path
pyqt_path = Path(sys.executable).parent / "Lib/site-packages/PyQt5/Qt"
os.environ["QT_QPA_PLATFORM_PLUGIN_PATH"] = str(pyqt_path / "plugins")
os.environ["QT_PLUGIN_PATH"] = str(pyqt_path / "plugins")
from PyQt5.QtWidgets import (
QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
QPushButton, QLabel, QFileDialog, QMessageBox
)
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
from PyQt5.QtCore import QUrl, Qt
from sound_iterator import SoundPathIterator


class AudioPlayerWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Аудиоплеер — Лабораторная №5")
self.setGeometry(200, 200, 600, 300)

self.iterator = None
self.current_media = None
self.player = QMediaPlayer()
self.player.mediaStatusChanged.connect(self.on_media_status_changed)

self.label_title = QLabel("Название: —")
self.label_duration = QLabel("Длительность: —")
self.btn_load = QPushButton("Загрузить аннотацию (CSV)")
self.btn_next = QPushButton("Следующий аудиофайл")
self.btn_play = QPushButton("Воспроизвести")

self.btn_next.setEnabled(False)
self.btn_play.setEnabled(False)

self.btn_load.clicked.connect(self.load_annotation)
self.btn_next.clicked.connect(self.next_audio)
self.btn_play.clicked.connect(self.toggle_playback)

central_widget = QWidget()
layout = QVBoxLayout()

layout.addWidget(self.label_title)
layout.addWidget(self.label_duration)
layout.addWidget(self.btn_load)

button_layout = QHBoxLayout()
button_layout.addWidget(self.btn_next)
button_layout.addWidget(self.btn_play)
layout.addLayout(button_layout)

central_widget.setLayout(layout)
self.setCentralWidget(central_widget)

def load_annotation(self):
file_path, _ = QFileDialog.getOpenFileName(
self, "Выберите CSV-файл аннотации", "", "CSV Files (*.csv)"
)
if file_path:
try:
self.iterator = iter(SoundPathIterator(file_path))
self.btn_next.setEnabled(True)
self.label_title.setText("Название: готово к воспроизведению")
self.label_duration.setText("Длительность: —")
except Exception as e:
QMessageBox.critical(self, "Ошибка", f"Не удалось загрузить аннотацию:\n{e}")

def next_audio(self):
if self.iterator is None:
return

try:
self.player.stop()

audio_path = next(self.iterator)
if not os.path.exists(audio_path):
raise FileNotFoundError(f"Файл не найден: {audio_path}")

filename = os.path.basename(audio_path)
self.label_title.setText(f"Название: {filename}")

self.current_media = QMediaContent(QUrl.fromLocalFile(audio_path))
self.player.setMedia(self.current_media)

self.label_duration.setText("Длительность: загрузка...")
self.player.durationChanged.connect(self.update_duration)

self.btn_play.setEnabled(True)
self.btn_play.setText("Воспроизвести")

except StopIteration:
QMessageBox.information(self, "Конец", "Больше аудиофайлов в аннотации нет.")
self.btn_next.setEnabled(False)
except Exception as e:
QMessageBox.critical(self, "Ошибка", f"Не удалось загрузить аудиофайл:\n{e}")

def update_duration(self, duration_ms: int):
if duration_ms > 0:
seconds = duration_ms // 1000
minutes = seconds // 60
seconds = seconds % 60
self.label_duration.setText(f"Длительность: {minutes}:{seconds:02d}")
else:
self.label_duration.setText("Длительность: неизвестна")

def toggle_playback(self):
if self.player.state() == QMediaPlayer.PlayingState:
self.player.pause()
self.btn_play.setText("Воспроизвести")
else:
self.player.play()
self.btn_play.setText("Пауза")

def on_media_status_changed(self, status):
# Опционально: обработка ошибок загрузки
if status == self.player.InvalidMedia:
self.label_duration.setText("Длительность: ошибка загрузки")

def closeEvent(self, event):
self.player.stop()
if hasattr(self.iterator, '_file') and self.iterator._file:
self.iterator._file.close()
event.accept()


def main():
app = QApplication(sys.argv)
window = AudioPlayerWindow()
window.show()
sys.exit(app.exec_())


if __name__ == "__main__":
main()
25 changes: 25 additions & 0 deletions PP_lab5/sound_iterator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import csv

class SoundPathIterator:
def __init__(self, csv_path: str):
self.csv_path = csv_path
self._file = None
self._reader = None

def __iter__(self):
self._file = open(self.csv_path, mode='r', encoding='utf-8', newline='')
self._reader = csv.reader(self._file)
next(self._reader, None)
return self

def __next__(self):
try:
row = next(self._reader)
if len(row) >= 2:
return row[1]
else:
raise StopIteration
except StopIteration:
if self._file:
self._file.close()
raise
Binary file added PP_lab5/sounds/Bueno.mp3
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added PP_lab5/sounds/Рассказ истории.mp3
Binary file not shown.