Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
45b5643cc7 | ||
|
eeadc0a8c2 | ||
|
5358deab51 | ||
|
f664548d71 | ||
|
c26d8833b3 | ||
|
32ed78e7bc | ||
|
edc498c510 | ||
|
d02f7302a2 | ||
|
e01edba7f3 | ||
|
0b63621532 | ||
|
89cedd4f7c |
101
form.ui
101
form.ui
@ -6,19 +6,19 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>350</width>
|
||||
<width>650</width>
|
||||
<height>500</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>350</width>
|
||||
<width>650</width>
|
||||
<height>500</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>350</width>
|
||||
<width>650</width>
|
||||
<height>500</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -44,7 +44,7 @@
|
||||
<rect>
|
||||
<x>9</x>
|
||||
<y>9</y>
|
||||
<width>332</width>
|
||||
<width>631</width>
|
||||
<height>461</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -52,19 +52,85 @@
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QListWidget" name="groupsListWidget">
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<width>200</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="radioTab">
|
||||
<attribute name="title">
|
||||
<string>Radio</string>
|
||||
</attribute>
|
||||
<widget class="QListWidget" name="radioGroupsListWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>200</width>
|
||||
<height>400</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>400</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>400</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="podcastTab">
|
||||
<attribute name="title">
|
||||
<string>Podcasty</string>
|
||||
</attribute>
|
||||
<widget class="QWidget" name="verticalLayoutWidget_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
<width>201</width>
|
||||
<height>401</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QListWidget" name="podcastGroupsListWidget"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="podcastListWidget">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>195</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>195</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@ -81,6 +147,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="stopToolButton">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="lineWidth">
|
||||
@ -99,6 +172,18 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>70</number>
|
||||
</property>
|
||||
@ -124,7 +209,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>350</width>
|
||||
<width>650</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
@ -1,6 +1,5 @@
|
||||
# This Python file uses the following encoding: utf-8
|
||||
|
||||
API_URL = "https://open.fm/radio/api/v2/ofm/stations_slug.json"
|
||||
DEFAULT_VOLUME = 70
|
||||
|
||||
from .mainwindow import MainWindow
|
||||
|
@ -11,7 +11,7 @@ from PySide6.QtMultimedia import QMediaPlayer, QAudioOutput
|
||||
from ui_form import Ui_MainWindow
|
||||
import json
|
||||
import requests
|
||||
from . import API_URL, DEFAULT_VOLUME
|
||||
from . import DEFAULT_VOLUME
|
||||
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
@ -24,25 +24,36 @@ class MainWindow(QMainWindow):
|
||||
self.ui.setupUi(self)
|
||||
volume_icon = self.style().standardIcon(QStyle.SP_MediaVolume)
|
||||
playback_icon = self.style().standardIcon(QStyle.SP_MediaPlay)
|
||||
stop_icon = self.style().standardIcon(QStyle.SP_MediaStop)
|
||||
self.ui.volumeToolButton.setIcon(volume_icon)
|
||||
self.ui.playbackToolButton.setIcon(playback_icon)
|
||||
self.ui.stopToolButton.setIcon(stop_icon)
|
||||
|
||||
self.__stations_data = self.getStationsData()
|
||||
self.__stations = self.getData(
|
||||
"https://open.fm/radio/api/v2/ofm/stations_slug.json"
|
||||
)
|
||||
self.__podcasts_groups = self.getData(
|
||||
"https://open.fm/api/podcasts/categories"
|
||||
)
|
||||
self.__player = QMediaPlayer()
|
||||
self.__audio = QAudioOutput()
|
||||
self.__player.setAudioOutput(self.__audio)
|
||||
self.setVolume(DEFAULT_VOLUME)
|
||||
self.printGroups()
|
||||
self.printRadioGroups()
|
||||
self.printPodcastGroups()
|
||||
|
||||
self.ui.groupsListWidget.itemClicked.connect(self.printStations)
|
||||
self.ui.radioGroupsListWidget.itemClicked.connect(self.printRadioStations)
|
||||
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)
|
||||
self.ui.stopToolButton.clicked.connect(self.stopPlayer)
|
||||
self.ui.volumeHorizontalSlider.valueChanged.connect(self.setVolume)
|
||||
self.ui.volumeToolButton.clicked.connect(self.toggleMute)
|
||||
|
||||
def getStationsData(self) -> dict:
|
||||
def getData(self, url) -> dict:
|
||||
"""Get JSON data from API and convert it to dict."""
|
||||
resp = requests.get(API_URL)
|
||||
resp = requests.get(url)
|
||||
if resp.status_code not in range(200, 299 + 1):
|
||||
error_box = QMessageBox.critical(
|
||||
self,
|
||||
@ -54,17 +65,25 @@ class MainWindow(QMainWindow):
|
||||
else:
|
||||
return json.loads(resp.text)
|
||||
|
||||
def printGroups(self) -> None:
|
||||
"""Print groups (categories) in groupsListWidget."""
|
||||
self.ui.groupsListWidget.addItems(
|
||||
[e["name"] for e in self.__stations_data["groups"]]
|
||||
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"]]
|
||||
)
|
||||
|
||||
def printStations(self) -> None:
|
||||
def printPodcastGroups(self) -> None:
|
||||
"""Print groups (categories) in podcastGroupsListWidget."""
|
||||
self.ui.stationsListWidget.clear()
|
||||
self.ui.podcastGroupsListWidget.addItems(
|
||||
[e["name"] for e in self.__podcasts_groups]
|
||||
)
|
||||
|
||||
def printRadioStations(self) -> None:
|
||||
"""Print stations (channels) in stationsListWidget."""
|
||||
group = self.ui.groupsListWidget.selectedItems()[0].text()
|
||||
group = self.ui.radioGroupsListWidget.selectedItems()[0].text()
|
||||
group_id = None
|
||||
for e in self.__stations_data["groups"]:
|
||||
for e in self.__stations["groups"]:
|
||||
if e["name"] == group:
|
||||
group_id = e["id"]
|
||||
|
||||
@ -72,11 +91,44 @@ class MainWindow(QMainWindow):
|
||||
self.ui.stationsListWidget.addItems(
|
||||
[
|
||||
e["name"]
|
||||
for e in self.__stations_data["channels"]
|
||||
for e in self.__stations["channels"]
|
||||
if e["group_id"] == group_id
|
||||
]
|
||||
)
|
||||
|
||||
def printPodcasts(self) -> None:
|
||||
"""Print podcasts in podcastListWidget."""
|
||||
self.ui.stationsListWidget.clear()
|
||||
group = self.ui.podcastGroupsListWidget.selectedItems()[0].text()
|
||||
group_name = None
|
||||
for e in self.__podcasts_groups:
|
||||
if e["name"] == group:
|
||||
group_name = e["slug"]
|
||||
|
||||
self.__podcasts = self.getData(
|
||||
f"https://open.fm/api/podcasts/category/{group_name}"
|
||||
)["podcasts"]["content"]
|
||||
self.ui.podcastListWidget.clear()
|
||||
self.ui.podcastListWidget.addItems(
|
||||
[e["title"] for e in self.__podcasts]
|
||||
)
|
||||
|
||||
def printPodcastEpisodes(self) -> None:
|
||||
"""Print podcast episodes in stationsListWidget."""
|
||||
podcast_name = self.ui.podcastListWidget.selectedItems()[0].text()
|
||||
podcast_id = None
|
||||
for e in self.__podcasts:
|
||||
if e["title"] == podcast_name:
|
||||
podcast_id = e["id"]
|
||||
|
||||
self.__podcast_episodes = self.getData(
|
||||
f"https://open.fm/api/podcast/{podcast_id}/episodes?size=999"
|
||||
)
|
||||
self.ui.stationsListWidget.clear()
|
||||
self.ui.stationsListWidget.addItems(
|
||||
[e["title"] for e in self.__podcast_episodes["content"]]
|
||||
)
|
||||
|
||||
def setVolume(self, volume: int = None) -> None:
|
||||
"""Set playback volume to given number or slider value."""
|
||||
if not volume:
|
||||
@ -98,30 +150,49 @@ class MainWindow(QMainWindow):
|
||||
|
||||
def playRadio(self) -> None:
|
||||
"""Play station selected by user."""
|
||||
station = self.ui.stationsListWidget.selectedItems()[0].text()
|
||||
selection = self.ui.stationsListWidget.selectedItems()[0].text()
|
||||
stream_url = None
|
||||
for e in self.__stations_data["channels"]:
|
||||
if e["name"] == station:
|
||||
for e in self.__stations["channels"]:
|
||||
if e["name"] == selection:
|
||||
stream_url = f"http://stream.open.fm/{e['id']}"
|
||||
|
||||
self.__player.setSource(QUrl(stream_url))
|
||||
if not stream_url:
|
||||
for e in self.__podcast_episodes["content"]:
|
||||
if e["title"] == selection:
|
||||
stream_url = e["file"].replace("https", "http")
|
||||
|
||||
# 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.
|
||||
self.__player.setSource(QUrl(stream_url))
|
||||
self.__fix_playback()
|
||||
|
||||
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.
|
||||
for _ in range(3):
|
||||
self.togglePlayer()
|
||||
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:
|
||||
"""Toggle playback (play/stop)."""
|
||||
"""Toggle playback (play/pause)."""
|
||||
pb_state = QMediaPlayer.PlaybackState
|
||||
if self.__player.playbackState() == pb_state.PlayingState:
|
||||
self.__player.stop()
|
||||
self.__player.pause()
|
||||
icon = self.style().standardIcon(QStyle.SP_MediaPlay)
|
||||
elif self.__player.playbackState() == pb_state.StoppedState:
|
||||
elif self.__player.playbackState() in [
|
||||
pb_state.PausedState,
|
||||
pb_state.StoppedState
|
||||
]:
|
||||
self.__player.play()
|
||||
icon = self.style().standardIcon(QStyle.SP_MediaStop)
|
||||
icon = self.style().standardIcon(QStyle.SP_MediaPause)
|
||||
else:
|
||||
pass
|
||||
|
||||
self.ui.playbackToolButton.setIcon(icon)
|
||||
|
||||
def stopPlayer(self) -> None:
|
||||
self.__player.stop()
|
||||
icon = self.style().standardIcon(QStyle.SP_MediaPlay)
|
||||
self.ui.playbackToolButton.setIcon(icon)
|
||||
|
@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "openfm-qt"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
description = "Qt client for Polish internet radio Open FM."
|
||||
authors = ["Wiktor Zykubek <wz-git@mailbox.org>"]
|
||||
license = "ISC"
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 53 KiB |
Loading…
x
Reference in New Issue
Block a user