From: Christian Heller Date: Sun, 22 Dec 2024 13:21:27 +0000 (+0100) Subject: Don't start right into playback, simplify player control. X-Git-Url: https://plomlompom.com/repos/%7B%7Bprefix%7D%7D/condition_titles?a=commitdiff_plain;h=55a5b3c4ea2b39a6c5761905ceeab7a5f11cf623;p=ytplom Don't start right into playback, simplify player control. --- diff --git a/src/templates/_base.tmpl b/src/templates/_base.tmpl index 62483a3..aa190a9 100644 --- a/src/templates/_base.tmpl +++ b/src/templates/_base.tmpl @@ -54,12 +54,14 @@ function player_command(command) { send_to({command: [command]}, PATH_PLAYER); } event_handlers.push(function(data) { // update player state - for (const [id, text] of [["playing_tags", data.title_tags ? `(tags: ${data.title_tags})` : ""], - ["a_playing", data.title], - ["player_state", data.running ? (data.paused ? "paused" : "playing") : "stopped"], - ["btn_pause", data.paused ? "resume" : "pause"], - ["btn_stop", data.running ? "stop" : "play"]]) { + for (const [id, text] of [ + ["playing_tags", data.title_tags ? `(tags: ${data.title_tags})` : ""], + ["a_playing", data.title], + ["player_state", data.is_running ? (data.is_playing ? "playing:" : "paused:") : "stopped" + (data.title ? ':' : '')], + ["btn_play", data.is_playing ? "pause" : "play"]]) { document.getElementById(id).textContent = text; } + for (const btn of document.getElementsByClassName("btn_if_can_play")) { + btn.disabled = !data.can_play; } document.getElementById("a_playing").href = data.title_digest ? `${PATH_PREFIX_FILE}${data.title_digest}` : PATH_PLAYLIST ; }) {% block script %} @@ -80,11 +82,10 @@ td, th { vertical-align: top; text-align: left; } · {{ macros.link_if("files" != selected, page_names.files) }} · {{ macros.link_if("yt_queries" != selected, page_names.yt_queries, "queries") }}
- - - - -· : + + + +·
{% block body %} {% endblock %} diff --git a/src/ytplom/http.py b/src/ytplom/http.py index c31d62b..7f4780f 100644 --- a/src/ytplom/http.py +++ b/src/ytplom/http.py @@ -144,16 +144,14 @@ class _TaskHandler(BaseHTTPRequestHandler): def _receive_player_command(self, postvars: _ReqMap) -> None: command = postvars.first_for('command') - if 'pause' == command: - self.server.player.toggle_pause() + if 'play' == command: + self.server.player.toggle_play() elif 'prev' == command: self.server.player.prev() elif 'next' == command: self.server.player.next() - elif 'stop' == command: - self.server.player.toggle_run() elif 'reload' == command: - self.server.player.load_files_and_start() + self.server.player.load_files_and_mpv() elif command.startswith('jump_'): self.server.player.jump_to(int(command.split('_')[1])) elif command.startswith('up_'): @@ -358,8 +356,6 @@ class _TaskHandler(BaseHTTPRequestHandler): headers=[(_HEADER_CONTENT_TYPE, _HEADER_APP_JSON)]) def _send_playlist(self) -> None: - if self.server.player.empty: - self.server.player.load_files_and_start() self._send_rendered_template( _NAME_TEMPLATE_PLAYLIST, {'selected': 'playlist', @@ -370,7 +366,7 @@ class _TaskHandler(BaseHTTPRequestHandler): self._send_http(headers=[(_HEADER_CONTENT_TYPE, 'text/event-stream'), ('Cache-Control', 'no-cache'), ('Connection', 'keep-alive')]) - playing: Optional[VideoFile] = None + selected: Optional[VideoFile] = None last_sent = '' payload: dict[str, Any] = {} time_last_write = 0.0 @@ -387,29 +383,29 @@ class _TaskHandler(BaseHTTPRequestHandler): time_last_write = time() payload.clear() if not self.server.player.current_digest: - playing = None - elif ((not playing) - or (playing.digest != self.server.player.current_digest)): + selected = None + elif ((not selected) + or (selected.digest != self.server.player.current_digest)): with DbConn() as conn: - playing = VideoFile.get_one_with_whitelist_tags_display( + selected = VideoFile.get_one_with_whitelist_tags_display( conn, self.server.player.current_digest, self.server.config.whitelist_tags_display) if last_sent < self.server.player.last_update: last_sent = self.server.player.last_update title, tags, digest = '', '', '' - if playing: - tags = playing.tags_showable.joined - title = str(playing.rel_path) - digest = playing.digest.b64 - payload['last_update'] = self.server.player.last_update - payload['running'] = self.server.player.is_running - payload['paused'] = self.server.player.is_paused - payload['idx'] = self.server.player.idx + if selected: + tags = selected.tags_showable.joined + title = str(selected.rel_path) + digest = selected.digest.b64 + payload['is_running'] = self.server.player.is_running + payload['is_playing'] = self.server.player.is_playing + payload['can_play'] = self.server.player.can_play payload['title_tags'] = tags payload['title_digest'] = digest payload['title'] = title if 'playlist' in params.as_dict: + payload['idx'] = self.server.player.idx payload['playlist_files'] = [ {'rel_path': str(f.rel_path), 'digest': f.digest.b64} for f in self.server.player.playlist] diff --git a/src/ytplom/misc.py b/src/ytplom/misc.py index 3671779..86254bf 100644 --- a/src/ytplom/misc.py +++ b/src/ytplom/misc.py @@ -521,7 +521,7 @@ class Player: self._monitoring_kill: bool = False self._kill_queue: Queue = Queue() self.playlist: list[VideoFile] = [] - self.load_files_and_start() + self.load_files_and_mpv() def _signal_update(self) -> None: """Update .last_update as signal player state has changed relevantly""" @@ -598,9 +598,8 @@ class Player: for path in [f.full_path for f in self.playlist]: self._mpv.command('loadfile', path, 'append') self._idx = 0 - self._play_at_index() - def load_files_and_start(self) -> None: + def load_files_and_mpv(self) -> None: """Collect filtered files into playlist, shuffle, start player.""" with DbConn() as conn: known_files = { @@ -625,11 +624,6 @@ class Player: """Read-only access to ._idx.""" return self._idx - @property - def empty(self) -> bool: - """Return if playlist empty.""" - return 0 == len(self.playlist) - @property def current_digest(self) -> Optional[Hash]: """Return hash digest ID of currently playing file.""" @@ -639,29 +633,30 @@ class Player: @property def is_running(self) -> bool: - """Return if player is running/available.""" - return bool(self._mpv) + """Return if player is up and has "playing" (possibly paused) title.""" + return bool(self._mpv + and len(self._mpv.playlist) > self._idx + and 'playing' in self._mpv.playlist[self._idx]) @property - def is_paused(self) -> bool: - """Return if player is paused.""" - if self._mpv: - return self._mpv.pause - return False + def is_playing(self) -> bool: + """Return if currently playing (non-paused).""" + return bool(self._mpv and self.is_running and not self._mpv.pause) - def toggle_run(self) -> None: - """Toggle player running.""" - if self._mpv: - self._kill_mpv() - else: - self._start_mpv() - self._signal_update() + @property + def can_play(self) -> bool: + """Return if playlist non-empty.""" + return len(self.playlist) > 0 - def toggle_pause(self) -> None: - """Toggle player pausing.""" - if self._mpv: + def toggle_play(self) -> None: + """Toggle playback, i.e. player pause _if_ playing, else start play.""" + if not self._mpv: + self._start_mpv() + assert self._mpv is not None + if 'playing' in self._mpv.playlist[self._idx]: self._mpv.pause = not self._mpv.pause - self._signal_update() + else: + self._play_at_index() def prev(self) -> None: """Move player to previous item in playlist."""