implement player *partial

This commit is contained in:
kokarare1212 2021-09-14 21:05:52 +09:00
parent 1d390c72a3
commit 6382c13fd0
No known key found for this signature in database
GPG Key ID: 9FB32C7C7D874F7A
2 changed files with 113 additions and 0 deletions

View File

@ -834,6 +834,12 @@ class Session(Closeable, MessageListener, SubListener):
def device_id(self) -> str:
return self.__inner.device_id
def device_name(self) -> str:
return self.__inner.device_name
def device_type(self) -> Connect.DeviceType:
return self.__inner.device_type
def event(self, resp: MercuryClient.Response) -> None:
if resp.uri == "spotify:user:attributes:update":
attributes_update = UserAttributesUpdate()

View File

@ -1,5 +1,95 @@
from __future__ import annotations
from librespot import Version
from librespot.audio.decoders import AudioQuality
from librespot.core import Session
from librespot.mercury import MercuryRequests
from librespot.proto import Connect_pb2 as Connect
from librespot.structure import Closeable, MessageListener, RequestListener
import concurrent.futures
import logging
import typing
import urllib.parse
class DeviceStateHandler(Closeable, MessageListener, RequestListener):
logger = logging.getLogger("Librespot:DeviceStateHandler")
__closing = False
__connection_id: str = None
__device_info: Connect.DeviceInfo
__put_state: Connect.PutStateRequest
__put_state_worker = concurrent.futures.ThreadPoolExecutor()
__session: Session
def __init__(self, session: Session, conf: PlayerConfiguration):
self.__session = session
self.__device_info = self.initialize_device_info(session, conf)
self.__put_state = Connect.PutStateRequest(
device=Connect.Device(
device_info=self.__device_info,
),
member_type=Connect.MemberType.CONNECT_STATE,
)
self.__session.dealer().add_message_listener(self, ["hm://pusher/v1/connections/", "hm://connect-state/v1/connect/volume", "hm://connect-state/v1/cluster"])
self.__session.dealer().add_request_listener(self, "hm://connect-state/v1/")
def close(self) -> None:
self.__closing = True
self.__session.dealer().remove_message_listener(self)
self.__session.dealer().remove_request_listener(self)
self.__put_state_worker.shutdown()
def initialize_device_info(self, session: Session, conf: PlayerConfiguration) -> Connect.Device:
return Connect.DeviceInfo(
can_play=True,
capabilities=Connect.Capabilities(
can_be_player=True,
command_acks=True,
is_controllable=True,
is_observable=True,
gaia_eq_connect_id=True,
needs_full_player_state=False,
supported_types=["audio/episode", "audio/track"],
supports_command_request=True,
supports_gzip_pushes=True,
supports_logout=True,
supports_playlist_v2=True,
supports_rename=False,
supports_transfer_command=True,
volume_steps=conf.volume_steps,
),
client_id=MercuryRequests.keymaster_client_id,
device_id=session.device_id(),
device_software_version=Version.version_string(),
device_type=session.device_type(),
name=session.device_name(),
spirc_version="3.2.6",
volume=conf.initial_volume,
)
def put_connect_state(self, request: Connect.PutStateRequest):
self.__session.api().put_connect_state(self.__connection_id, request)
self.logger.info("Put state. [ts: {}, connId: {}, reason: {}]".format(request.client_side_timestamp, self.__connection_id, request.put_state_reason))
def update_connection_id(self, newer: str) -> None:
newer = urllib.parse.unquote(newer)
if self.__connection_id is None or self.__connection_id != newer:
self.__connection_id = newer
self.logger.debug("Updated Spotify-Connection-Id: {}".format(newer))
class Player:
volume_max = 65536
__conf: PlayerConfiguration
__session: Session
__state: StateWrapper
def __init__(self, conf: PlayerConfiguration, session: Session):
self.__conf = conf
self.__session = session
def init_state(self) -> None:
self.__state = StateWrapper(self.__session, self, self.__conf)
class PlayerConfiguration:
@ -85,3 +175,20 @@ class PlayerConfiguration:
self.initial_volume,
self.volume_steps,
)
class StateWrapper(MessageListener):
__conf: PlayerConfiguration
__device: DeviceStateHandler
__player: Player
__session: Session
def __init__(self, session: Session, player: Player, conf: PlayerConfiguration):
self.__session = session
self.__player = player
self.__device = DeviceStateHandler(session, conf)
self.__conf = conf
session.dealer().add_message_listener(self, ["spotify:user:attributes:update", "hm://playlist/", "hm://collection/collection/" + session.username() + "/json"])
def on_message(self, uri: str, headers: typing.Dict[str, str], payload: bytes):
pass