Added configuration for the QR code
This commit is contained in:
parent
9b5b1ee9d0
commit
948bb4da5c
3 changed files with 85 additions and 20 deletions
|
@ -36,7 +36,7 @@ from socketio.exceptions import ConnectionError
|
||||||
import engineio
|
import engineio
|
||||||
from yaml import load, Loader
|
from yaml import load, Loader
|
||||||
|
|
||||||
from syng.player_libmpv import Player
|
from syng.player_libmpv import Player, QRPosition
|
||||||
|
|
||||||
from . import jsonencoder
|
from . import jsonencoder
|
||||||
from .entry import Entry
|
from .entry import Entry
|
||||||
|
@ -60,6 +60,8 @@ def default_config() -> dict[str, Optional[int | str]]:
|
||||||
"waiting_room_policy": None,
|
"waiting_room_policy": None,
|
||||||
"key": None,
|
"key": None,
|
||||||
"buffer_in_advance": 2,
|
"buffer_in_advance": 2,
|
||||||
|
"qr_box_size": 5,
|
||||||
|
"qr_position": "bottom-left",
|
||||||
"show_advanced": False,
|
"show_advanced": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +104,15 @@ class State:
|
||||||
- `None`, performers are always added to the queue.
|
- `None`, performers are always added to the queue.
|
||||||
* `buffer_in_advance` (`int`): The number of songs, that are buffered in
|
* `buffer_in_advance` (`int`): The number of songs, that are buffered in
|
||||||
advance.
|
advance.
|
||||||
|
* `qr_box_size` (`int`): The size of one box in the QR code.
|
||||||
|
* `qr_position` (`str`): The position of the QR code on the screen. One of:
|
||||||
|
- `top-left`
|
||||||
|
- `top-right`
|
||||||
|
- `bottom-left`
|
||||||
|
- `bottom-right`
|
||||||
|
* `show_advanced` (`bool`): If the advanced options should be shown in the
|
||||||
|
gui.
|
||||||
|
|
||||||
:type config: dict[str, Any]:
|
:type config: dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -128,7 +139,10 @@ class Client:
|
||||||
self.currentLock = asyncio.Semaphore(0)
|
self.currentLock = asyncio.Semaphore(0)
|
||||||
self.buffer_in_advance = config["config"]["buffer_in_advance"]
|
self.buffer_in_advance = config["config"]["buffer_in_advance"]
|
||||||
self.player = Player(
|
self.player = Player(
|
||||||
f"{config['config']['server']}/{config['config']['room']}", self.quit_callback
|
f"{config['config']['server']}/{config['config']['room']}",
|
||||||
|
1 if config["config"]["qr_box_size"] < 1 else config["config"]["qr_box_size"],
|
||||||
|
QRPosition.from_string(config["config"]["qr_position"]),
|
||||||
|
self.quit_callback,
|
||||||
)
|
)
|
||||||
self.register_handlers()
|
self.register_handlers()
|
||||||
|
|
||||||
|
|
38
syng/gui.py
38
syng/gui.py
|
@ -330,6 +330,17 @@ class OptionFrame(QWidget):
|
||||||
self.date_time_options: dict[str, tuple[QDateTimeEdit, QCheckBox]] = {}
|
self.date_time_options: dict[str, tuple[QDateTimeEdit, QCheckBox]] = {}
|
||||||
self.rows: dict[str, tuple[QLabel, QWidget | QLayout]] = {}
|
self.rows: dict[str, tuple[QLabel, QWidget | QLayout]] = {}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def option_names(self) -> set[str]:
|
||||||
|
return set(
|
||||||
|
self.string_options.keys()
|
||||||
|
| self.int_options.keys()
|
||||||
|
| self.choose_options.keys()
|
||||||
|
| self.bool_options.keys()
|
||||||
|
| self.list_options.keys()
|
||||||
|
| self.date_time_options.keys()
|
||||||
|
)
|
||||||
|
|
||||||
def get_config(self) -> dict[str, Any]:
|
def get_config(self) -> dict[str, Any]:
|
||||||
config: dict[str, Any] = {}
|
config: dict[str, Any] = {}
|
||||||
for name, textbox in self.string_options.items():
|
for name, textbox in self.string_options.items():
|
||||||
|
@ -446,15 +457,18 @@ class GeneralConfig(OptionFrame):
|
||||||
"Buffer the next songs in advance",
|
"Buffer the next songs in advance",
|
||||||
int(config["buffer_in_advance"]),
|
int(config["buffer_in_advance"]),
|
||||||
)
|
)
|
||||||
|
self.add_int_option("qr_box_size", "QR Code Box Size", int(config["qr_box_size"]))
|
||||||
|
self.add_choose_option(
|
||||||
|
"qr_position",
|
||||||
|
"QR Code Position",
|
||||||
|
["top-left", "top-right", "bottom-left", "bottom-right"],
|
||||||
|
config["qr_position"],
|
||||||
|
)
|
||||||
|
|
||||||
|
self.simple_options = ["server", "room", "secret"]
|
||||||
|
|
||||||
if not config["show_advanced"]:
|
if not config["show_advanced"]:
|
||||||
for option in [
|
for option in self.option_names.difference(self.simple_options):
|
||||||
"waiting_room_policy",
|
|
||||||
"last_song",
|
|
||||||
"preview_duration",
|
|
||||||
"key",
|
|
||||||
"buffer_in_advance",
|
|
||||||
]:
|
|
||||||
self.rows[option][0].setVisible(False)
|
self.rows[option][0].setVisible(False)
|
||||||
widget_or_layout = self.rows[option][1]
|
widget_or_layout = self.rows[option][1]
|
||||||
if isinstance(widget_or_layout, QWidget):
|
if isinstance(widget_or_layout, QWidget):
|
||||||
|
@ -518,13 +532,9 @@ class SyngGui(QMainWindow):
|
||||||
self.exportbutton.setVisible(state)
|
self.exportbutton.setVisible(state)
|
||||||
self.importbutton.setVisible(state)
|
self.importbutton.setVisible(state)
|
||||||
|
|
||||||
for option in [
|
for option in self.general_config.option_names.difference(
|
||||||
"waiting_room_policy",
|
self.general_config.simple_options
|
||||||
"last_song",
|
):
|
||||||
"preview_duration",
|
|
||||||
"key",
|
|
||||||
"buffer_in_advance",
|
|
||||||
]:
|
|
||||||
self.general_config.rows[option][0].setVisible(state)
|
self.general_config.rows[option][0].setVisible(state)
|
||||||
widget_or_layout = self.general_config.rows[option][1]
|
widget_or_layout = self.general_config.rows[option][1]
|
||||||
if isinstance(widget_or_layout, QWidget):
|
if isinstance(widget_or_layout, QWidget):
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from enum import Enum
|
||||||
import locale
|
import locale
|
||||||
import sys
|
import sys
|
||||||
from typing import Callable, Iterable, Optional, cast
|
from typing import Callable, Iterable, Optional, cast
|
||||||
|
@ -9,8 +10,35 @@ import os
|
||||||
from .entry import Entry
|
from .entry import Entry
|
||||||
|
|
||||||
|
|
||||||
|
class QRPosition(Enum):
|
||||||
|
TOP_LEFT = 1
|
||||||
|
TOP_RIGHT = 2
|
||||||
|
BOTTOM_LEFT = 3
|
||||||
|
BOTTOM_RIGHT = 4
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_string(value: str) -> "QRPosition":
|
||||||
|
match value:
|
||||||
|
case "top-left":
|
||||||
|
return QRPosition.TOP_LEFT
|
||||||
|
case "top-right":
|
||||||
|
return QRPosition.TOP_RIGHT
|
||||||
|
case "bottom-left":
|
||||||
|
return QRPosition.BOTTOM_LEFT
|
||||||
|
case "bottom-right":
|
||||||
|
return QRPosition.BOTTOM_RIGHT
|
||||||
|
case _:
|
||||||
|
return QRPosition.BOTTOM_LEFT
|
||||||
|
|
||||||
|
|
||||||
class Player:
|
class Player:
|
||||||
def __init__(self, qr_string: str, quit_callback: Callable[[], None]) -> None:
|
def __init__(
|
||||||
|
self,
|
||||||
|
qr_string: str,
|
||||||
|
qr_box_size: int,
|
||||||
|
qr_position: QRPosition,
|
||||||
|
quit_callback: Callable[[], None],
|
||||||
|
) -> None:
|
||||||
locale.setlocale(locale.LC_ALL, "C")
|
locale.setlocale(locale.LC_ALL, "C")
|
||||||
|
|
||||||
self.base_dir = f"{os.path.dirname(__file__)}/static"
|
self.base_dir = f"{os.path.dirname(__file__)}/static"
|
||||||
|
@ -19,6 +47,8 @@ class Player:
|
||||||
self.closing = False
|
self.closing = False
|
||||||
self.mpv: Optional[mpv.MPV] = None
|
self.mpv: Optional[mpv.MPV] = None
|
||||||
self.qr_overlay: Optional[mpv.ImageOverlay] = None
|
self.qr_overlay: Optional[mpv.ImageOverlay] = None
|
||||||
|
self.qr_box_size = qr_box_size
|
||||||
|
self.qr_position = qr_position
|
||||||
self.update_qr(
|
self.update_qr(
|
||||||
qr_string,
|
qr_string,
|
||||||
)
|
)
|
||||||
|
@ -47,7 +77,7 @@ class Player:
|
||||||
self.quit_callback()
|
self.quit_callback()
|
||||||
|
|
||||||
def update_qr(self, qr_string: str) -> None:
|
def update_qr(self, qr_string: str) -> None:
|
||||||
qr = QRCode(box_size=5, border=1)
|
qr = QRCode(box_size=self.qr_box_size, border=1)
|
||||||
qr.add_data(qr_string)
|
qr.add_data(qr_string)
|
||||||
qr.make()
|
qr.make()
|
||||||
self.qr = qr.make_image().convert("RGBA")
|
self.qr = qr.make_image().convert("RGBA")
|
||||||
|
@ -62,8 +92,19 @@ class Player:
|
||||||
osd_width: int = cast(int, self.mpv.osd_width)
|
osd_width: int = cast(int, self.mpv.osd_width)
|
||||||
osd_height: int = cast(int, self.mpv.osd_height)
|
osd_height: int = cast(int, self.mpv.osd_height)
|
||||||
|
|
||||||
x_pos = osd_width - self.qr.width - 10
|
match self.qr_position:
|
||||||
y_pos = osd_height - self.qr.height - 10
|
case QRPosition.BOTTOM_LEFT:
|
||||||
|
x_pos = osd_width - self.qr.width - 10
|
||||||
|
y_pos = osd_height - self.qr.height - 10
|
||||||
|
case QRPosition.BOTTOM_RIGHT:
|
||||||
|
x_pos = 10
|
||||||
|
y_pos = osd_height - self.qr.height - 10
|
||||||
|
case QRPosition.TOP_LEFT:
|
||||||
|
x_pos = osd_width - self.qr.width - 10
|
||||||
|
y_pos = 10
|
||||||
|
case QRPosition.TOP_RIGHT:
|
||||||
|
x_pos = 10
|
||||||
|
y_pos = 10
|
||||||
|
|
||||||
self.qr_overlay = self.mpv.create_image_overlay(self.qr, pos=(x_pos, y_pos))
|
self.qr_overlay = self.mpv.create_image_overlay(self.qr, pos=(x_pos, y_pos))
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue