mirror of
https://github.com/kokarare1212/librespot-python.git
synced 2024-10-04 18:16:54 +02:00
112 lines
3.2 KiB
Python
112 lines
3.2 KiB
Python
from __future__ import annotations
|
|
|
|
import concurrent.futures
|
|
import random
|
|
import socket
|
|
|
|
from zeroconf import ServiceBrowser
|
|
from zeroconf import ServiceInfo
|
|
from zeroconf import Zeroconf
|
|
|
|
from librespot.common import Utils
|
|
from librespot.core import Session
|
|
from librespot.crypto import DiffieHellman
|
|
from librespot.proto import Connect
|
|
from librespot.standard import Closeable
|
|
from librespot.standard import Runnable
|
|
|
|
|
|
class ZeroconfServer(Closeable):
|
|
SERVICE = "spotify-connect"
|
|
__MAX_PORT = 65536
|
|
__MIN_PORT = 1024
|
|
__EOL = "\r\n"
|
|
__keys: DiffieHellman
|
|
__inner: ZeroconfServer.Inner
|
|
|
|
def __init__(self, inner: ZeroconfServer.Inner, listen_port: int, listen_all: bool):
|
|
self.__inner = inner
|
|
self.__keys = DiffieHellman()
|
|
|
|
if listen_port == -1:
|
|
listen_port = random.randint(self.__MIN_PORT, self.__MAX_PORT)
|
|
|
|
class Builder(Session.AbsBuilder):
|
|
__listenAll = False
|
|
__listenPort = -1
|
|
|
|
def __init__(self, conf: Session.Configuration):
|
|
super().__init__(conf)
|
|
|
|
def set_listen_all(self, listen_all: bool) -> ZeroconfServer.Builder:
|
|
self.__listenAll = listen_all
|
|
return self
|
|
|
|
def set_listen_port(self, listen_port: int) -> ZeroconfServer.Builder:
|
|
self.__listenPort = listen_port
|
|
return self
|
|
|
|
def create(self) -> ZeroconfServer:
|
|
return ZeroconfServer(
|
|
ZeroconfServer.Inner(
|
|
self.device_type,
|
|
self.device_name,
|
|
self.preferred_locale,
|
|
self.conf,
|
|
self.device_id,
|
|
),
|
|
self.__listenPort,
|
|
self.__listenAll,
|
|
)
|
|
|
|
class Inner:
|
|
device_type: Connect.DeviceType = None
|
|
device_name: str = None
|
|
device_id: str = None
|
|
preferred_locale: str = None
|
|
conf = None
|
|
|
|
def __init__(
|
|
self,
|
|
device_type: Connect.DeviceType,
|
|
device_name: str,
|
|
preferred_locale: str,
|
|
conf: Session.Configuration,
|
|
device_id: str = None,
|
|
):
|
|
self.preferred_locale = preferred_locale
|
|
self.conf = conf
|
|
self.device_type = device_type
|
|
self.device_name = device_name
|
|
self.device_id = (
|
|
device_id if device_id is not None else Utils.random_hex_string(40)
|
|
)
|
|
|
|
class HttpRunner(Runnable, Closeable):
|
|
__sock: socket
|
|
__executorService: concurrent.futures.ThreadPoolExecutor = (
|
|
concurrent.futures.ThreadPoolExecutor()
|
|
)
|
|
__shouldStop: bool = False
|
|
|
|
def __init__(self, port: int):
|
|
self.__sock = socket.socket()
|
|
self.__sock.bind(("0.0.0.0", port))
|
|
self.__sock.listen(1)
|
|
|
|
def run(self) -> None:
|
|
while not self.__shouldStop:
|
|
client, address = self.__sock.accept()
|
|
|
|
def anonymous():
|
|
self.__handle(client)
|
|
client.close()
|
|
|
|
self.__executorService.submit(anonymous)
|
|
|
|
def __handle(self, client: socket.socket):
|
|
client.recv(1)
|
|
|
|
def close(self) -> None:
|
|
super().close()
|