cleaning up, preparing for windows tests

This commit is contained in:
Christoph Stahl 2024-11-18 18:15:13 +01:00
parent e7b895888b
commit 55bedf7aa3
8 changed files with 35 additions and 140 deletions

View file

@ -42,8 +42,8 @@ pymediainfo = { version = "^6.1.0", optional = true }
pyyaml = { version = "^6.0.1", optional = true }
alt-profanity-check = {version = "^1.4.1", optional = true}
pyqt6 = {version="^6.7.1", optional = true}
mpv = "^1.0.7"
qasync = "^0.27.1"
mpv = {version = "^1.0.7", optional = true}
qasync = {version = "^0.27.1", optional = true}
[tool.poetry.group.dev.dependencies]
types-pyyaml = "^6.0.12.12"

View file

@ -5,10 +5,13 @@ mkdir -p requirements
cd requirements
# download mpv
wget https://nightly.link/mpv-player/mpv/workflows/build/master/mpv-x86_64-windows-msvc.zip
unzip mpv-x86_64-windows-msvc.zip
cp mpv.exe ../src
cp vulkan-1.dll ../src
# wget https://nightly.link/mpv-player/mpv/workflows/build/master/mpv-x86_64-windows-msvc.zip
# unzip mpv-x86_64-windows-msvc.zip
# cp mpv.exe ../src
# cp vulkan-1.dll ../src
wget https://github.com/shinchiro/mpv-winbuild-cmake/releases/download/20241118/mpv-dev-x86_64-20241118-git-e8fd7b8.7z
7z x mpv-dev-x86_64-20241118-git-e8fd7b8.7z
cp libmpv-2.dll ../src
# download ffmpeg
wget https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-full.7z
@ -27,7 +30,7 @@ cp ../icons/syng.ico src/
# rm -rf src/build
# rm -rf src/dist
# docker run --volume "$(pwd)/src:/src/" batonogov/pyinstaller-windows:latest "pyinstaller --onefile -w -i'.\syng.ico' --add-data='.\syng\static\syng.png;.\static' --add-binary '.\mpv.exe;.' --add-binary '.\vulkan-1.dll;.' --add-binary '.\ffmpeg.exe;.' syng/main.py"
docker run --volume "$(pwd)/src:/src/" batonogov/pyinstaller-windows:latest "pyinstaller -F -w -i'.\syng.ico' --add-data='.\syng.ico;.' --add-binary '.\mpv.exe;.' --add-binary '.\vulkan-1.dll;.' --add-binary '.\ffmpeg.exe;.' syng/main.py"
docker run --volume "$(pwd)/src:/src/" batonogov/pyinstaller-windows:latest "pyinstaller -w -i'.\syng.ico' --add-data='.\syng.ico;.' --add-binary '.\libmpv-2.dll;.' --add-binary '.\ffmpeg.exe;.' syng/main.py"
# cd syng-2.0.1
# wine python -m poetry install -E client

View file

@ -21,7 +21,6 @@ from logging.handlers import QueueHandler
from multiprocessing import Queue
import secrets
import string
import tempfile
import signal
from argparse import Namespace
from dataclasses import dataclass
@ -35,7 +34,6 @@ from qrcode.main import QRCode
import socketio
from socketio.exceptions import ConnectionError
import engineio
from PIL import Image
from yaml import load, Loader
from syng.player_libmpv import Player

View file

@ -5,7 +5,6 @@ import logging
from logging.handlers import QueueListener
from logging.handlers import QueueHandler
# from multiprocessing import Process, Queue
from queue import Queue
from collections.abc import Callable
from datetime import datetime
@ -13,7 +12,6 @@ import os
from functools import partial
import random
from typing import TYPE_CHECKING, Any, Optional
import threading
import secrets
import string
import signal
@ -32,7 +30,6 @@ from qasync import QEventLoop, QApplication
from PyQt6.QtCore import QTimer, Qt
from PyQt6.QtGui import QCloseEvent, QIcon, QPixmap
from PyQt6.QtWidgets import (
# QApplication,
QCheckBox,
QComboBox,
QDateTimeEdit,
@ -58,7 +55,7 @@ from qrcode.main import QRCode
import platformdirs
from . import resources # noqa
from .client import Client, create_async_and_start_client, default_config
from .client import Client, default_config
from .log import logger
from .sources import available_sources
@ -73,16 +70,6 @@ from .config import (
StrOption,
)
# try:
# from .server import run_server
#
# SERVER_AVAILABLE = True
# except ImportError:
# if TYPE_CHECKING:
# from .server import run_server
#
# SERVER_AVAILABLE = False
# TODO: ScrollableFrame
class OptionFrame(QWidget):
@ -482,14 +469,8 @@ class GeneralConfig(OptionFrame):
class SyngGui(QMainWindow):
def closeEvent(self, a0: Optional[QCloseEvent]) -> None:
# if self.syng_server is not None:
# self.syng_server.kill()
# self.syng_server.join()
# if self.syng_client is not None:
# self.syng_client.terminate()
# self.syng_client.join(1.0)
# self.syng_client.kill()
if self.client is not None:
self.client.quit_callback()
self.destroy()
@ -497,10 +478,6 @@ class SyngGui(QMainWindow):
self.buttons_layout = QHBoxLayout()
self.central_layout.addLayout(self.buttons_layout)
# self.startsyng_serverbutton = QPushButton("Start Local Server")
# self.startsyng_serverbutton.clicked.connect(self.start_syng_server)
# self.buttons_layout.addWidget(self.startsyng_serverbutton)
self.resetbutton = QPushButton("Set Config to Default")
self.exportbutton = QPushButton("Export Config")
self.importbutton = QPushButton("Import Config")
@ -521,11 +498,7 @@ class SyngGui(QMainWindow):
self.buttons_layout.addWidget(self.show_advanced_toggle)
spacer_item = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
# self.notification_label = QLabel("", self)
# spacer_item2 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
self.buttons_layout.addItem(spacer_item)
# self.buttons_layout.addWidget(self.notification_label)
# self.buttons_layout.addItem(spacer_item2)
self.savebutton = QPushButton("Save")
self.savebutton.clicked.connect(self.save_config)
@ -632,8 +605,6 @@ class SyngGui(QMainWindow):
self.setWindowIcon(QIcon(":/icons/syng.ico"))
self.loop = asyncio.get_event_loop()
# self.syng_server: Optional[threading.Thread] = None
# self.syng_client: Optional[threading.Thread] = None
self.client: Optional[Client] = None
self.syng_client_logging_listener: Optional[QueueListener] = None
@ -658,7 +629,6 @@ class SyngGui(QMainWindow):
self.setCentralWidget(self.central_widget)
# check every 500 ms if client is running
self.timer = QTimer()
self.timer.timeout.connect(self.check_if_client_is_running)
@ -781,48 +751,16 @@ class SyngGui(QMainWindow):
)
self.syng_client_logging_listener.start()
# self.syng_client = multiprocessing.Process(
# target=create_async_and_start_client, args=[config, queue]
# )
logger.addHandler(QueueHandler(queue))
self.client = Client(config)
asyncio.run_coroutine_threadsafe(self.client.start_client(config), self.loop)
# self.syng_client = threading.Thread(
# target=create_async_and_start_client, args=[config, queue, self.client]
# )
# self.syng_client.start()
self.notification_label.setText("")
self.timer.start(500)
self.set_client_button_stop()
else:
self.client.quit_callback()
# self.syng_client.join(1.0)
self.set_client_button_start()
# def start_syng_server(self) -> None:
# if self.syng_server is None:
# root_path = os.path.join(os.path.dirname(__file__), "static")
# self.syng_server = multiprocessing.Process(
# target=run_server,
# args=[
# Namespace(
# host="0.0.0.0",
# port=8080,
# registration_keyfile=None,
# root_folder=root_path,
# private=False,
# restricted=False,
# )
# ],
# )
# self.syng_server.start()
# self.startsyng_serverbutton.setText("Stop Local Server")
# else:
# self.syng_server.terminate()
# self.syng_server.join()
# self.syng_server = None
# self.startsyng_serverbutton.setText("Start Local Server")
def change_qr(self, data: str) -> None:
qr = QRCode(box_size=10, border=2)
qr.add_data(data)
@ -876,7 +814,6 @@ def run_gui() -> None:
app.setDesktopFileName("rocks.syng.Syng")
window = SyngGui()
window.show()
# app.exec()
with event_loop:
event_loop.run_forever()

View file

@ -477,8 +477,8 @@ class Server:
"source": data["source"],
"performer": data["performer"],
"ident": data["ident"],
"artist": data["artist"],
"title": data["title"],
"artist": data.get("artist", None),
"title": data.get("title", None),
},
"old_entry": {
"artist": old_entry.artist,
@ -493,7 +493,10 @@ class Server:
source_obj = state.client.sources[data["source"]]
entry = await source_obj.get_entry(
data["performer"], data["ident"], artist=data["artist"], title=data["title"]
data["performer"],
data["ident"],
artist=data.get("artist", None),
title=data.get("title", None),
)
if entry is None:

View file

@ -127,40 +127,11 @@ class Source(ABC):
"""
self.downloaded_files: defaultdict[str, DLFilesEntry] = defaultdict(DLFilesEntry)
self._masterlock: asyncio.Lock = asyncio.Lock()
# self.player: Optional[asyncio.subprocess.Process] = None
self._index: list[str] = config["index"] if "index" in config else []
self.extra_mpv_arguments: list[str] = []
self.extra_mpv_options: dict[str, str] = {}
self._skip_next = False
@staticmethod
async def play_mpv(
video: str, audio: Optional[str], /, *options: str
) -> asyncio.subprocess.Process:
"""
Create a mpv process to play a song in full screen.
:param video: Location of the video part.
:type video: str
:param audio: Location of the audio part, if it exists.
:type audio: Optional[str]
:param options: Extra arguments forwarded to the mpv player
:type options: str
:returns: An async reference to the process
:rtype: asyncio.subprocess.Process
"""
args = ["--fullscreen", *options, video] + ([f"--audio-file={audio}"] if audio else [])
# print(f"File is {video=} and {audio=}")
mpv_process = asyncio.create_subprocess_exec(
"mpv",
*args,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
)
return await mpv_process
async def get_entry(
self,
performer: str,
@ -299,22 +270,10 @@ class Source(ABC):
entry.skip = True
return
extra_options = (
(self.extra_mpv_arguments + [mpv_options])
if mpv_options
else self.extra_mpv_arguments
)
# self.player = await self.play_mpv(
# self.downloaded_files[entry.ident].video,
# self.downloaded_files[entry.ident].audio,
# *extra_options,
# )
await player.play(
self.downloaded_files[entry.ident].video, self.downloaded_files[entry.ident].audio
)
# await self.player.wait()
# self.player = None
if self._skip_next:
self._skip_next = False
entry.skip = True
@ -339,9 +298,6 @@ class Source(ABC):
buffer_task.cancel()
self.downloaded_files[entry.ident].ready.set()
# if self.player is not None:
# self.player.kill()
async def ensure_playable(self, entry: Entry) -> tuple[str, Optional[str]]:
"""
Guaranties that the given entry can be played.

View file

@ -103,12 +103,6 @@ class YouTube:
:type search_result: dict[str, Any]
"""
url = search_result["url"]
# cls.__cache__[url] = {
# "duration": int(search_result["duration"]),
# "title": search_result["title"],
# "channel": search_result["channel"],
# "url": url,
# }
return cls(url, info=search_result)
@ -255,15 +249,6 @@ class YoutubeSource(Source):
:rtype: None
"""
if self.start_streaming and not self.downloaded_files[entry.ident].complete:
# self.player = await self.play_mpv(
# entry.ident,
# None,
# "--script-opts=ytdl_hook-ytdl_path=yt-dlp,ytdl_hook-exclude='%.pls$'",
# f"--ytdl-format={self.formatstring}",
# "--fullscreen",
# mpv_options,
# )
# await self.player.wait()
await player.play(entry.ident)
else:
await super().play(entry, player, mpv_options)

View file

@ -1,4 +1,17 @@
from asyncio import AbstractEventLoop
from types import TracebackType
from typing import Optional
import PyQt6.QtWidgets
from asyncio import BaseEventLoop
class QApplication:
class QApplication(PyQt6.QtWidgets.QApplication):
def __init__(self, argv: list[str]) -> None: ...
class QEventLoop(BaseEventLoop):
def __init__(self, app: QApplication) -> None: ...
def __enter__(self) -> None: ...
def __exit__(
self,
exc_type: Optional[type[BaseException]],
exc_value: Optional[BaseException],
traceback: Optional[TracebackType],
) -> None: ...