Files
Artemis/audio_player.py
alessandro90 43a9ce954e Add docstrings. Also add safe_cast function. Finally
fix some minor issues.
2019-05-25 15:18:06 +02:00

149 lines
5.1 KiB
Python

import os
from pydub import AudioSegment
from pygame import mixer
from PyQt5.QtCore import QTimer, pyqtSlot, QObject
from constants import Constants
import qtawesome as qta
class AudioPlayer(QObject):
"""Subclass QObject. Audio player widget for the audio samples.
The only public methods are the __init__
method, set_audio_player, which loads the current file and refresh_btns_colors.
Everything else is managed internally."""
__time_step = 500 # Milliseconds.
def __init__(self, play,
pause,
stop,
volume,
audio_progress,
active_color,
inactive_color):
"""Initialize the player."""
super().__init__()
self.__paused = False
self.__first_call = True
self.__play = play
self.__pause = pause
self.__stop = stop
self.__volume = volume
self.__audio_progress = audio_progress
self.__audio_file = None
self.__timer = QTimer()
self.__timer.timeout.connect(self.__update_bar)
self.__play.clicked.connect(self.__play_audio)
self.__pause.clicked.connect(self.__pause_audio)
self.__stop.clicked.connect(self.__stop_audio)
self.__volume.valueChanged.connect(self.__set_volume)
self.__play.setIconSize(self.__play.size())
self.__pause.setIconSize(self.__pause.size())
self.__stop.setIconSize(self.__stop.size())
self.refresh_btns_colors(active_color, inactive_color)
def refresh_btns_colors(self, active_color, inactive_color):
"""Repaint the buttons of the widgetd after the theme has changed."""
self.__play.setIcon(qta.icon('fa5.play-circle',
color=active_color,
color_disabled=inactive_color))
self.__pause.setIcon(qta.icon('fa5.pause-circle',
color=active_color,
color_disabled=inactive_color))
self.__stop.setIcon(qta.icon('fa5.stop-circle',
color=active_color,
color_disabled=inactive_color))
@pyqtSlot()
def __set_volume(self):
"""Set the volume of the audio samples."""
if mixer.get_init():
mixer.music.set_volume(
self.__volume.value() / self.__volume.maximum()
)
def __reset_audio_widget(self):
"""Reset the widget. Stop all playing samples."""
if mixer.get_init():
if mixer.music.get_busy():
mixer.music.stop()
self.__timer.stop()
mixer.quit()
self.__audio_progress.reset()
self.__enable_buttons(False, False, False)
self.__paused = False
@pyqtSlot()
def __update_bar(self):
"""Upadte the progress bar."""
pos = mixer.music.get_pos()
if pos == -1:
self.__timer.stop()
self.__audio_progress.reset()
self.__enable_buttons(True, False, False)
else:
self.__audio_progress.setValue(pos)
def __set_max_progress_bar(self):
"""Set the maximum value of the progress bar."""
self.__audio_progress.setMaximum(
mixer.Sound(self.__audio_file).get_length() * 1000
)
def set_audio_player(self, fname=""):
"""Set the current audio sample."""
self.__first_call = True
self.__reset_audio_widget()
full_name = os.path.join(
Constants.DATA_FOLDER,
Constants.AUDIO_FOLDER,
fname + '.ogg'
)
if os.path.exists(full_name):
self.__play.setEnabled(True)
self.__audio_file = full_name
@pyqtSlot()
def __play_audio(self):
"""Play the audio sample."""
if not self.__paused:
if self.__first_call:
self.__first_call = False
mixer.init(frequency=AudioSegment.from_ogg(
self.__audio_file
).frame_rate,
buffer=2048)
mixer.music.load(self.__audio_file)
self.__set_volume()
self.__set_max_progress_bar()
mixer.music.play()
else:
mixer.music.unpause()
self.__paused = False
self.__timer.start(self.__time_step)
self.__enable_buttons(False, True, True)
@pyqtSlot()
def __stop_audio(self):
"""Stop the audio sample."""
mixer.music.stop()
self.__audio_progress.reset()
self.__timer.stop()
self.__enable_buttons(True, False, False)
@pyqtSlot()
def __pause_audio(self):
"""Pause the audio sample."""
mixer.music.pause()
self.__timer.stop()
self.__paused = True
self.__enable_buttons(True, False, False)
def __enable_buttons(self, play_en, pause_en, stop_en):
"""Set the three buttons status."""
self.__play.setEnabled(play_en)
self.__pause.setEnabled(pause_en)
self.__stop.setEnabled(stop_en)