view src/light9/ascoltami/webapp.py @ 2439:06da5db2fafe

rewrite ascoltami to use the graph for more playback data
author drewp@bigasterisk.com
date Thu, 30 May 2024 01:08:07 -0700
parents cc69faa87c27
children
line wrap: on
line source

"""
this module shouldn't be necessary for playback to work
"""
import logging
import socket
import subprocess
from dataclasses import dataclass
from typing import Callable
from typing import Literal as Lit

from rdfdb.syncedgraph.syncedgraph import SyncedGraph
from rdflib import URIRef
from starlette.requests import Request
from starlette.responses import JSONResponse, PlainTextResponse

from light9.ascoltami.player import Player, PlayerState
from light9.ascoltami.playlist import Playlist
from light9.showconfig import showUri

log = logging.getLogger("web")


@dataclass
class PlayerState2(PlayerState):
    song2: URIRef | None = None
    nextAction: Lit["finish"] | Lit['disabled'] | Lit['play'] = 'disabled'


@dataclass
class WebHandlers:
    graph: SyncedGraph
    show: URIRef
    player: Player
    playlist: Playlist
    getPlayerState: Callable[[], PlayerState]

    # _keep:list=field(default_factory=list)
    async def get_config(self, request: Request) -> JSONResponse:
        return JSONResponse(
            dict(
                host=socket.gethostname(),
                show=str(showUri()),
                times={
                    # these are just for the web display. True values are on Player.__init__
                    'intro': 4,
                    'post': 0
                }))

    async def post_time(self, request: Request) -> PlainTextResponse:
        """
        post a json object with {pause: true} or {resume: true} if you
        want those actions. Use {t: <seconds>} to seek, optionally
        with a pause/resume command too.
        """
        params = await request.json()
        if params.get('pause', False):
            self.player.pause()
        if params.get('resume', False):
            self.player.resume()
        if 't' in params:
            self.player.seek(params['t'])
        return PlainTextResponse("ok")

    async def get_songs(self, request: Request) -> JSONResponse:

        songs_data = [
            {  #
                "uri": s,
                "path": self.playlist.fileUri(s),
                "label": self.playlist.label(s),
            } for s in self.playlist.allSongs()
        ]

        return JSONResponse({"songs": songs_data})

    async def post_song(self, request: Request) -> PlainTextResponse:
        """post a uri of song to switch to (and seek to 0)"""

        song_uri = URIRef((await request.body()).decode('utf8'))
        self.player.setSong(self.playlist.fileUri(song_uri))

        return PlainTextResponse("ok")

    async def post_seekPlayOrPause(self, request: Request) -> PlainTextResponse:
        """curveCalc's ctrl-p or a vidref scrub"""

        data = await request.json()
        if 'scrub' in data:
            self.player.pause()
            self.player.seek(data['scrub'])
            return PlainTextResponse("ok")
        if 'action' in data:
            if data['action'] == 'play':
                self.player.resume()
            elif data['action'] == 'pause':
                self.player.pause()
            else:
                raise NotImplementedError
            return PlainTextResponse("ok")
        if self.player.isPlaying():
            self.player.pause()
        else:
            self.player.seek(data['t'])
            self.player.resume()

        return PlainTextResponse("ok")

    async def post_output(self, request: Request) -> PlainTextResponse:
        d = await request.json()
        subprocess.check_call(["bin/movesinks", str(d['sink'])])
        return PlainTextResponse("ok")

    async def post_goButton(self, request: Request) -> PlainTextResponse:
        """
        if music is playing, this silently does nothing.
        """

        if self.player.isAutostopped():
            self.player.resume()
        elif self.player.isPlaying():
            pass
        else:
            self.player.resume()
        return PlainTextResponse("ok")