2023-07-10 17:04:47 +02:00
|
|
|
# coding=utf-8
|
2023-06-11 22:50:01 +02:00
|
|
|
|
|
|
|
import json
|
2023-07-11 15:29:37 +02:00
|
|
|
|
2023-06-11 22:50:01 +02:00
|
|
|
import requests
|
2023-07-11 15:29:37 +02:00
|
|
|
from PySide6.QtCore import QUrl
|
|
|
|
from PySide6.QtMultimedia import QAudioOutput, QMediaPlayer
|
|
|
|
from PySide6.QtWidgets import QMainWindow, QMessageBox, QStyle
|
|
|
|
|
2023-07-08 20:20:56 +02:00
|
|
|
from . import API_URL, DEFAULT_VOLUME, Ui_MainWindow
|
2023-06-15 00:12:32 +02:00
|
|
|
|
2023-07-16 15:46:55 +02:00
|
|
|
from __feature__ import snake_case, true_property # isort: skip
|
2023-07-16 15:44:47 +02:00
|
|
|
|
2023-06-11 22:50:01 +02:00
|
|
|
|
|
|
|
class MainWindow(QMainWindow):
|
2023-06-15 00:12:32 +02:00
|
|
|
"""MainWindow Class."""
|
|
|
|
|
2023-07-16 15:48:30 +02:00
|
|
|
def __init__(self):
|
2023-06-15 00:12:32 +02:00
|
|
|
"""Initialize UI, audio player and handlers."""
|
2023-07-16 15:48:30 +02:00
|
|
|
super().__init__()
|
2023-06-11 22:50:01 +02:00
|
|
|
self.ui = Ui_MainWindow()
|
|
|
|
self.ui.setupUi(self)
|
2023-07-16 15:44:47 +02:00
|
|
|
volume_icon = self.style().standard_icon(QStyle.SP_MediaVolume)
|
|
|
|
playback_icon = self.style().standard_icon(QStyle.SP_MediaPlay)
|
|
|
|
self.ui.volumeToolButton.icon = volume_icon
|
|
|
|
self.ui.playbackToolButton.icon = playback_icon
|
2023-06-15 00:32:41 +02:00
|
|
|
|
2023-07-16 15:50:43 +02:00
|
|
|
self.__stations_data = self.get_stations_data()
|
2023-06-12 23:16:24 +02:00
|
|
|
self.__player = QMediaPlayer()
|
|
|
|
self.__audio = QAudioOutput()
|
2023-07-16 15:44:47 +02:00
|
|
|
self.__player.audio_output = self.__audio
|
2023-07-16 15:50:43 +02:00
|
|
|
self.print_groups()
|
2023-06-15 00:32:41 +02:00
|
|
|
|
2023-07-16 15:50:43 +02:00
|
|
|
self.set_volume(DEFAULT_VOLUME)
|
2023-07-16 15:44:47 +02:00
|
|
|
self.ui.volumeHorizontalSlider.value = DEFAULT_VOLUME
|
2023-07-11 16:24:53 +02:00
|
|
|
|
2023-07-16 15:50:43 +02:00
|
|
|
self.ui.groupsListWidget.itemClicked.connect(self.print_stations)
|
|
|
|
self.ui.stationsListWidget.itemClicked.connect(self.play_radio)
|
|
|
|
self.ui.playbackToolButton.clicked.connect(self.toggle_player)
|
|
|
|
self.ui.volumeHorizontalSlider.valueChanged.connect(self.set_volume)
|
|
|
|
self.ui.volumeToolButton.clicked.connect(self.toggle_mute)
|
2023-06-11 22:50:01 +02:00
|
|
|
|
2023-07-16 15:50:43 +02:00
|
|
|
def get_stations_data(self) -> dict:
|
2023-06-15 00:12:32 +02:00
|
|
|
"""Get JSON data from API and convert it to dict."""
|
2023-07-11 18:27:45 +02:00
|
|
|
try:
|
|
|
|
resp = requests.get(API_URL)
|
|
|
|
if resp.status_code not in range(200, 299 + 1):
|
|
|
|
raise requests.exceptions.ConnectionError()
|
|
|
|
else:
|
|
|
|
return json.loads(resp.text)
|
|
|
|
except requests.exceptions.ConnectionError:
|
2023-06-14 15:57:46 +02:00
|
|
|
error_box = QMessageBox.critical(
|
2023-06-15 00:12:32 +02:00
|
|
|
self,
|
|
|
|
"Błąd",
|
2023-07-11 18:27:45 +02:00
|
|
|
"Brak połączenia z serwerem.",
|
2023-06-15 00:12:32 +02:00
|
|
|
QMessageBox.Cancel,
|
2023-06-14 15:57:46 +02:00
|
|
|
)
|
|
|
|
error_box.exec()
|
|
|
|
|
2023-07-16 15:50:43 +02:00
|
|
|
def print_groups(self) -> None:
|
2023-06-15 00:12:32 +02:00
|
|
|
"""Print groups (categories) in groupsListWidget."""
|
2023-07-16 15:44:47 +02:00
|
|
|
self.ui.groupsListWidget.add_items(
|
2023-07-10 17:04:47 +02:00
|
|
|
[e["name"] for e in self.__stations_data["groups"]])
|
2023-06-15 00:12:32 +02:00
|
|
|
|
2023-07-16 15:50:43 +02:00
|
|
|
def print_stations(self) -> None:
|
2023-06-15 00:12:32 +02:00
|
|
|
"""Print stations (channels) in stationsListWidget."""
|
2023-07-16 15:44:47 +02:00
|
|
|
group = self.ui.groupsListWidget.selected_items()[0].text()
|
2023-06-15 00:12:32 +02:00
|
|
|
group_id = None
|
|
|
|
for e in self.__stations_data["groups"]:
|
|
|
|
if e["name"] == group:
|
|
|
|
group_id = e["id"]
|
|
|
|
|
|
|
|
self.ui.stationsListWidget.clear()
|
2023-07-16 15:44:47 +02:00
|
|
|
self.ui.stationsListWidget.add_items([
|
2023-07-10 17:04:47 +02:00
|
|
|
e["name"] for e in self.__stations_data["channels"]
|
|
|
|
if e["group_id"] == group_id
|
|
|
|
])
|
2023-06-15 00:12:32 +02:00
|
|
|
|
2023-07-16 15:50:43 +02:00
|
|
|
def set_volume(self, volume: int = None) -> None:
|
2023-06-15 00:12:32 +02:00
|
|
|
"""Set playback volume to given number or slider value."""
|
|
|
|
if not volume:
|
2023-07-16 15:44:47 +02:00
|
|
|
volume = self.ui.volumeHorizontalSlider.value
|
|
|
|
self.__audio.volume = volume / 100
|
2023-06-14 16:22:48 +02:00
|
|
|
|
2023-07-16 15:50:43 +02:00
|
|
|
def toggle_mute(self) -> None:
|
2023-06-15 00:12:32 +02:00
|
|
|
"""Toggle playback volume between 0 and DEFAULT_VOLUME."""
|
2023-07-16 15:44:47 +02:00
|
|
|
if self.ui.volumeHorizontalSlider.value == 0:
|
|
|
|
self.ui.volumeHorizontalSlider.value = self.previous_volume
|
|
|
|
icon = self.style().standard_icon(QStyle.SP_MediaVolume)
|
2023-07-16 15:50:43 +02:00
|
|
|
self.set_volume(self.previous_volume)
|
2023-06-14 16:22:48 +02:00
|
|
|
else:
|
2023-07-16 15:44:47 +02:00
|
|
|
self.previous_volume = self.__audio.volume * 100
|
|
|
|
self.ui.volumeHorizontalSlider.value = 0
|
|
|
|
icon = self.style().standard_icon(QStyle.SP_MediaVolumeMuted)
|
2023-07-16 15:50:43 +02:00
|
|
|
self.set_volume(0)
|
2023-06-14 16:22:48 +02:00
|
|
|
|
2023-07-16 15:44:47 +02:00
|
|
|
self.ui.volumeToolButton.icon = icon
|
2023-06-15 00:32:41 +02:00
|
|
|
|
2023-07-16 15:50:43 +02:00
|
|
|
def play_radio(self) -> None:
|
2023-06-15 00:12:32 +02:00
|
|
|
"""Play station selected by user."""
|
2023-07-16 15:44:47 +02:00
|
|
|
station = self.ui.stationsListWidget.selected_items()[0].text()
|
2023-06-12 23:16:24 +02:00
|
|
|
stream_url = None
|
2023-06-15 00:12:32 +02:00
|
|
|
for e in self.__stations_data["channels"]:
|
|
|
|
if e["name"] == station:
|
|
|
|
stream_url = f"http://stream.open.fm/{e['id']}"
|
2023-06-12 23:16:24 +02:00
|
|
|
|
2023-07-16 15:44:47 +02:00
|
|
|
self.__player.source = QUrl(stream_url)
|
|
|
|
self.window_title = f"Open FM - {station}"
|
2023-06-15 12:12:17 +02:00
|
|
|
|
|
|
|
# Required to avoid crashing. For some reason if you want to change
|
|
|
|
# the station for the first time, you need to stop and resume playback.
|
|
|
|
# If you won't, application would crash.
|
|
|
|
for _ in range(3):
|
2023-07-16 15:50:43 +02:00
|
|
|
self.toggle_player()
|
2023-06-13 00:06:24 +02:00
|
|
|
|
2023-07-16 15:50:43 +02:00
|
|
|
def toggle_player(self) -> None:
|
2023-06-15 00:12:32 +02:00
|
|
|
"""Toggle playback (play/stop)."""
|
|
|
|
pb_state = QMediaPlayer.PlaybackState
|
2023-07-16 15:44:47 +02:00
|
|
|
if self.__player.playback_state == pb_state.PlayingState:
|
2023-06-13 00:06:24 +02:00
|
|
|
self.__player.stop()
|
2023-07-16 15:44:47 +02:00
|
|
|
icon = self.style().standard_icon(QStyle.SP_MediaPlay)
|
|
|
|
elif self.__player.playback_state == pb_state.StoppedState:
|
2023-06-13 00:06:24 +02:00
|
|
|
self.__player.play()
|
2023-07-16 15:44:47 +02:00
|
|
|
icon = self.style().standard_icon(QStyle.SP_MediaStop)
|
2023-06-13 00:06:24 +02:00
|
|
|
else:
|
|
|
|
pass
|
2023-06-12 23:16:24 +02:00
|
|
|
|
2023-07-16 15:44:47 +02:00
|
|
|
self.ui.playbackToolButton.icon = icon
|