Added downloading from spotify.

TODO: Two playing options - old stream and new download
This commit is contained in:
BarsTiger
2022-12-12 23:04:17 +02:00
parent 9d2bc0aeb6
commit 9dae35a537
15 changed files with 351 additions and 78 deletions

View File

@@ -270,6 +270,10 @@ class Ui_MainWindow(object):
self.output_device_restream_box.setObjectName("output_device_restream_box") self.output_device_restream_box.setObjectName("output_device_restream_box")
self.verticalLayout.addWidget(self.output_device_restream_box) self.verticalLayout.addWidget(self.output_device_restream_box)
self.audio_devices_settings_tab_lay.addWidget(self.restream_options_group, 0, QtCore.Qt.AlignTop) self.audio_devices_settings_tab_lay.addWidget(self.restream_options_group, 0, QtCore.Qt.AlignTop)
self.use_original_streaming_method_check = QtWidgets.QCheckBox(self.audio_devices_settings_tab)
self.use_original_streaming_method_check.setChecked(True)
self.use_original_streaming_method_check.setObjectName("use_original_streaming_method_check")
self.audio_devices_settings_tab_lay.addWidget(self.use_original_streaming_method_check)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.audio_devices_settings_tab_lay.addItem(spacerItem) self.audio_devices_settings_tab_lay.addItem(spacerItem)
self.settings_tabs_widget.addTab(self.audio_devices_settings_tab, "") self.settings_tabs_widget.addTab(self.audio_devices_settings_tab, "")
@@ -288,6 +292,41 @@ class Ui_MainWindow(object):
self.theme_box.addItem("") self.theme_box.addItem("")
self.theme_box.addItem("") self.theme_box.addItem("")
self.general_settings_tab_lay.addWidget(self.theme_box) self.general_settings_tab_lay.addWidget(self.theme_box)
self.api_keys_settings_label = QtWidgets.QLabel(self.general_settings_tab)
self.api_keys_settings_label.setObjectName("api_keys_settings_label")
self.general_settings_tab_lay.addWidget(self.api_keys_settings_label)
self.api_keys_settings_tabs_widget = QtWidgets.QTabWidget(self.general_settings_tab)
self.api_keys_settings_tabs_widget.setObjectName("api_keys_settings_tabs_widget")
self.spotify_api_settings_tab = QtWidgets.QWidget()
self.spotify_api_settings_tab.setObjectName("spotify_api_settings_tab")
self.spotify_api_settings_tab_lay = QtWidgets.QVBoxLayout(self.spotify_api_settings_tab)
self.spotify_api_settings_tab_lay.setContentsMargins(0, 0, 0, 0)
self.spotify_api_settings_tab_lay.setObjectName("spotify_api_settings_tab_lay")
self.spotify_client_id_label = QtWidgets.QLabel(self.spotify_api_settings_tab)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.spotify_client_id_label.sizePolicy().hasHeightForWidth())
self.spotify_client_id_label.setSizePolicy(sizePolicy)
self.spotify_client_id_label.setMaximumSize(QtCore.QSize(16777215, 50))
self.spotify_client_id_label.setObjectName("spotify_client_id_label")
self.spotify_api_settings_tab_lay.addWidget(self.spotify_client_id_label)
self.spotify_client_id_box = QtWidgets.QLineEdit(self.spotify_api_settings_tab)
self.spotify_client_id_box.setMinimumSize(QtCore.QSize(0, 30))
self.spotify_client_id_box.setObjectName("spotify_client_id_box")
self.spotify_api_settings_tab_lay.addWidget(self.spotify_client_id_box)
self.spotify_client_secret_label = QtWidgets.QLabel(self.spotify_api_settings_tab)
self.spotify_client_secret_label.setObjectName("spotify_client_secret_label")
self.spotify_api_settings_tab_lay.addWidget(self.spotify_client_secret_label)
self.spotify_client_secret_box = QtWidgets.QLineEdit(self.spotify_api_settings_tab)
self.spotify_client_secret_box.setMinimumSize(QtCore.QSize(0, 30))
self.spotify_client_secret_box.setObjectName("spotify_client_secret_box")
self.spotify_api_settings_tab_lay.addWidget(self.spotify_client_secret_box)
self.api_keys_settings_tabs_widget.addTab(self.spotify_api_settings_tab, "")
self.pusher_settings_tab = QtWidgets.QWidget()
self.pusher_settings_tab.setObjectName("pusher_settings_tab")
self.api_keys_settings_tabs_widget.addTab(self.pusher_settings_tab, "")
self.general_settings_tab_lay.addWidget(self.api_keys_settings_tabs_widget, 0, QtCore.Qt.AlignTop)
spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.general_settings_tab_lay.addItem(spacerItem1) self.general_settings_tab_lay.addItem(spacerItem1)
self.clear_temp_button = QtWidgets.QPushButton(self.general_settings_tab) self.clear_temp_button = QtWidgets.QPushButton(self.general_settings_tab)
@@ -391,11 +430,19 @@ class Ui_MainWindow(object):
self.restream_micro_checkbox.setText(_translate("MainWindow", "Restream microphone")) self.restream_micro_checkbox.setText(_translate("MainWindow", "Restream microphone"))
self.input_device_restream_label.setText(_translate("MainWindow", "Input microphone")) self.input_device_restream_label.setText(_translate("MainWindow", "Input microphone"))
self.output_device_restream_label.setText(_translate("MainWindow", "Output device (virtual mic input)")) self.output_device_restream_label.setText(_translate("MainWindow", "Output device (virtual mic input)"))
self.use_original_streaming_method_check.setText(_translate("MainWindow", "Use direct stream method (cuts last second of audio, not recommended if playing short files)"))
self.settings_tabs_widget.setTabText(self.settings_tabs_widget.indexOf(self.audio_devices_settings_tab), _translate("MainWindow", "Audio")) self.settings_tabs_widget.setTabText(self.settings_tabs_widget.indexOf(self.audio_devices_settings_tab), _translate("MainWindow", "Audio"))
self.theme_label.setText(_translate("MainWindow", " App theme (restart needed)")) self.theme_label.setText(_translate("MainWindow", " App theme (restart needed)"))
self.theme_box.setItemText(0, _translate("MainWindow", "Dark gray")) self.theme_box.setItemText(0, _translate("MainWindow", "Dark gray"))
self.theme_box.setItemText(1, _translate("MainWindow", "Black")) self.theme_box.setItemText(1, _translate("MainWindow", "Black"))
self.theme_box.setItemText(2, _translate("MainWindow", "Black acrylic")) self.theme_box.setItemText(2, _translate("MainWindow", "Black acrylic"))
self.api_keys_settings_label.setText(_translate("MainWindow", "API keys settings"))
self.spotify_client_id_label.setText(_translate("MainWindow", "Client id"))
self.spotify_client_id_box.setPlaceholderText(_translate("MainWindow", "5f573c9620494bae87890c0f08a60293"))
self.spotify_client_secret_label.setText(_translate("MainWindow", "Client secret"))
self.spotify_client_secret_box.setPlaceholderText(_translate("MainWindow", "212476d9b0f3472eaa762d90b19b0ba8"))
self.api_keys_settings_tabs_widget.setTabText(self.api_keys_settings_tabs_widget.indexOf(self.spotify_api_settings_tab), _translate("MainWindow", "Spotify"))
self.api_keys_settings_tabs_widget.setTabText(self.api_keys_settings_tabs_widget.indexOf(self.pusher_settings_tab), _translate("MainWindow", "Pusher"))
self.clear_temp_button.setText(_translate("MainWindow", "Clear KotoPad temporary files (use if sound doesn\'t play correctly)")) self.clear_temp_button.setText(_translate("MainWindow", "Clear KotoPad temporary files (use if sound doesn\'t play correctly)"))
self.settings_tabs_widget.setTabText(self.settings_tabs_widget.indexOf(self.general_settings_tab), _translate("MainWindow", "General")) self.settings_tabs_widget.setTabText(self.settings_tabs_widget.indexOf(self.general_settings_tab), _translate("MainWindow", "General"))
import gui.images_rc import gui.images_rc

View File

@@ -850,6 +850,16 @@ QListWidget:item:selected {
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="use_original_streaming_method_check">
<property name="text">
<string>Use direct stream method (cuts last second of audio, not recommended if playing short files)</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item> <item>
<spacer name="audio_devices_settings_tab_spacer"> <spacer name="audio_devices_settings_tab_spacer">
<property name="orientation"> <property name="orientation">
@@ -914,6 +924,93 @@ QListWidget:item:selected {
</item> </item>
</widget> </widget>
</item> </item>
<item>
<widget class="QLabel" name="api_keys_settings_label">
<property name="text">
<string>API keys settings</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignTop">
<widget class="QTabWidget" name="api_keys_settings_tabs_widget">
<widget class="QWidget" name="spotify_api_settings_tab">
<attribute name="title">
<string>Spotify</string>
</attribute>
<layout class="QVBoxLayout" name="spotify_api_settings_tab_lay">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="spotify_client_id_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>50</height>
</size>
</property>
<property name="text">
<string>Client id</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="spotify_client_id_box">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="placeholderText">
<string>5f573c9620494bae87890c0f08a60293</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="spotify_client_secret_label">
<property name="text">
<string>Client secret</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="spotify_client_secret_box">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="placeholderText">
<string>212476d9b0f3472eaa762d90b19b0ba8</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="pusher_settings_tab">
<attribute name="title">
<string>Pusher</string>
</attribute>
</widget>
</widget>
</item>
<item> <item>
<spacer name="general_settings_tab_spacer"> <spacer name="general_settings_tab_spacer">
<property name="orientation"> <property name="orientation">

View File

@@ -12,6 +12,6 @@ from modules.restream.restream import Restreamer
def register_handlers(ui: Ui_MainWindow, MainWindow: QMainWindow, p: Player, rs: Restreamer): def register_handlers(ui: Ui_MainWindow, MainWindow: QMainWindow, p: Player, rs: Restreamer):
menu.register_handlers(ui) menu.register_handlers(ui)
pads.register_handlers(ui, MainWindow, p) pads.register_handlers(ui, MainWindow, p)
player.register_handlers(ui, MainWindow, p) player.register_handlers(ui, p)
settings.register_handlers(ui) settings.register_handlers(ui)
restreammic.register_handlers(ui, MainWindow, rs) restreammic.register_handlers(ui, MainWindow, rs)

View File

@@ -1,6 +1,8 @@
from gui.gui import Ui_MainWindow from gui.gui import Ui_MainWindow
from modules.config import Config from modules.config import Config
from modules.spotify.config import SpotifyConfig
from modules.restream import get_streaming_devices from modules.restream import get_streaming_devices
from modules.player.player import get_devices, get_instance, get_player
def fill_settings(ui: Ui_MainWindow): def fill_settings(ui: Ui_MainWindow):
@@ -8,7 +10,23 @@ def fill_settings(ui: Ui_MainWindow):
ui.theme_box.setCurrentText(Config.get().theme) ui.theme_box.setCurrentText(Config.get().theme)
# ui.output_device_play_box.addItems() play_devices = get_devices(get_player(get_instance()))
ui.output_device_play_box.addItems(play_devices)
ui.preview_device_play_box.addItems(play_devices)
if Config.get().out_device in play_devices.keys():
ui.output_device_play_box.setCurrentText(Config.get().out_device)
else:
for item in play_devices.keys():
if '(VB-Audio Virtual Cable)' in item:
ui.output_device_play_box.setCurrentText(item)
break
if Config.get().preview_device in play_devices.keys():
ui.preview_device_play_box.setCurrentText(Config.get().preview_device)
elif 'Default' in play_devices.keys():
ui.preview_device_play_box.setCurrentText('Default')
ui.restream_micro_checkbox.setChecked(Config.get().restream) ui.restream_micro_checkbox.setChecked(Config.get().restream)
ui.input_device_restream_box.addItems(get_streaming_devices().in_l) ui.input_device_restream_box.addItems(get_streaming_devices().in_l)
@@ -19,3 +37,6 @@ def fill_settings(ui: Ui_MainWindow):
if Config.get().out_micro in get_streaming_devices().out_l: if Config.get().out_micro in get_streaming_devices().out_l:
ui.output_device_restream_box.setCurrentText(Config.get().out_micro) ui.output_device_restream_box.setCurrentText(Config.get().out_micro)
ui.spotify_client_id_box.setText(SpotifyConfig.get().client_id)
ui.spotify_client_secret_box.setText(SpotifyConfig.get().client_secret)

View File

@@ -11,12 +11,6 @@ from modules.restream.restream import Restreamer
def on_load(ui: Ui_MainWindow, MainWindow: QMainWindow): def on_load(ui: Ui_MainWindow, MainWindow: QMainWindow):
"""
Setup all UI elements
:param ui:
:param MainWindow:
:return:
"""
ui.content.setCurrentIndex(0) ui.content.setCurrentIndex(0)
MainWindow.setStyleSheet(styles.centralwidget()) MainWindow.setStyleSheet(styles.centralwidget())
@@ -27,11 +21,11 @@ def on_load(ui: Ui_MainWindow, MainWindow: QMainWindow):
ui.timer = QtCore.QTimer(MainWindow) ui.timer = QtCore.QTimer(MainWindow)
ui.timer.start(100) ui.timer.start(100)
p = Player()
rs = Restreamer()
fill_settings.fill_settings(ui) fill_settings.fill_settings(ui)
p = Player(ui)
rs = Restreamer()
(lambda: rs.restart(ui) if ui.restream_micro_checkbox.isChecked() else rs.stop())() (lambda: rs.restart(ui) if ui.restream_micro_checkbox.isChecked() else rs.stop())()
register.register_handlers(ui, MainWindow, p, rs) register.register_handlers(ui, MainWindow, p, rs)

View File

@@ -3,9 +3,4 @@ from .menu import handle_menu_click
def register_handlers(ui: Ui_MainWindow): def register_handlers(ui: Ui_MainWindow):
"""
Register this module handlers
:param ui:
:return:
"""
ui.menu.itemClicked.connect(lambda: handle_menu_click(ui.menu.currentItem().text(), ui)) ui.menu.itemClicked.connect(lambda: handle_menu_click(ui.menu.currentItem().text(), ui))

View File

@@ -3,10 +3,6 @@ from gui.gui import Ui_MainWindow
def open_menu(ui: Ui_MainWindow) -> None: def open_menu(ui: Ui_MainWindow) -> None:
"""
Animates the menu to open and close, using animation from config
:return:
"""
width = ui.menu.geometry().width() width = ui.menu.geometry().width()
Ui_MainWindow.animation = QtCore.QPropertyAnimation(ui.menu, b"minimumWidth") Ui_MainWindow.animation = QtCore.QPropertyAnimation(ui.menu, b"minimumWidth")
Ui_MainWindow.animation.setDuration(300) Ui_MainWindow.animation.setDuration(300)
@@ -22,12 +18,6 @@ def open_menu(ui: Ui_MainWindow) -> None:
def handle_menu_click(text: str, ui: Ui_MainWindow) -> None: def handle_menu_click(text: str, ui: Ui_MainWindow) -> None:
"""
Handles the click on the menu and changes the page
:param text:
:param ui:
:return:
"""
index = { index = {
"Close menu": [lambda _: open_menu(ui), None], "Close menu": [lambda _: open_menu(ui), None],
"Pads": [ui.content.setCurrentWidget, ui.pads_page], "Pads": [ui.content.setCurrentWidget, ui.pads_page],

View File

@@ -1,19 +1,10 @@
from gui.gui import Ui_MainWindow from gui.gui import Ui_MainWindow
from PyQt5 import QtGui from PyQt5 import QtGui
from PyQt5.QtWidgets import QMainWindow
from modules.player.player import Player from modules.player.player import Player
from modules.config import Config from modules.config import Config
def register_handlers(ui: Ui_MainWindow, MainWindow: QMainWindow, p: Player): def register_handlers(ui: Ui_MainWindow, p: Player):
"""
Register this module handlers
:param p:
:param ui:
:param MainWindow:
:return:
"""
play_icon = QtGui.QIcon() play_icon = QtGui.QIcon()
play_icon.addPixmap(QtGui.QPixmap(":/img/img/play.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) play_icon.addPixmap(QtGui.QPixmap(":/img/img/play.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
@@ -27,3 +18,5 @@ def register_handlers(ui: Ui_MainWindow, MainWindow: QMainWindow, p: Player):
ui.play_pause_button.setIcon(play_icon) if not p.mediaplayer_out.is_playing() ui.play_pause_button.setIcon(play_icon) if not p.mediaplayer_out.is_playing()
else ui.play_pause_button.setIcon(pause_icon))) else ui.play_pause_button.setIcon(pause_icon)))
ui.player_time_slider.sliderPressed.connect(lambda: p.set_position(ui.player_time_slider.value() / 100.0)) ui.player_time_slider.sliderPressed.connect(lambda: p.set_position(ui.player_time_slider.value() / 100.0))
ui.output_device_play_box.currentTextChanged.connect(lambda: p.update_devices(ui))
ui.preview_device_play_box.currentTextChanged.connect(lambda: p.update_devices(ui))

View File

@@ -1,15 +1,10 @@
from gui.gui import Ui_MainWindow from gui.gui import Ui_MainWindow
from modules.config import Config from modules.config import Config
from modules.spotify.config import SpotifyConfig
import shutil import shutil
def register_handlers(ui: Ui_MainWindow): def register_handlers(ui: Ui_MainWindow):
"""
Register this module handlers
:param ui:
:return:
"""
ui.theme_box.currentTextChanged.connect(lambda: Config.update("theme", ui.theme_box.currentText())) ui.theme_box.currentTextChanged.connect(lambda: Config.update("theme", ui.theme_box.currentText()))
ui.restream_micro_checkbox.clicked.connect(lambda: Config.update("restream", ui.restream_micro_checkbox.clicked.connect(lambda: Config.update("restream",
ui.restream_micro_checkbox.isChecked())) ui.restream_micro_checkbox.isChecked()))
@@ -21,6 +16,20 @@ def register_handlers(ui: Ui_MainWindow):
lambda: Config.update("in_micro", ui.input_device_restream_box.currentText()) lambda: Config.update("in_micro", ui.input_device_restream_box.currentText())
) )
ui.output_device_play_box.currentTextChanged.connect(
lambda: Config.update("out_device", ui.output_device_play_box.currentText())
)
ui.preview_device_play_box.currentTextChanged.connect(
lambda: Config.update("preview_device", ui.preview_device_play_box.currentText())
)
ui.spotify_client_id_box.textChanged.connect(
lambda: SpotifyConfig.update("client_id", ui.spotify_client_id_box.text())
)
ui.spotify_client_secret_box.textChanged.connect(
lambda: SpotifyConfig.update("client_secret", ui.spotify_client_secret_box.text())
)
ui.clear_temp_button.clicked.connect( ui.clear_temp_button.clicked.connect(
lambda: shutil.rmtree('temp', ignore_errors=True) lambda: shutil.rmtree('temp', ignore_errors=True)
) )

View File

@@ -1,30 +0,0 @@
import pydub
import validators
from urllib.request import urlopen
from io import BytesIO
from rich import print
import pafy
import hashlib
import os
def get_silenced_media(original: str) -> str | None:
if not os.path.isdir('temp'):
os.mkdir('temp')
try:
name = original
namehash = 'temp\\' + hashlib.md5(name.encode('utf-8')).hexdigest()
if not os.path.isfile(namehash):
if validators.url(original):
if 'youtu' in original:
original = pafy.new(original).getbestaudio().url
original = BytesIO(urlopen(original).read())
(pydub.AudioSegment.from_file(original) + pydub.AudioSegment.silent(1500))\
.export(namehash, format='mp3')
return namehash
except Exception as e:
print(e)
return None

42
modules/player/convert.py Normal file
View File

@@ -0,0 +1,42 @@
import pydub
import validators
from io import BytesIO
from rich import print
import pafy
import hashlib
import os
from modules.spotify.spotify_dl import Spotify
from gui.modules.core.popup import popup
import requests
def get_raw_link(url):
if validators.url(url):
if 'spotify' in url:
url = Spotify().get_youtube_url(url)
if 'youtu' in url:
url = pafy.new(url).audiostreams[0].url
else:
url = None
return url
def get_silenced_media(original: str) -> str | None:
if not os.path.isdir('temp'):
os.mkdir('temp')
try:
namehash = 'temp\\' + hashlib.md5(original.encode('utf-8')).hexdigest()
if not os.path.isfile(original):
if validators.url(original):
original = BytesIO(requests.get(get_raw_link(original)).content)
(pydub.AudioSegment.from_file(original) + pydub.AudioSegment.silent(1500))\
.export(namehash, format='mp3')
return namehash
except Exception as e:
raise e
print(e)
return None

View File

@@ -1,7 +1,7 @@
import vlc import vlc
from gui.gui import Ui_MainWindow from gui.gui import Ui_MainWindow
from gui.modules.core import popup from gui.modules.core import popup
from modules.player.add_second import get_silenced_media from modules.player.convert import get_silenced_media
def get_instance() -> vlc.Instance: def get_instance() -> vlc.Instance:
@@ -24,14 +24,16 @@ def get_devices(mediaplayer: vlc.MediaPlayer) -> dict:
class Player(object): class Player(object):
def __init__(self): def __init__(self, ui: Ui_MainWindow):
self.instance_preview = get_instance() self.instance_preview = get_instance()
self.instance_out = get_instance() self.instance_out = get_instance()
self.mediaplayer_preview = get_player(self.instance_preview) self.mediaplayer_preview = get_player(self.instance_preview)
self.mediaplayer_preview.audio_output_device_set(None, get_devices(self.mediaplayer_preview)['Default']) self.mediaplayer_preview.audio_output_device_set(None, get_devices(self.mediaplayer_preview)[
ui.preview_device_play_box.currentText()
])
self.mediaplayer_out = get_player(self.instance_out) self.mediaplayer_out = get_player(self.instance_out)
self.mediaplayer_out.audio_output_device_set(None, get_devices( self.mediaplayer_out.audio_output_device_set(None, get_devices(
self.mediaplayer_out)['CABLE Input (VB-Audio Virtual Cable)']) self.mediaplayer_out)[ui.output_device_play_box.currentText()])
def set_media(self, media: str) -> None: def set_media(self, media: str) -> None:
if get_silenced_media(media): if get_silenced_media(media):
@@ -77,5 +79,10 @@ class Player(object):
self.mediaplayer_preview.set_position(pos) self.mediaplayer_preview.set_position(pos)
self.mediaplayer_out.set_position(pos) self.mediaplayer_out.set_position(pos)
def update_devices(self): def update_devices(self, ui: Ui_MainWindow):
pass self.mediaplayer_preview.audio_output_device_set(None, get_devices(self.mediaplayer_preview)[
ui.preview_device_play_box.currentText()
])
self.mediaplayer_out.audio_output_device_set(None, get_devices(self.mediaplayer_out)[
ui.output_device_play_box.currentText()
])

View File

51
modules/spotify/config.py Normal file
View File

@@ -0,0 +1,51 @@
import json
import os
from dataclasses import dataclass
from dataclasses_json import dataclass_json
@dataclass_json
@dataclass(frozen=True)
class SpotConfig:
client_id: str
client_secret: str
class SpotifyConfig:
@staticmethod
def default():
return {
"client_id": "5f573c9620494bae87890c0f08a60293",
"client_secret": "212476d9b0f3472eaa762d90b19b0ba8"
}
@staticmethod
def fix() -> None:
try:
with open("data/config.spotify", "w") as file:
json.dump(SpotifyConfig.default(), file)
except FileNotFoundError:
if not os.path.exists('data'):
os.mkdir('data')
SpotifyConfig.fix()
@staticmethod
def get() -> SpotConfig:
try:
with open("data/config.spotify", "r") as file:
return SpotConfig.from_dict(json.load(file))
except:
SpotifyConfig.fix()
return SpotifyConfig.get()
@staticmethod
def update(key: str, value: str | None) -> dict:
with open("data/config.spotify", "r") as file:
settings = json.load(file)
settings[key] = value
with open("data/config.spotify", "w") as file:
json.dump(settings, file)
return settings

View File

@@ -0,0 +1,57 @@
import requests
from urllib.parse import urlencode
from urllib.request import urlopen
from urllib.error import HTTPError
import re
from base64 import b64encode
from modules.spotify.config import SpotifyConfig
def reencode(text: str):
return b64encode(text.encode()).decode()
class Spotify(object):
def __init__(self):
try:
headers = {
'Authorization': f'Basic '
f'{reencode(f"{SpotifyConfig.get().client_id}:{SpotifyConfig.get().client_secret}")}',
}
data = {
'grant_type': 'client_credentials'
}
r = requests.post('https://accounts.spotify.com/api/token', headers=headers, data=data)
self.token = r.json()['access_token']
except Exception as e:
print(e)
def get_youtube_url(self, url) -> str | None:
track_id = url.split('/')[-1].split('?')[0]
r = requests.get(f"https://api.spotify.com/v1/tracks/{track_id}",
headers={'Authorization': f'Bearer {self.token}'})
if r.status_code == 400 or r.status_code == 401:
return None
track = r.json()
song_name = track['name']
artists = []
for artist in track['artists']:
artists.append(artist['name'])
artist_name = ' '.join(artists)
try:
query_string = urlencode({'search_query': artist_name + ' ' + song_name})
htm_content = urlopen('http://www.youtube.com/results?' + query_string)
search_results = re.findall(r'/watch\?v=(.{11})', htm_content.read().decode())
return f'http://www.youtube.com/watch?v={search_results[0]}'
except HTTPError:
return None