diff --git a/gui/gui.py b/gui/gui.py
index 6e9ace5..5404f8e 100644
--- a/gui/gui.py
+++ b/gui/gui.py
@@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
- MainWindow.resize(815, 484)
+ MainWindow.resize(815, 497)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/img/img/kotopad.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
MainWindow.setWindowIcon(icon)
@@ -324,6 +324,153 @@ class Ui_MainWindow(object):
self.content.addWidget(self.stream_page)
self.collab_page = QtWidgets.QWidget()
self.collab_page.setObjectName("collab_page")
+ self.collab_page_lay = QtWidgets.QVBoxLayout(self.collab_page)
+ self.collab_page_lay.setContentsMargins(0, 0, 0, 0)
+ self.collab_page_lay.setObjectName("collab_page_lay")
+ self.collab_tab_widget = QtWidgets.QTabWidget(self.collab_page)
+ self.collab_tab_widget.setObjectName("collab_tab_widget")
+ self.collab_connect_tab = QtWidgets.QWidget()
+ self.collab_connect_tab.setObjectName("collab_connect_tab")
+ self.collab_connect_tab_2 = QtWidgets.QVBoxLayout(self.collab_connect_tab)
+ self.collab_connect_tab_2.setContentsMargins(0, 0, 0, 0)
+ self.collab_connect_tab_2.setObjectName("collab_connect_tab_2")
+ self.connect_session_widget = QtWidgets.QWidget(self.collab_connect_tab)
+ self.connect_session_widget.setObjectName("connect_session_widget")
+ self.connect_session_widget_lay = QtWidgets.QHBoxLayout(self.connect_session_widget)
+ self.connect_session_widget_lay.setContentsMargins(0, 0, 0, 0)
+ self.connect_session_widget_lay.setObjectName("connect_session_widget_lay")
+ self.collab_session_key_box = QtWidgets.QLineEdit(self.connect_session_widget)
+ self.collab_session_key_box.setMinimumSize(QtCore.QSize(0, 35))
+ self.collab_session_key_box.setObjectName("collab_session_key_box")
+ self.connect_session_widget_lay.addWidget(self.collab_session_key_box)
+ self.connect_to_session_button = QtWidgets.QPushButton(self.connect_session_widget)
+ self.connect_to_session_button.setMinimumSize(QtCore.QSize(70, 35))
+ self.connect_to_session_button.setObjectName("connect_to_session_button")
+ self.connect_session_widget_lay.addWidget(self.connect_to_session_button)
+ self.collab_connect_tab_2.addWidget(self.connect_session_widget)
+ self.collab_connect_logs = QtWidgets.QTextBrowser(self.collab_connect_tab)
+ self.collab_connect_logs.setObjectName("collab_connect_logs")
+ self.collab_connect_tab_2.addWidget(self.collab_connect_logs)
+ self.collab_disconnect_button = QtWidgets.QPushButton(self.collab_connect_tab)
+ self.collab_disconnect_button.setMinimumSize(QtCore.QSize(0, 35))
+ self.collab_disconnect_button.setObjectName("collab_disconnect_button")
+ self.collab_connect_tab_2.addWidget(self.collab_disconnect_button)
+ self.collab_tab_widget.addTab(self.collab_connect_tab, "")
+ self.collab_host_tab = QtWidgets.QWidget()
+ self.collab_host_tab.setObjectName("collab_host_tab")
+ self.collab_host_tab_lay = QtWidgets.QVBoxLayout(self.collab_host_tab)
+ self.collab_host_tab_lay.setContentsMargins(0, 0, 0, 0)
+ self.collab_host_tab_lay.setObjectName("collab_host_tab_lay")
+ self.collab_host_tabs = QtWidgets.QTabWidget(self.collab_host_tab)
+ self.collab_host_tabs.setObjectName("collab_host_tabs")
+ self.collab_host_create_tab = QtWidgets.QWidget()
+ self.collab_host_create_tab.setObjectName("collab_host_create_tab")
+ self.collab_host_create_tab_lay = QtWidgets.QVBoxLayout(self.collab_host_create_tab)
+ self.collab_host_create_tab_lay.setContentsMargins(0, 0, 0, 0)
+ self.collab_host_create_tab_lay.setObjectName("collab_host_create_tab_lay")
+ self.create_session_widget = QtWidgets.QWidget(self.collab_host_create_tab)
+ self.create_session_widget.setObjectName("create_session_widget")
+ self.create_session_widget_lay = QtWidgets.QHBoxLayout(self.create_session_widget)
+ self.create_session_widget_lay.setContentsMargins(0, 0, 0, 0)
+ self.create_session_widget_lay.setObjectName("create_session_widget_lay")
+ self.create_session_name_box = QtWidgets.QLineEdit(self.create_session_widget)
+ self.create_session_name_box.setMinimumSize(QtCore.QSize(0, 35))
+ self.create_session_name_box.setMaxLength(25)
+ self.create_session_name_box.setObjectName("create_session_name_box")
+ self.create_session_widget_lay.addWidget(self.create_session_name_box)
+ self.create_session_button = QtWidgets.QPushButton(self.create_session_widget)
+ self.create_session_button.setMinimumSize(QtCore.QSize(70, 35))
+ self.create_session_button.setObjectName("create_session_button")
+ self.create_session_widget_lay.addWidget(self.create_session_button)
+ self.collab_host_create_tab_lay.addWidget(self.create_session_widget, 0, QtCore.Qt.AlignTop)
+ self.connection_key_label = QtWidgets.QLabel(self.collab_host_create_tab)
+ self.connection_key_label.setObjectName("connection_key_label")
+ self.collab_host_create_tab_lay.addWidget(self.connection_key_label, 0, QtCore.Qt.AlignTop)
+ self.new_connection_key_copy_box = QtWidgets.QLineEdit(self.collab_host_create_tab)
+ self.new_connection_key_copy_box.setMinimumSize(QtCore.QSize(0, 35))
+ self.new_connection_key_copy_box.setReadOnly(True)
+ self.new_connection_key_copy_box.setObjectName("new_connection_key_copy_box")
+ self.collab_host_create_tab_lay.addWidget(self.new_connection_key_copy_box)
+ self.admin_key_label = QtWidgets.QLabel(self.collab_host_create_tab)
+ self.admin_key_label.setObjectName("admin_key_label")
+ self.collab_host_create_tab_lay.addWidget(self.admin_key_label)
+ self.new_connection_admin_key_copy_box = QtWidgets.QLineEdit(self.collab_host_create_tab)
+ self.new_connection_admin_key_copy_box.setMinimumSize(QtCore.QSize(0, 35))
+ self.new_connection_admin_key_copy_box.setReadOnly(True)
+ self.new_connection_admin_key_copy_box.setObjectName("new_connection_admin_key_copy_box")
+ self.collab_host_create_tab_lay.addWidget(self.new_connection_admin_key_copy_box)
+ spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.collab_host_create_tab_lay.addItem(spacerItem1)
+ self.collab_host_tabs.addTab(self.collab_host_create_tab, "")
+ self.collab_host_control_tab = QtWidgets.QWidget()
+ self.collab_host_control_tab.setObjectName("collab_host_control_tab")
+ self.collab_host_control_tab_lay = QtWidgets.QVBoxLayout(self.collab_host_control_tab)
+ self.collab_host_control_tab_lay.setContentsMargins(0, 0, 0, 0)
+ self.collab_host_control_tab_lay.setObjectName("collab_host_control_tab_lay")
+ self.connect_admin_session_widget = QtWidgets.QWidget(self.collab_host_control_tab)
+ self.connect_admin_session_widget.setObjectName("connect_admin_session_widget")
+ self.connect_session_widget_lay_2 = QtWidgets.QHBoxLayout(self.connect_admin_session_widget)
+ self.connect_session_widget_lay_2.setContentsMargins(0, 0, 0, 0)
+ self.connect_session_widget_lay_2.setObjectName("connect_session_widget_lay_2")
+ self.collab_session_admin_key_box = QtWidgets.QLineEdit(self.connect_admin_session_widget)
+ self.collab_session_admin_key_box.setMinimumSize(QtCore.QSize(0, 35))
+ self.collab_session_admin_key_box.setObjectName("collab_session_admin_key_box")
+ self.connect_session_widget_lay_2.addWidget(self.collab_session_admin_key_box)
+ self.connect_to_admin_session_button = QtWidgets.QPushButton(self.connect_admin_session_widget)
+ self.connect_to_admin_session_button.setMinimumSize(QtCore.QSize(70, 35))
+ self.connect_to_admin_session_button.setObjectName("connect_to_admin_session_button")
+ self.connect_session_widget_lay_2.addWidget(self.connect_to_admin_session_button)
+ self.collab_host_control_tab_lay.addWidget(self.connect_admin_session_widget, 0, QtCore.Qt.AlignTop)
+ self.url_to_send_admin_box = QtWidgets.QLineEdit(self.collab_host_control_tab)
+ self.url_to_send_admin_box.setMinimumSize(QtCore.QSize(0, 35))
+ self.url_to_send_admin_box.setObjectName("url_to_send_admin_box")
+ self.collab_host_control_tab_lay.addWidget(self.url_to_send_admin_box, 0, QtCore.Qt.AlignTop)
+ self.send_to_users_admin_button = QtWidgets.QPushButton(self.collab_host_control_tab)
+ self.send_to_users_admin_button.setMinimumSize(QtCore.QSize(0, 35))
+ self.send_to_users_admin_button.setObjectName("send_to_users_admin_button")
+ self.collab_host_control_tab_lay.addWidget(self.send_to_users_admin_button)
+ self.stop_all_button_admin = QtWidgets.QPushButton(self.collab_host_control_tab)
+ self.stop_all_button_admin.setMinimumSize(QtCore.QSize(0, 35))
+ self.stop_all_button_admin.setObjectName("stop_all_button_admin")
+ self.collab_host_control_tab_lay.addWidget(self.stop_all_button_admin)
+ self.control_admin_logs = QtWidgets.QTextBrowser(self.collab_host_control_tab)
+ self.control_admin_logs.setObjectName("control_admin_logs")
+ self.collab_host_control_tab_lay.addWidget(self.control_admin_logs)
+ self.collab_host_tabs.addTab(self.collab_host_control_tab, "")
+ self.collab_host_upload_tab = QtWidgets.QWidget()
+ self.collab_host_upload_tab.setObjectName("collab_host_upload_tab")
+ self.collab_host_upload_tab_lay = QtWidgets.QVBoxLayout(self.collab_host_upload_tab)
+ self.collab_host_upload_tab_lay.setContentsMargins(0, 0, 0, 0)
+ self.collab_host_upload_tab_lay.setObjectName("collab_host_upload_tab_lay")
+ self.upload_sound_widget = QtWidgets.QWidget(self.collab_host_upload_tab)
+ self.upload_sound_widget.setObjectName("upload_sound_widget")
+ self.create_session_widget_lay_2 = QtWidgets.QHBoxLayout(self.upload_sound_widget)
+ self.create_session_widget_lay_2.setContentsMargins(0, 0, 0, 0)
+ self.create_session_widget_lay_2.setObjectName("create_session_widget_lay_2")
+ self.filename_to_upload_box = QtWidgets.QLineEdit(self.upload_sound_widget)
+ self.filename_to_upload_box.setMinimumSize(QtCore.QSize(0, 35))
+ self.filename_to_upload_box.setObjectName("filename_to_upload_box")
+ self.create_session_widget_lay_2.addWidget(self.filename_to_upload_box)
+ self.choose_upload_sound_button = QtWidgets.QPushButton(self.upload_sound_widget)
+ self.choose_upload_sound_button.setMinimumSize(QtCore.QSize(70, 35))
+ self.choose_upload_sound_button.setObjectName("choose_upload_sound_button")
+ self.create_session_widget_lay_2.addWidget(self.choose_upload_sound_button)
+ self.collab_host_upload_tab_lay.addWidget(self.upload_sound_widget)
+ self.upload_sound_button = QtWidgets.QPushButton(self.collab_host_upload_tab)
+ self.upload_sound_button.setMinimumSize(QtCore.QSize(0, 35))
+ self.upload_sound_button.setObjectName("upload_sound_button")
+ self.collab_host_upload_tab_lay.addWidget(self.upload_sound_button)
+ self.anonfiles_uploaded_url_box = QtWidgets.QLineEdit(self.collab_host_upload_tab)
+ self.anonfiles_uploaded_url_box.setMinimumSize(QtCore.QSize(0, 35))
+ self.anonfiles_uploaded_url_box.setReadOnly(True)
+ self.anonfiles_uploaded_url_box.setObjectName("anonfiles_uploaded_url_box")
+ self.collab_host_upload_tab_lay.addWidget(self.anonfiles_uploaded_url_box)
+ spacerItem2 = QtWidgets.QSpacerItem(20, 261, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.collab_host_upload_tab_lay.addItem(spacerItem2)
+ self.collab_host_tabs.addTab(self.collab_host_upload_tab, "")
+ self.collab_host_tab_lay.addWidget(self.collab_host_tabs)
+ self.collab_tab_widget.addTab(self.collab_host_tab, "")
+ self.collab_page_lay.addWidget(self.collab_tab_widget)
self.content.addWidget(self.collab_page)
self.download_page = QtWidgets.QWidget()
self.download_page.setObjectName("download_page")
@@ -445,8 +592,8 @@ class Ui_MainWindow(object):
self.use_original_streaming_method_desc.setWordWrap(True)
self.use_original_streaming_method_desc.setObjectName("use_original_streaming_method_desc")
self.audio_devices_settings_tab_lay.addWidget(self.use_original_streaming_method_desc, 0, QtCore.Qt.AlignTop)
- spacerItem1 = QtWidgets.QSpacerItem(20, 0, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
- self.audio_devices_settings_tab_lay.addItem(spacerItem1)
+ spacerItem3 = QtWidgets.QSpacerItem(20, 0, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.audio_devices_settings_tab_lay.addItem(spacerItem3)
self.settings_tabs_widget.addTab(self.audio_devices_settings_tab, "")
self.general_settings_tab = QtWidgets.QWidget()
self.general_settings_tab.setObjectName("general_settings_tab")
@@ -493,13 +640,58 @@ class Ui_MainWindow(object):
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)
+ spacerItem4 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.spotify_api_settings_tab_lay.addItem(spacerItem4)
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.pusher_settings_tab_lay = QtWidgets.QVBoxLayout(self.pusher_settings_tab)
+ self.pusher_settings_tab_lay.setContentsMargins(0, 0, 0, 0)
+ self.pusher_settings_tab_lay.setObjectName("pusher_settings_tab_lay")
+ self.pusher_app_id_label = QtWidgets.QLabel(self.pusher_settings_tab)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.pusher_app_id_label.sizePolicy().hasHeightForWidth())
+ self.pusher_app_id_label.setSizePolicy(sizePolicy)
+ self.pusher_app_id_label.setMaximumSize(QtCore.QSize(16777215, 50))
+ self.pusher_app_id_label.setObjectName("pusher_app_id_label")
+ self.pusher_settings_tab_lay.addWidget(self.pusher_app_id_label)
+ self.pusher_app_id_box = QtWidgets.QLineEdit(self.pusher_settings_tab)
+ self.pusher_app_id_box.setMinimumSize(QtCore.QSize(0, 30))
+ self.pusher_app_id_box.setObjectName("pusher_app_id_box")
+ self.pusher_settings_tab_lay.addWidget(self.pusher_app_id_box)
+ self.pusher_key_label = QtWidgets.QLabel(self.pusher_settings_tab)
+ self.pusher_key_label.setObjectName("pusher_key_label")
+ self.pusher_settings_tab_lay.addWidget(self.pusher_key_label)
+ self.pusher_key_box = QtWidgets.QLineEdit(self.pusher_settings_tab)
+ self.pusher_key_box.setMinimumSize(QtCore.QSize(0, 30))
+ self.pusher_key_box.setObjectName("pusher_key_box")
+ self.pusher_settings_tab_lay.addWidget(self.pusher_key_box)
+ self.pusher_secret_label = QtWidgets.QLabel(self.pusher_settings_tab)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.pusher_secret_label.sizePolicy().hasHeightForWidth())
+ self.pusher_secret_label.setSizePolicy(sizePolicy)
+ self.pusher_secret_label.setMaximumSize(QtCore.QSize(16777215, 50))
+ self.pusher_secret_label.setObjectName("pusher_secret_label")
+ self.pusher_settings_tab_lay.addWidget(self.pusher_secret_label)
+ self.pusher_secret_box = QtWidgets.QLineEdit(self.pusher_settings_tab)
+ self.pusher_secret_box.setMinimumSize(QtCore.QSize(0, 30))
+ self.pusher_secret_box.setObjectName("pusher_secret_box")
+ self.pusher_settings_tab_lay.addWidget(self.pusher_secret_box)
+ self.pusher_cluster_label = QtWidgets.QLabel(self.pusher_settings_tab)
+ self.pusher_cluster_label.setObjectName("pusher_cluster_label")
+ self.pusher_settings_tab_lay.addWidget(self.pusher_cluster_label)
+ self.pusher_cluster_box = QtWidgets.QLineEdit(self.pusher_settings_tab)
+ self.pusher_cluster_box.setMinimumSize(QtCore.QSize(0, 30))
+ self.pusher_cluster_box.setObjectName("pusher_cluster_box")
+ self.pusher_settings_tab_lay.addWidget(self.pusher_cluster_box)
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)
- spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
- self.general_settings_tab_lay.addItem(spacerItem2)
+ spacerItem5 = QtWidgets.QSpacerItem(20, 0, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.general_settings_tab_lay.addItem(spacerItem5)
self.clear_temp_button = QtWidgets.QPushButton(self.general_settings_tab)
self.clear_temp_button.setMinimumSize(QtCore.QSize(0, 40))
self.clear_temp_button.setObjectName("clear_temp_button")
@@ -566,7 +758,10 @@ class Ui_MainWindow(object):
self.pads_content.setCurrentIndex(0)
self.browser_page_tabs.setCurrentIndex(0)
self.collections_page_tabs.setCurrentIndex(0)
+ self.collab_tab_widget.setCurrentIndex(0)
+ self.collab_host_tabs.setCurrentIndex(0)
self.settings_tabs_widget.setCurrentIndex(0)
+ self.api_keys_settings_tabs_widget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
@@ -611,6 +806,29 @@ class Ui_MainWindow(object):
self.collections_page_tabs.setTabText(self.collections_page_tabs.indexOf(self.edit_collections_tabs), _translate("MainWindow", "Edit collections"))
self.to_stream_url_box.setPlaceholderText(_translate("MainWindow", "URL (direct web file, YouTube or spotify link) or path to file"))
self.play_stream_button.setText(_translate("MainWindow", "Play"))
+ self.collab_session_key_box.setPlaceholderText(_translate("MainWindow", "Collab session key"))
+ self.connect_to_session_button.setText(_translate("MainWindow", "Connect"))
+ self.collab_disconnect_button.setText(_translate("MainWindow", "Disconnect"))
+ self.collab_tab_widget.setTabText(self.collab_tab_widget.indexOf(self.collab_connect_tab), _translate("MainWindow", "Connect"))
+ self.create_session_name_box.setPlaceholderText(_translate("MainWindow", "Collab session room name"))
+ self.create_session_button.setText(_translate("MainWindow", "Create"))
+ self.connection_key_label.setText(_translate("MainWindow", "Connection key. With this key, everyone can connect to the room"))
+ self.new_connection_key_copy_box.setPlaceholderText(_translate("MainWindow", "Create session first"))
+ self.admin_key_label.setText(_translate("MainWindow", "Control key, contains current pusher credentials. Do not share it"))
+ self.new_connection_admin_key_copy_box.setPlaceholderText(_translate("MainWindow", "Create session first"))
+ self.collab_host_tabs.setTabText(self.collab_host_tabs.indexOf(self.collab_host_create_tab), _translate("MainWindow", "Create"))
+ self.collab_session_admin_key_box.setPlaceholderText(_translate("MainWindow", "Admin session key"))
+ self.connect_to_admin_session_button.setText(_translate("MainWindow", "Connect"))
+ self.url_to_send_admin_box.setPlaceholderText(_translate("MainWindow", "Direct, Anonfiles, YouTube or Spotify URL"))
+ self.send_to_users_admin_button.setText(_translate("MainWindow", "Send URL"))
+ self.stop_all_button_admin.setText(_translate("MainWindow", "Stop playing"))
+ self.collab_host_tabs.setTabText(self.collab_host_tabs.indexOf(self.collab_host_control_tab), _translate("MainWindow", "Control"))
+ self.filename_to_upload_box.setPlaceholderText(_translate("MainWindow", "Path to file"))
+ self.choose_upload_sound_button.setText(_translate("MainWindow", "Pick file"))
+ self.upload_sound_button.setText(_translate("MainWindow", "Upload"))
+ self.anonfiles_uploaded_url_box.setPlaceholderText(_translate("MainWindow", "Upload file first"))
+ self.collab_host_tabs.setTabText(self.collab_host_tabs.indexOf(self.collab_host_upload_tab), _translate("MainWindow", "Upload sound"))
+ self.collab_tab_widget.setTabText(self.collab_tab_widget.indexOf(self.collab_host_tab), _translate("MainWindow", "Host"))
self.download_url_box.setPlaceholderText(_translate("MainWindow", "URL (direct web file, YouTube or spotify link) or path to file"))
self.download_to_path_box.setPlaceholderText(_translate("MainWindow", "File download folder"))
self.choose_download_path_button.setText(_translate("MainWindow", "Choose path"))
@@ -635,6 +853,14 @@ class Ui_MainWindow(object):
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.pusher_app_id_label.setText(_translate("MainWindow", "app_id"))
+ self.pusher_app_id_box.setPlaceholderText(_translate("MainWindow", "1699645"))
+ self.pusher_key_label.setText(_translate("MainWindow", "key"))
+ self.pusher_key_box.setPlaceholderText(_translate("MainWindow", "0c39944565451ae335d1"))
+ self.pusher_secret_label.setText(_translate("MainWindow", "secret"))
+ self.pusher_secret_box.setPlaceholderText(_translate("MainWindow", "5011da8cb2725b4b2298"))
+ self.pusher_cluster_label.setText(_translate("MainWindow", "cluster"))
+ self.pusher_cluster_box.setPlaceholderText(_translate("MainWindow", "us"))
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.settings_tabs_widget.setTabText(self.settings_tabs_widget.indexOf(self.general_settings_tab), _translate("MainWindow", "General"))
diff --git a/gui/gui.ui b/gui/gui.ui
index e7d874f..5be809a 100644
--- a/gui/gui.ui
+++ b/gui/gui.ui
@@ -7,7 +7,7 @@
0
0
815
- 484
+ 497
@@ -1072,7 +1072,469 @@ QListWidget:item:selected {
-
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ 0
+
+
+
+ Connect
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 35
+
+
+
+ Collab session key
+
+
+
+ -
+
+
+
+ 70
+ 35
+
+
+
+ Connect
+
+
+
+
+
+
+ -
+
+
+ -
+
+
+
+ 0
+ 35
+
+
+
+ Disconnect
+
+
+
+
+
+
+
+ Host
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ 0
+
+
+
+ Create
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 35
+
+
+
+ 25
+
+
+ Collab session room name
+
+
+
+ -
+
+
+
+ 70
+ 35
+
+
+
+ Create
+
+
+
+
+
+
+ -
+
+
+ Connection key. With this key, everyone can connect to the room
+
+
+
+ -
+
+
+
+ 0
+ 35
+
+
+
+ true
+
+
+ Create session first
+
+
+
+ -
+
+
+ Control key, contains current pusher credentials. Do not share it
+
+
+
+ -
+
+
+
+ 0
+ 35
+
+
+
+ true
+
+
+ Create session first
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+ Control
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 35
+
+
+
+ Admin session key
+
+
+
+ -
+
+
+
+ 70
+ 35
+
+
+
+ Connect
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 35
+
+
+
+ Direct, Anonfiles, YouTube or Spotify URL
+
+
+
+ -
+
+
+
+ 0
+ 35
+
+
+
+ Send URL
+
+
+
+ -
+
+
+
+ 0
+ 35
+
+
+
+ Stop playing
+
+
+
+ -
+
+
+
+
+
+
+ Upload sound
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 35
+
+
+
+ Path to file
+
+
+
+ -
+
+
+
+ 70
+ 35
+
+
+
+ Pick file
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 35
+
+
+
+ Upload
+
+
+
+ -
+
+
+
+ 0
+ 35
+
+
+
+ true
+
+
+ Upload file first
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 261
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1358,7 +1820,7 @@ QListWidget:item:selected {
-
-
+
Qt::Vertical
@@ -1430,6 +1892,9 @@ QListWidget:item:selected {
-
+
+ 0
+
Spotify
@@ -1499,12 +1964,143 @@ QListWidget:item:selected {
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
Pusher
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 50
+
+
+
+ app_id
+
+
+
+ -
+
+
+
+ 0
+ 30
+
+
+
+ 1699645
+
+
+
+ -
+
+
+ key
+
+
+
+ -
+
+
+
+ 0
+ 30
+
+
+
+ 0c39944565451ae335d1
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 50
+
+
+
+ secret
+
+
+
+ -
+
+
+
+ 0
+ 30
+
+
+
+ 5011da8cb2725b4b2298
+
+
+
+ -
+
+
+ cluster
+
+
+
+ -
+
+
+
+ 0
+ 30
+
+
+
+ us
+
+
+
+
@@ -1516,7 +2112,7 @@ QListWidget:item:selected {
20
- 40
+ 0
diff --git a/gui/modules/collab/__init__.py b/gui/modules/collab/__init__.py
new file mode 100644
index 0000000..d7ed779
--- /dev/null
+++ b/gui/modules/collab/__init__.py
@@ -0,0 +1 @@
+from .handlers import *
diff --git a/gui/modules/collab/connect.py b/gui/modules/collab/connect.py
new file mode 100644
index 0000000..e7cfc44
--- /dev/null
+++ b/gui/modules/collab/connect.py
@@ -0,0 +1,43 @@
+from gui.gui import Ui_MainWindow
+import json
+import pysher
+from gui.modules.core.popup import popup
+import base64
+from modules.player.player import Player
+
+
+def on_url_music(url: str, p: Player, ui: Ui_MainWindow):
+ ui.collab_connect_logs.append(f"Received {url}")
+ p.set_media(url)
+ p.play(ui)
+
+
+def handle_connection_to_server(ui: Ui_MainWindow, p: Player):
+ ui.collab_connect_logs.append(f'Connected to {ui.receiver_creds["name"]}')
+ channel = ui.receiver.subscribe(ui.collab_session_key_box.text())
+ channel.bind('sound', lambda _: on_url_music(_, p, ui))
+ channel.bind('stop', lambda _: (p.mediaplayer_preview.stop(),
+ p.mediaplayer_out.stop()))
+
+
+def on_connect_clicked(ui: Ui_MainWindow, p: Player):
+ try:
+ creds = dict(json.loads(
+ base64.decodebytes(bytes(ui.collab_session_key_box.text().replace('-', '\n'), encoding='utf-8')
+ ).decode('utf-8').replace("'", '"')
+ ))
+ ui.collab_connect_logs.append(f'Loaded {creds["name"]}')
+ except Exception as e:
+ print(e)
+ popup("Error", 'Invalid connection key')
+ return
+
+ ui.receiver_creds = creds
+
+ ui.receiver = pysher.Pusher(
+ key=creds["key"],
+ cluster=creds["cluster"]
+ )
+ ui.receiver.connection.bind('pusher:connection_established', lambda _: handle_connection_to_server(ui, p))
+ ui.receiver.connect()
+ ui.collab_disconnect_button.setEnabled(True)
diff --git a/gui/modules/collab/create.py b/gui/modules/collab/create.py
new file mode 100644
index 0000000..1c9f4bc
--- /dev/null
+++ b/gui/modules/collab/create.py
@@ -0,0 +1,34 @@
+from gui.gui import Ui_MainWindow
+from modules.config.pusher import PusherConfig
+from gui.modules.core.popup import popup
+import base64
+from gui.modules.collab.host import connect_to_host_admin
+
+
+def on_create_session_clicked(ui: Ui_MainWindow):
+ if ui.create_session_name_box.text() == "":
+ popup("Error", "Specify room name")
+ return
+
+ connection_key = base64.encodebytes(
+ bytes(str(
+ {
+ "name": ui.create_session_name_box.text(),
+ "key": PusherConfig.get().key,
+ "cluster": PusherConfig.get().cluster
+ }
+ ), encoding='utf-8')).decode('utf-8').strip().replace('\n', '-')
+
+ ui.new_connection_key_copy_box.setText(connection_key)
+
+ admin_key = base64.encodebytes(
+ bytes(str(
+ {
+ "connection_key": connection_key,
+ "app_id": PusherConfig.get().app_id,
+ "secret": PusherConfig.get().secret
+ }
+ ), encoding='utf-8')).decode('utf-8').strip().replace('\n', '-')
+ ui.new_connection_admin_key_copy_box.setText(admin_key)
+ ui.collab_session_admin_key_box.setText(admin_key)
+ connect_to_host_admin(ui)
diff --git a/gui/modules/collab/handlers.py b/gui/modules/collab/handlers.py
new file mode 100644
index 0000000..bb2dd2a
--- /dev/null
+++ b/gui/modules/collab/handlers.py
@@ -0,0 +1,50 @@
+from gui.gui import Ui_MainWindow
+from PyQt5.QtWidgets import QFileDialog
+from modules.player.player import Player
+from modules.anonfiles.anonfiles import Anonfiles
+from ezzthread import threaded
+from gui.modules.core.qt_updater import call
+from gui.modules.collab import create, host, connect
+
+
+def register_handlers(ui: Ui_MainWindow, p: Player):
+ ui.send_to_users_admin_button.setEnabled(False)
+ ui.collab_disconnect_button.setEnabled(False)
+ ui.stop_all_button_admin.setEnabled(False)
+
+ ui.create_session_button.clicked.connect(
+ lambda: create.on_create_session_clicked(ui)
+ )
+
+
+ ui.connect_to_admin_session_button.clicked.connect(
+ lambda: host.connect_to_host_admin(ui)
+ )
+ ui.send_to_users_admin_button.clicked.connect(
+ lambda: host.on_send_sound_button(ui)
+ )
+ ui.stop_all_button_admin.clicked.connect(
+ lambda: host.on_stop_sound_button(ui)
+ )
+
+
+ ui.connect_to_session_button.clicked.connect(
+ lambda: connect.on_connect_clicked(ui, p)
+ )
+ ui.collab_disconnect_button.clicked.connect(
+ lambda: (ui.receiver.disconnect(),
+ ui.collab_disconnect_button.setEnabled(False),
+ ui.collab_connect_logs.append('Disconnected'))
+ )
+
+
+ ui.choose_upload_sound_button.clicked.connect(
+ lambda: ui.filename_to_upload_box.setText(
+ QFileDialog.getOpenFileName(caption='Choose file to upload')[0]
+ )
+ )
+ ui.upload_sound_button.clicked.connect(
+ lambda: threaded(
+ call(ui.anonfiles_uploaded_url_box.setText, Anonfiles.upload(ui.filename_to_upload_box.text()).url)
+ )
+ )
diff --git a/gui/modules/collab/host.py b/gui/modules/collab/host.py
new file mode 100644
index 0000000..a57ce5b
--- /dev/null
+++ b/gui/modules/collab/host.py
@@ -0,0 +1,45 @@
+from gui.gui import Ui_MainWindow
+import pusher
+import base64
+import json
+from gui.modules.core.popup import popup
+
+
+def connect_to_host_admin(ui: Ui_MainWindow):
+ try:
+ creds = dict(json.loads(
+ base64.decodebytes(bytes(ui.collab_session_admin_key_box.text().replace('-', '\n'), encoding='utf-8')
+ ).decode('utf-8').replace("'", '"')
+ ))
+ creds_from_connection = dict(json.loads(
+ base64.decodebytes(bytes(creds['connection_key'].replace('-', '\n'), encoding='utf-8')
+ ).decode('utf-8').replace("'", '"')
+ ))
+ creds |= creds_from_connection
+ ui.control_admin_logs.append(f'Loaded {creds["name"]}')
+ except Exception as e:
+ print(e)
+ popup("Error", 'Invalid admin key')
+ return
+
+ ui.sender_creds = creds
+
+ ui.sender = pusher.Pusher(
+ app_id=creds["app_id"],
+ key=creds["key"],
+ secret=creds["secret"],
+ cluster=creds["cluster"]
+ )
+ ui.send_to_users_admin_button.setEnabled(True)
+ ui.stop_all_button_admin.setEnabled(True)
+
+
+def on_send_sound_button(ui: Ui_MainWindow):
+ ui.sender.trigger(ui.sender_creds["connection_key"], 'sound',
+ ui.url_to_send_admin_box.text())
+ ui.control_admin_logs.append(f'Sent {ui.url_to_send_admin_box.text()}')
+
+
+def on_stop_sound_button(ui: Ui_MainWindow):
+ ui.sender.trigger(ui.sender_creds["connection_key"], 'stop', None)
+ ui.control_admin_logs.append(f'Stopped sounds')
diff --git a/gui/modules/download/downloader.py b/gui/modules/download/downloader.py
index a819769..bf7c709 100644
--- a/gui/modules/download/downloader.py
+++ b/gui/modules/download/downloader.py
@@ -13,30 +13,35 @@ import os
@threaded
def download_track(ui: Ui_MainWindow):
- url = ui.download_url_box.text()
+ try:
+ url = ui.download_url_box.text()
- if not validators.url(url):
- call(ui.download_track_logs.append, f"{url} is not valid URL, skipping")
- return
+ if not validators.url(url):
+ call(ui.download_track_logs.append, f"{url} is not valid URL, skipping")
+ return
- call(ui.download_track_logs.append, f"Downloading {url}")
+ call(ui.download_track_logs.append, f"Downloading {url}")
- name = (lambda song: song.artist + " - " + song.name + ".mp3")(Spotify().get_song(url)) \
- if "spotify" in url or "youtu" in url else url.split('/')[-1]
+ name = (lambda song: song.artist + " - " + song.name + ".mp3")(Spotify().get_song(url)) \
+ if "spotify" in url or "youtu" in url else url.split('/')[-1]
- url = convert.get_raw_link(url)
+ url = convert.get_raw_link(url)
- call(ui.download_track_button.setEnabled, False)
+ call(ui.download_track_button.setEnabled, False)
- response = urlopen(url)
- call(ui.download_track_progress.setValue, 0)
- size = int(response.info()["Content-length"])
- downloaded = 0
- with open(os.path.join(ui.download_to_path_box.text(), name), "wb") as dest_file:
- for data in iter(partial(response.read, 4096), b""):
- downloaded += len(data)
- dest_file.write(data)
- call(ui.download_track_progress.setValue, int(downloaded / size * 100))
+ response = urlopen(url)
+ call(ui.download_track_progress.setValue, 0)
+ size = int(response.info()["Content-length"])
+ downloaded = 0
+ with open(os.path.join(ui.download_to_path_box.text(), name), "wb") as dest_file:
+ for data in iter(partial(response.read, 4096), b""):
+ downloaded += len(data)
+ dest_file.write(data)
+ call(ui.download_track_progress.setValue, int(downloaded / size * 100))
- call(ui.download_track_button.setEnabled, True)
- call(ui.download_track_logs.append, f"Downloaded to {os.path.join(ui.download_to_path_box.text(), name)}")
+ call(ui.download_track_button.setEnabled, True)
+ call(ui.download_track_logs.append, f"Downloaded to {os.path.join(ui.download_to_path_box.text(), name)}")
+ except Exception as e:
+ print(e)
+ call(ui.download_track_button.setEnabled, True)
+ call(ui.download_track_logs.append, f"Failed")
diff --git a/gui/modules/handlers/register.py b/gui/modules/handlers/register.py
index 39bf4a9..73507a2 100644
--- a/gui/modules/handlers/register.py
+++ b/gui/modules/handlers/register.py
@@ -9,6 +9,7 @@ from gui.modules import explorer
from gui.modules import collections
from gui.modules import stream
from gui.modules import download
+from gui.modules import collab
from modules.player.player import Player
from modules.restream.restream import Restreamer
@@ -23,3 +24,4 @@ def register_handlers(ui: Ui_MainWindow, MainWindow: QMainWindow, p: Player, rs:
collections.register_handlers(ui, p)
stream.register_handlers(ui, p)
download.register_handlers(ui)
+ collab.register_handlers(ui, p)
diff --git a/gui/modules/initialize/fill_settings.py b/gui/modules/initialize/fill_settings.py
index 719242c..ceb0117 100644
--- a/gui/modules/initialize/fill_settings.py
+++ b/gui/modules/initialize/fill_settings.py
@@ -1,5 +1,6 @@
from gui.gui import Ui_MainWindow
from modules.config import Config
+from modules.config.pusher import PusherConfig
from modules.spotify.config import SpotifyConfig
from modules.restream import get_streaming_devices
from modules.player.player import get_devices, get_instance, get_player
@@ -41,4 +42,9 @@ def fill_settings(ui: Ui_MainWindow):
ui.spotify_client_id_box.setText(SpotifyConfig.get().client_id)
ui.spotify_client_secret_box.setText(SpotifyConfig.get().client_secret)
+ ui.pusher_app_id_box.setText(PusherConfig.get().app_id)
+ ui.pusher_key_box.setText(PusherConfig.get().key)
+ ui.pusher_secret_box.setText(PusherConfig.get().secret)
+ ui.pusher_cluster_box.setText(PusherConfig.get().cluster)
+
ui.use_original_streaming_method_check.setChecked(Config.get().direct_stream)
diff --git a/gui/modules/settings/handlers.py b/gui/modules/settings/handlers.py
index 840d5a9..bf6d011 100644
--- a/gui/modules/settings/handlers.py
+++ b/gui/modules/settings/handlers.py
@@ -1,5 +1,6 @@
from gui.gui import Ui_MainWindow
from modules.config import Config
+from modules.config.pusher import PusherConfig
from modules.spotify.config import SpotifyConfig
import shutil
@@ -30,6 +31,19 @@ def register_handlers(ui: Ui_MainWindow):
lambda: SpotifyConfig.update("client_secret", ui.spotify_client_secret_box.text())
)
+ ui.pusher_app_id_box.textChanged.connect(
+ lambda: PusherConfig.update("app_id", ui.pusher_app_id_box.text())
+ )
+ ui.pusher_key_box.textChanged.connect(
+ lambda: PusherConfig.update("key", ui.pusher_key_box.text())
+ )
+ ui.pusher_secret_box.textChanged.connect(
+ lambda: PusherConfig.update("secret", ui.pusher_secret_box.text())
+ )
+ ui.pusher_cluster_box.textChanged.connect(
+ lambda: PusherConfig.update("cluster", ui.pusher_cluster_box.text())
+ )
+
ui.use_original_streaming_method_check.stateChanged.connect(
lambda: Config.update("direct_stream", ui.use_original_streaming_method_check.isChecked())
)
diff --git a/modules/anonfiles/__init__.py b/modules/anonfiles/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/modules/anonfiles/anonfiles.py b/modules/anonfiles/anonfiles.py
new file mode 100644
index 0000000..2ecb9a2
--- /dev/null
+++ b/modules/anonfiles/anonfiles.py
@@ -0,0 +1,35 @@
+import requests
+from dataclasses import dataclass
+from Direct_Download import Direct
+
+
+@dataclass
+class File:
+ url: str | None
+ id: str | None
+ name: str | None
+
+
+class Anonfiles:
+ @staticmethod
+ def upload(path: str) -> File | None:
+ try:
+ r = requests.post("https://api.anonfiles.com/upload", files={'file': open(path, 'rb')}).json()
+ if not r["status"]:
+ return
+
+ return File(url=r["data"]["file"]["url"]["full"],
+ id=r["data"]["file"]["metadata"]["id"],
+ name=r["data"]["file"]["metadata"]["name"])
+
+ except Exception as e:
+ print(e)
+ return File(None, None, None)
+
+ @staticmethod
+ def get_direct(url: str) -> str | None:
+ try:
+ return Direct().anonfiles(url)['directDownload']
+
+ except Exception as e:
+ print(e)
diff --git a/modules/config/model.py b/modules/config/model.py
index b585141..8074e72 100644
--- a/modules/config/model.py
+++ b/modules/config/model.py
@@ -22,3 +22,12 @@ class PathsModel:
first_browser_path: str
second_browser_path: str
collections_list: List[str]
+
+
+@dataclass_json
+@dataclass(frozen=True)
+class PusherModel:
+ app_id: str
+ key: str
+ secret: str
+ cluster: str
diff --git a/modules/config/pusher.py b/modules/config/pusher.py
new file mode 100644
index 0000000..b6a4541
--- /dev/null
+++ b/modules/config/pusher.py
@@ -0,0 +1,45 @@
+from modules.config.model import PusherModel
+import json
+import os
+
+
+class PusherConfig:
+ @staticmethod
+ def default():
+ return {
+ "app_id": str(),
+ "key": str(),
+ "secret": str(),
+ "cluster": str()
+ }
+
+ @staticmethod
+ def fix() -> None:
+ try:
+ with open("data/config.pusher", "w") as file:
+ json.dump(PusherConfig.default(), file)
+ except FileNotFoundError:
+ if not os.path.exists('data'):
+ os.mkdir('data')
+ PusherConfig.fix()
+
+ @staticmethod
+ def get() -> PusherModel:
+ try:
+ with open("data/config.pusher", "r") as file:
+ return PusherModel.from_dict(json.load(file))
+ except:
+ PusherConfig.fix()
+ return PusherConfig.get()
+
+ @staticmethod
+ def update(key: str, value: str | list | None) -> dict:
+ with open("data/config.pusher", "r") as file:
+ settings = json.load(file)
+
+ settings[key] = value
+
+ with open("data/config.pusher", "w") as file:
+ json.dump(settings, file)
+
+ return settings
diff --git a/modules/player/convert.py b/modules/player/convert.py
index a030816..5f4a1fc 100644
--- a/modules/player/convert.py
+++ b/modules/player/convert.py
@@ -6,17 +6,19 @@ import pafy
import hashlib
import os
from modules.spotify.spotify_dl import Spotify
+from modules.anonfiles.anonfiles import Anonfiles
import requests
+import urllib.parse
def get_raw_link(url):
if validators.url(url):
- if 'spotify' in url:
+ if 'spotify' in url.lower():
url = Spotify().get_youtube_url(url)
- print(url)
- if 'youtu' in url:
+ if 'youtu' in url.lower():
url = pafy.new(url).getbestaudio().url
- print(url)
+ if 'anonfiles' in url.lower():
+ url = urllib.parse.quote(Anonfiles.get_direct(url), safe=':/')
return url
diff --git a/requirements.txt b/requirements.txt
index 0ca280f..e7dd2d7 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -12,4 +12,7 @@ pydub
pafy
youtube-dl==2020.12.2
ezzthread
-qt-thread-updater
\ No newline at end of file
+qt-thread-updater
+Direct-Download
+pusher
+pysher
\ No newline at end of file