Compare commits
5 commits
7ce4586dd2
...
266d98f12e
Author | SHA1 | Date | |
---|---|---|---|
266d98f12e | |||
fbc37ba198 | |||
8b8f2ed43b | |||
5128b90e95 | |||
2bab9c0a11 |
7 changed files with 2334 additions and 1978 deletions
1179
poetry.lock
generated
1179
poetry.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -41,7 +41,7 @@ qrcode = { version = "^7.4.2", optional = true }
|
||||||
pymediainfo = { version = "^6.1.0", optional = true }
|
pymediainfo = { version = "^6.1.0", optional = true }
|
||||||
pyyaml = { version = "^6.0.1", optional = true }
|
pyyaml = { version = "^6.0.1", optional = true }
|
||||||
alt-profanity-check = {version = "^1.4.1", optional = true}
|
alt-profanity-check = {version = "^1.4.1", optional = true}
|
||||||
pyqt6 = {version="^6.7.1", optional = true}
|
pyqt6 = {version=">=6.7.1", optional = true}
|
||||||
mpv = {version = "^1.0.7", optional = true}
|
mpv = {version = "^1.0.7", optional = true}
|
||||||
qasync = {version = "^0.27.1", optional = true}
|
qasync = {version = "^0.27.1", optional = true}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -155,12 +155,14 @@ class State:
|
||||||
waiting_room: list[Entry] = field(default_factory=list)
|
waiting_room: list[Entry] = field(default_factory=list)
|
||||||
recent: list[Entry] = field(default_factory=list)
|
recent: list[Entry] = field(default_factory=list)
|
||||||
config: dict[str, Any] = field(default_factory=default_config)
|
config: dict[str, Any] = field(default_factory=default_config)
|
||||||
|
old_config: dict[str, Any] = field(default_factory=default_config)
|
||||||
|
|
||||||
|
|
||||||
class Client:
|
class Client:
|
||||||
def __init__(self, config: dict[str, Any]):
|
def __init__(self, config: dict[str, Any]):
|
||||||
config["config"] = default_config() | config["config"]
|
config["config"] = default_config() | config["config"]
|
||||||
|
|
||||||
|
self.connection_event = asyncio.Event()
|
||||||
self.connection_state = ConnectionState()
|
self.connection_state = ConnectionState()
|
||||||
self.set_log_level(config["config"]["log_level"])
|
self.set_log_level(config["config"]["log_level"])
|
||||||
self.sio = socketio.AsyncClient(json=jsonencoder, reconnection_attempts=-1)
|
self.sio = socketio.AsyncClient(json=jsonencoder, reconnection_attempts=-1)
|
||||||
|
@ -294,6 +296,23 @@ class Client:
|
||||||
"""
|
"""
|
||||||
self.state.config = default_config() | data
|
self.state.config = default_config() | data
|
||||||
|
|
||||||
|
async def send_update_config(self) -> None:
|
||||||
|
"""
|
||||||
|
Send the current configuration to the server.
|
||||||
|
|
||||||
|
This is used to update the server with the current configuration of the
|
||||||
|
client. This is done by sending a "update_config" message to the server.
|
||||||
|
|
||||||
|
:rtype: None
|
||||||
|
"""
|
||||||
|
|
||||||
|
changes = dict()
|
||||||
|
for key, value in self.state.config.items():
|
||||||
|
if key in default_config() and default_config()[key] != value:
|
||||||
|
changes[key] = value
|
||||||
|
|
||||||
|
await self.sio.emit("update_config", self.state.config)
|
||||||
|
|
||||||
async def handle_skip_current(self, data: dict[str, Any]) -> None:
|
async def handle_skip_current(self, data: dict[str, Any]) -> None:
|
||||||
"""
|
"""
|
||||||
Handle the "skip-current" message.
|
Handle the "skip-current" message.
|
||||||
|
@ -333,6 +352,7 @@ class Client:
|
||||||
:type data: dict[str, Any]
|
:type data: dict[str, Any]
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
|
await self.connection_event.wait()
|
||||||
self.state.queue.clear()
|
self.state.queue.clear()
|
||||||
self.state.queue.extend([Entry(**entry) for entry in data["queue"]])
|
self.state.queue.extend([Entry(**entry) for entry in data["queue"]])
|
||||||
self.state.waiting_room = [Entry(**entry) for entry in data["waiting_room"]]
|
self.state.waiting_room = [Entry(**entry) for entry in data["waiting_room"]]
|
||||||
|
@ -400,6 +420,8 @@ class Client:
|
||||||
await self.sio.emit("sources", {"sources": list(self.sources.keys())})
|
await self.sio.emit("sources", {"sources": list(self.sources.keys())})
|
||||||
if self.state.current_source is None: # A possible race condition can occur here
|
if self.state.current_source is None: # A possible race condition can occur here
|
||||||
await self.sio.emit("get-first")
|
await self.sio.emit("get-first")
|
||||||
|
self.connection_event.set()
|
||||||
|
self.connection_state.set_connected()
|
||||||
|
|
||||||
async def handle_get_meta_info(self, data: dict[str, Any]) -> None:
|
async def handle_get_meta_info(self, data: dict[str, Any]) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -540,6 +562,7 @@ class Client:
|
||||||
:type data: dict[str, Any]
|
:type data: dict[str, Any]
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
|
await self.connection_event.wait()
|
||||||
if data["source"] in self.sources:
|
if data["source"] in self.sources:
|
||||||
config: dict[str, Any] | list[dict[str, Any]] = await self.sources[
|
config: dict[str, Any] | list[dict[str, Any]] = await self.sources[
|
||||||
data["source"]
|
data["source"]
|
||||||
|
@ -556,6 +579,7 @@ class Client:
|
||||||
"total": num_chunks,
|
"total": num_chunks,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
await asyncio.sleep(0.1) # Avoiding qasync errors
|
||||||
else:
|
else:
|
||||||
await self.sio.emit("config", {"source": data["source"], "config": config})
|
await self.sio.emit("config", {"source": data["source"], "config": config})
|
||||||
|
|
||||||
|
@ -602,7 +626,7 @@ class Client:
|
||||||
|
|
||||||
async def kill_mpv(self) -> None:
|
async def kill_mpv(self) -> None:
|
||||||
"""
|
"""
|
||||||
Kill the mpv process. Needs to be called in a thread, because of mpv...
|
Kill the mpv process. Needs to be called in a seperate thread, because of mpv...
|
||||||
See https://github.com/jaseg/python-mpv/issues/114#issuecomment-1214305952
|
See https://github.com/jaseg/python-mpv/issues/114#issuecomment-1214305952
|
||||||
|
|
||||||
:rtype: None
|
:rtype: None
|
||||||
|
@ -715,7 +739,6 @@ class Client:
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
loop.add_signal_handler(signal.SIGINT, partial(self.signal_handler, loop))
|
loop.add_signal_handler(signal.SIGINT, partial(self.signal_handler, loop))
|
||||||
|
|
||||||
self.connection_state.set_connected()
|
|
||||||
await self.sio.wait()
|
await self.sio.wait()
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
pass
|
pass
|
||||||
|
|
49
syng/gui.py
49
syng/gui.py
|
@ -509,7 +509,6 @@ class GeneralConfig(OptionFrame):
|
||||||
["debug", "info", "warning", "error", "critical"],
|
["debug", "info", "warning", "error", "critical"],
|
||||||
config["log_level"],
|
config["log_level"],
|
||||||
)
|
)
|
||||||
# self.add_bool_option("show_advanced", "Show Advanced Options", config["show_advanced"])
|
|
||||||
|
|
||||||
self.simple_options = ["server", "room", "secret"]
|
self.simple_options = ["server", "room", "secret"]
|
||||||
|
|
||||||
|
@ -541,6 +540,7 @@ class SyngGui(QMainWindow):
|
||||||
self.log_label_handler.cleanup()
|
self.log_label_handler.cleanup()
|
||||||
|
|
||||||
self.destroy()
|
self.destroy()
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
def add_buttons(self, show_advanced: bool) -> None:
|
def add_buttons(self, show_advanced: bool) -> None:
|
||||||
self.buttons_layout = QHBoxLayout()
|
self.buttons_layout = QHBoxLayout()
|
||||||
|
@ -608,6 +608,27 @@ class SyngGui(QMainWindow):
|
||||||
"You need to start the client before you can import a queue.",
|
"You need to start the client before you can import a queue.",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def clear_cache(self) -> None:
|
||||||
|
"""
|
||||||
|
Clear the cache directory of the client.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cache_dir = platformdirs.user_cache_dir("syng")
|
||||||
|
if os.path.exists(cache_dir):
|
||||||
|
answer = QMessageBox.question(
|
||||||
|
self,
|
||||||
|
"Clear Cache",
|
||||||
|
f"Are you sure you want to clear the cache directory at {cache_dir}?",
|
||||||
|
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
|
||||||
|
)
|
||||||
|
if answer == QMessageBox.StandardButton.Yes:
|
||||||
|
for root, dirs, files in os.walk(cache_dir, topdown=False):
|
||||||
|
for name in files:
|
||||||
|
os.remove(os.path.join(root, name))
|
||||||
|
for name in dirs:
|
||||||
|
os.rmdir(os.path.join(root, name))
|
||||||
|
QMessageBox.information(self, "Cache Cleared", "The cache has been cleared.")
|
||||||
|
|
||||||
def remove_room(self) -> None:
|
def remove_room(self) -> None:
|
||||||
if self.client is not None:
|
if self.client is not None:
|
||||||
answer = QMessageBox.question(
|
answer = QMessageBox.question(
|
||||||
|
@ -736,14 +757,26 @@ class SyngGui(QMainWindow):
|
||||||
self.remove_room_button = QPushButton("Remove Room", self.admin_tab)
|
self.remove_room_button = QPushButton("Remove Room", self.admin_tab)
|
||||||
self.remove_room_button.clicked.connect(self.remove_room)
|
self.remove_room_button.clicked.connect(self.remove_room)
|
||||||
self.admin_layout.addWidget(self.remove_room_button)
|
self.admin_layout.addWidget(self.remove_room_button)
|
||||||
|
self.remove_room_button.setDisabled(True)
|
||||||
|
|
||||||
self.export_queue_button = QPushButton("Export Queue", self.admin_tab)
|
self.export_queue_button = QPushButton("Export Queue", self.admin_tab)
|
||||||
self.export_queue_button.clicked.connect(self.export_queue)
|
self.export_queue_button.clicked.connect(self.export_queue)
|
||||||
self.admin_layout.addWidget(self.export_queue_button)
|
self.admin_layout.addWidget(self.export_queue_button)
|
||||||
|
self.export_queue_button.setDisabled(True)
|
||||||
|
|
||||||
self.import_queue_button = QPushButton("Import Queue", self.admin_tab)
|
self.import_queue_button = QPushButton("Import Queue", self.admin_tab)
|
||||||
self.import_queue_button.clicked.connect(self.import_queue)
|
self.import_queue_button.clicked.connect(self.import_queue)
|
||||||
self.admin_layout.addWidget(self.import_queue_button)
|
self.admin_layout.addWidget(self.import_queue_button)
|
||||||
|
self.import_queue_button.setDisabled(True)
|
||||||
|
|
||||||
|
self.update_config_button = QPushButton("Update Config")
|
||||||
|
self.update_config_button.clicked.connect(self.update_config)
|
||||||
|
self.admin_layout.addWidget(self.update_config_button)
|
||||||
|
self.update_config_button.setDisabled(True)
|
||||||
|
|
||||||
|
self.clear_cache_button = QPushButton("Clear Cache", self.admin_tab)
|
||||||
|
self.clear_cache_button.clicked.connect(self.clear_cache)
|
||||||
|
self.admin_layout.addWidget(self.clear_cache_button)
|
||||||
|
|
||||||
self.tabview.addTab(self.admin_tab, "Admin")
|
self.tabview.addTab(self.admin_tab, "Admin")
|
||||||
|
|
||||||
|
@ -897,9 +930,23 @@ class SyngGui(QMainWindow):
|
||||||
self.set_client_button_stop()
|
self.set_client_button_stop()
|
||||||
|
|
||||||
def set_client_button_stop(self) -> None:
|
def set_client_button_stop(self) -> None:
|
||||||
|
self.general_config.string_options["server"].setEnabled(False)
|
||||||
|
self.general_config.string_options["room"].setEnabled(False)
|
||||||
|
self.update_config_button.setDisabled(False)
|
||||||
|
self.remove_room_button.setDisabled(False)
|
||||||
|
self.export_queue_button.setDisabled(False)
|
||||||
|
self.import_queue_button.setDisabled(False)
|
||||||
|
|
||||||
self.startbutton.setText("Disconnect")
|
self.startbutton.setText("Disconnect")
|
||||||
|
|
||||||
def set_client_button_start(self) -> None:
|
def set_client_button_start(self) -> None:
|
||||||
|
self.general_config.string_options["server"].setEnabled(True)
|
||||||
|
self.general_config.string_options["room"].setEnabled(True)
|
||||||
|
self.update_config_button.setDisabled(True)
|
||||||
|
self.remove_room_button.setDisabled(True)
|
||||||
|
self.export_queue_button.setDisabled(True)
|
||||||
|
self.import_queue_button.setDisabled(True)
|
||||||
|
|
||||||
self.startbutton.setText("Connect")
|
self.startbutton.setText("Connect")
|
||||||
|
|
||||||
def start_syng_client(self) -> None:
|
def start_syng_client(self) -> None:
|
||||||
|
|
|
@ -119,7 +119,7 @@ class Queue:
|
||||||
|
|
||||||
def find_by_name(self, name: str) -> Optional[Entry]:
|
def find_by_name(self, name: str) -> Optional[Entry]:
|
||||||
"""
|
"""
|
||||||
Find an entry by its performer and return it.
|
Find the first entry by its performer and return it.
|
||||||
|
|
||||||
:param name: The name of the performer to search for.
|
:param name: The name of the performer to search for.
|
||||||
:type name: str
|
:type name: str
|
||||||
|
|
Loading…
Add table
Reference in a new issue