openfm-qt/openfm_qt/mainwindow.py

199 lines
7.4 KiB
Python
Raw Normal View History

2023-06-11 22:50:01 +02:00
# This Python file uses the following encoding: utf-8
2023-06-12 23:16:24 +02:00
from PySide6.QtCore import QUrl
2023-06-15 13:14:40 +02:00
from PySide6.QtWidgets import QMainWindow, QMessageBox, QStyle
2023-06-12 23:16:24 +02:00
from PySide6.QtMultimedia import QMediaPlayer, QAudioOutput
2023-06-11 22:50:01 +02:00
# Important:
# You need to run the following command to generate the ui_form.py file
# pyside6-uic form.ui -o ui_form.py, or
# pyside2-uic form.ui -o ui_form.py
from ui_form import Ui_MainWindow
import json
import requests
from . import DEFAULT_VOLUME
2023-06-11 22:50:01 +02:00
class MainWindow(QMainWindow):
"""MainWindow Class."""
2023-06-11 22:50:01 +02:00
def __init__(self, parent=None):
"""Initialize UI, audio player and handlers."""
2023-06-11 22:50:01 +02:00
super().__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
volume_icon = self.style().standardIcon(QStyle.SP_MediaVolume)
playback_icon = self.style().standardIcon(QStyle.SP_MediaPlay)
2023-06-18 22:27:55 +02:00
stop_icon = self.style().standardIcon(QStyle.SP_MediaStop)
self.ui.volumeToolButton.setIcon(volume_icon)
self.ui.playbackToolButton.setIcon(playback_icon)
2023-06-18 22:27:55 +02:00
self.ui.stopToolButton.setIcon(stop_icon)
self.__stations = self.getData(
"https://open.fm/radio/api/v2/ofm/stations_slug.json"
)
2023-06-18 17:37:10 +02:00
self.__podcasts_groups = self.getData(
2023-06-18 16:37:12 +02:00
"https://open.fm/api/podcasts/categories"
)
2023-06-12 23:16:24 +02:00
self.__player = QMediaPlayer()
self.__audio = QAudioOutput()
self.__player.setAudioOutput(self.__audio)
self.setVolume(DEFAULT_VOLUME)
2023-06-18 16:34:19 +02:00
self.printRadioGroups()
2023-06-18 16:37:12 +02:00
self.printPodcastGroups()
2023-06-18 16:34:19 +02:00
self.ui.radioGroupsListWidget.itemClicked.connect(self.printRadioStations)
2023-06-18 17:37:10 +02:00
self.ui.podcastGroupsListWidget.itemClicked.connect(self.printPodcasts)
self.ui.podcastListWidget.itemClicked.connect(self.printPodcastEpisodes)
self.ui.stationsListWidget.itemClicked.connect(self.playRadio)
self.ui.playbackToolButton.clicked.connect(self.togglePlayer)
2023-06-18 22:27:55 +02:00
self.ui.stopToolButton.clicked.connect(self.stopPlayer)
2023-06-14 16:22:48 +02:00
self.ui.volumeHorizontalSlider.valueChanged.connect(self.setVolume)
self.ui.volumeToolButton.clicked.connect(self.toggleMute)
2023-06-11 22:50:01 +02:00
def getData(self, url) -> dict:
"""Get JSON data from API and convert it to dict."""
resp = requests.get(url)
2023-06-14 15:57:46 +02:00
if resp.status_code not in range(200, 299 + 1):
error_box = QMessageBox.critical(
self,
"Błąd",
2023-06-14 15:57:46 +02:00
f"Błąd połączenia o kodzie: {resp.status_code}",
QMessageBox.Cancel,
2023-06-14 15:57:46 +02:00
)
error_box.exec()
else:
return json.loads(resp.text)
2023-06-18 16:34:19 +02:00
def printRadioGroups(self) -> None:
"""Print groups (categories) in radioGroupsListWidget."""
self.ui.stationsListWidget.clear()
self.ui.radioGroupsListWidget.addItems(
[e["name"] for e in self.__stations["groups"]]
)
2023-06-18 16:37:12 +02:00
def printPodcastGroups(self) -> None:
"""Print groups (categories) in podcastGroupsListWidget."""
self.ui.stationsListWidget.clear()
2023-06-18 16:37:12 +02:00
self.ui.podcastGroupsListWidget.addItems(
2023-06-18 17:37:10 +02:00
[e["name"] for e in self.__podcasts_groups]
2023-06-18 16:37:12 +02:00
)
2023-06-18 16:34:19 +02:00
def printRadioStations(self) -> None:
"""Print stations (channels) in stationsListWidget."""
group = self.ui.radioGroupsListWidget.selectedItems()[0].text()
group_id = None
for e in self.__stations["groups"]:
if e["name"] == group:
group_id = e["id"]
self.ui.stationsListWidget.clear()
self.ui.stationsListWidget.addItems(
[
e["name"]
for e in self.__stations["channels"]
if e["group_id"] == group_id
]
)
2023-06-18 17:37:10 +02:00
def printPodcasts(self) -> None:
"""Print podcasts in podcastListWidget."""
self.ui.stationsListWidget.clear()
2023-06-18 17:37:10 +02:00
group = self.ui.podcastGroupsListWidget.selectedItems()[0].text()
group_name = None
for e in self.__podcasts_groups:
if e["name"] == group:
group_name = e["slug"]
2023-06-18 17:57:27 +02:00
self.__podcasts = self.getData(
2023-06-18 17:37:10 +02:00
f"https://open.fm/api/podcasts/category/{group_name}"
)["podcasts"]["content"]
self.ui.podcastListWidget.clear()
self.ui.podcastListWidget.addItems(
2023-06-18 17:57:27 +02:00
[e["title"] for e in self.__podcasts]
2023-06-18 17:37:10 +02:00
)
def printPodcastEpisodes(self) -> None:
"""Print podcast episodes in stationsListWidget."""
podcast_name = self.ui.podcastListWidget.selectedItems()[0].text()
podcast_id = None
2023-06-18 17:57:27 +02:00
for e in self.__podcasts:
2023-06-18 17:37:10 +02:00
if e["title"] == podcast_name:
podcast_id = e["id"]
2023-06-18 17:57:27 +02:00
self.__podcast_episodes = self.getData(
2023-06-18 18:01:06 +02:00
f"https://open.fm/api/podcast/{podcast_id}/episodes?size=999"
2023-06-18 17:37:10 +02:00
)
self.ui.stationsListWidget.clear()
self.ui.stationsListWidget.addItems(
2023-06-18 17:57:27 +02:00
[e["title"] for e in self.__podcast_episodes["content"]]
2023-06-18 17:37:10 +02:00
)
def setVolume(self, volume: int = None) -> None:
"""Set playback volume to given number or slider value."""
if not volume:
2023-06-14 16:22:48 +02:00
volume = self.ui.volumeHorizontalSlider.value()
self.__audio.setVolume(volume / 100)
def toggleMute(self) -> None:
"""Toggle playback volume between 0 and DEFAULT_VOLUME."""
2023-06-14 16:22:48 +02:00
if self.ui.volumeHorizontalSlider.value() == 0:
self.ui.volumeHorizontalSlider.setValue(DEFAULT_VOLUME)
icon = self.style().standardIcon(QStyle.SP_MediaVolume)
self.setVolume(DEFAULT_VOLUME)
2023-06-14 16:22:48 +02:00
else:
self.ui.volumeHorizontalSlider.setValue(0)
icon = self.style().standardIcon(QStyle.SP_MediaVolumeMuted)
2023-06-14 16:22:48 +02:00
self.setVolume(0)
self.ui.volumeToolButton.setIcon(icon)
def playRadio(self) -> None:
"""Play station selected by user."""
2023-06-18 17:57:27 +02:00
selection = self.ui.stationsListWidget.selectedItems()[0].text()
2023-06-12 23:16:24 +02:00
stream_url = None
for e in self.__stations["channels"]:
2023-06-18 17:57:27 +02:00
if e["name"] == selection:
stream_url = f"http://stream.open.fm/{e['id']}"
2023-06-12 23:16:24 +02:00
2023-06-18 17:57:27 +02:00
if not stream_url:
for e in self.__podcast_episodes["content"]:
if e["title"] == selection:
stream_url = e["file"].replace("https", "http")
2023-06-12 23:16:24 +02:00
self.__player.setSource(QUrl(stream_url))
2023-06-18 22:27:55 +02:00
self.__fix_playback()
2023-06-18 22:27:55 +02:00
def __fix_playback(self) -> None:
"""Fix playack."""
# 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.
2023-06-18 22:27:55 +02:00
self.__player.play()
self.__player.stop()
self.__player.play()
icon = self.style().standardIcon(QStyle.SP_MediaPause)
self.ui.playbackToolButton.setIcon(icon)
def togglePlayer(self) -> None:
2023-06-18 22:27:55 +02:00
"""Toggle playback (play/pause)."""
pb_state = QMediaPlayer.PlaybackState
if self.__player.playbackState() == pb_state.PlayingState:
2023-06-18 22:27:55 +02:00
self.__player.pause()
icon = self.style().standardIcon(QStyle.SP_MediaPlay)
2023-06-18 22:27:55 +02:00
elif self.__player.playbackState() in [
pb_state.PausedState,
pb_state.StoppedState
]:
self.__player.play()
2023-06-18 22:27:55 +02:00
icon = self.style().standardIcon(QStyle.SP_MediaPause)
else:
pass
2023-06-12 23:16:24 +02:00
self.ui.playbackToolButton.setIcon(icon)
2023-06-18 22:27:55 +02:00
def stopPlayer(self) -> None:
self.__player.stop()
icon = self.style().standardIcon(QStyle.SP_MediaPlay)
self.ui.playbackToolButton.setIcon(icon)