{% macro _link_if(cond, target, display_name = false ) %}{% if cond %}<a href="/{{target}}">{% endif %}{% if display_name %}{{display_name}}{% else %}{{target}}{% endif %}{% if cond %}</a>{% endif %}{% endmacro %}
 
 
-{% macro nav_head(page_names, selected="") %}
-<p>
+{% macro nav_head(page_names, redir_target, player_state, selected="") %}
+<form action="/player" method="POST">
+<input type="hidden" name="redir_target" value="{{redir_target}}" />
 {{ _link_if("playlist" != selected, page_names.playlist) }}
 ·
 {{ _link_if("files" != selected, page_names.files) }}
 ·
 {{ _link_if("yt_queries" != selected, page_names.yt_queries, "queries") }}
-</p>
+|
+<input type="submit" name="pause" value="{% if player_state.paused %}resume{% else %}pause{% endif %}">
+<input type="submit" name="prev" value="prev">
+<input type="submit" name="next" value="next">
+<input type="submit" name="stop" value="{% if player_state.running %}stop{% else %}start{% endif %}">
+{% if player_state.running %}{% if player_state.paused %}PAUSED{% else %}PLAYING{% endif %}{% else %}STOPPED{% endif %}: {{player_state.title}}
+</form>
 <hr />
 {% endmacro %}
 
 <form action="/{{page_names.file}}/{{file.digest.b64}}" method="POST" />
 <input type="hidden" name="redir_target" value="{{redir_target}}" />
 <table>
+{% if playlist_view %}
+<tr><th colspan=2 class="screen_half_titles">current selection</th></tr>
+{% endif %}
 <tr><th>path:</th><td class="top_field">{% if playlist_view %}<a href="/{{page_names.file}}/{{file.digest.b64}}">{% endif %}{{file.rel_path}}{% if playlist_view %}</a>{% endif %}</td></tr>
 {% if not playlist_view %}
 <tr><th>present:</th><td>{% if file.present %}<a href="/{{page_names.download}}/{{file.yt_id}}">yes</a>{% else %}no{% endif %}</td></tr>
 
 
 
 {% block css %}
-#status { font-weight: bold; }
 td.screen_half { width: 50%; }
-tr.screen_half_titles>th { text-align: center; }
+th.screen_half_titles { text-align: center; }
 td.entry_buttons { width: 5em; }
 td.tag_checkboxes { width: 1em; }
 {% endblock %}
 
 
 {% block body %}
-{{ macros.nav_head(page_names, "playlist") }}
+{{ macros.nav_head(page_names, redir_target, player_state, "playlist") }}
 <table>
-<tr><td id="status" colspan=2>
-<form action="{{redir_target}}" method="POST">
-<input type="submit" name="pause" autofocus value="{% if paused %}resume{% else %}pause{% endif %}">
-<input type="submit" name="prev" value="prev">
-<input type="submit" name="next" value="next">
-<input type="submit" name="stop" value="{% if running %}stop{% else %}start{% endif %}">
-<input type="submit" name="reload" value="reload">
-{% if running %}{% if pause %}PAUSED{% else %}PLAYING{% endif %}{% else %}STOPPED{% endif %}
-</form>
-</td></tr>
 <tr><td colspan=2>
 <form method="GET">
 filter filename: <input name="filter_path" value="{{filter_path}}" />
 <input type="submit" value="filter" />
 </form>
 </td></tr>
-<tr class="screen_half_titles"><th>current selection</th><th>playlist</th></tr>
 <tr>
 <td class="screen_half">
 {% if current_file %}
 <td class="screen_half">
 <form action="{{redir_target}}" method="POST">
 <table>
+<tr><th colspan=2 class="screen_half_titles"><form action="{{redir_target}}" method="POST">playlist <input type="submit" name="reload" value="reload"></form></th></tr>
 {% for idx, file in files_w_idx %}
 <tr>
 <td class="entry_buttons">
 
 _ColorStr = NewType('_ColorStr', str)
 _PageNames: TypeAlias = dict[str, Path]
 _ReqDict: TypeAlias = dict[str, list[str]]
+_PlayerState: TypeAlias = dict[str, bool | Path | str]
 _TemplateContext: TypeAlias = dict[
         str,
         None | bool
-        | _ColorStr | FilesWithIndex | _PageNames | FilterStr | Path
-        | PlayerUpdateId | QueryText | QuotaCost | UrlStr | 'VideoFile'
+        | _ColorStr | FilesWithIndex | _PlayerState | _PageNames | FilterStr
+        | Path | PlayerUpdateId | QueryText | QuotaCost | UrlStr | 'VideoFile'
         | YoutubeId | 'YoutubeVideo' | list[FlagName] | set['Tag']
         | list['VideoFile'] | list['YoutubeVideo'] | list['YoutubeQuery']
 ]
     'files': Path('files'),
     'last_update': Path('last_playlist_update.json'),
     'missing': Path('missing.json'),
+    'player': Path('player'),
     'playlist': Path('playlist'),
     'thumbnails': Path('thumbnails'),
     'yt_result': Path('yt_result'),
         page_name = Path(toks_url[1] if len(toks_url) > 1 else '')
         body_length = int(self.headers['content-length'])
         postvars = _ReqMap(self.rfile.read(body_length).decode())
-        # postvars = parse_qs(self.rfile.read(body_length).decode())
-        if PAGE_NAMES['playlist'] == page_name:
-            self._receive_player_command(postvars.single_key, url.query)
-        if PAGE_NAMES['files'] == page_name:
+        if PAGE_NAMES['player'] == page_name:
+            self._receive_player_command(postvars.as_dict)
+        elif PAGE_NAMES['playlist'] == page_name:
+            self._receive_playlist_command(postvars.single_key, url.query)
+        elif PAGE_NAMES['files'] == page_name:
             self._receive_files_command(postvars)
         elif PAGE_NAMES['file'] == page_name:
             self._receive_file_data(Hash.from_b64(toks_url[2]),
         elif PAGE_NAMES['yt_queries'] == page_name:
             self._receive_yt_query(QueryText(postvars.single_value('query')))
 
-    def _receive_player_command(self, command: str, params_str: str) -> None:
-        if 'pause' == command:
+    def _receive_player_command(self, postvars: _ReqDict) -> None:
+        if 'pause' in postvars.keys():
             self.server.player.toggle_pause()
-        elif 'prev' == command:
+        elif 'prev' in postvars.keys():
             self.server.player.prev()
-        elif 'next' == command:
+        elif 'next' in postvars.keys():
             self.server.player.next()
-        elif 'stop' == command:
+        elif 'stop' in postvars.keys():
             self.server.player.toggle_run()
-        elif 'reload' == command:
+        self._redirect(Path(postvars['redir_target'][0]))
+
+    def _receive_playlist_command(self, command: str, params_str: str) -> None:
+        if 'reload' == command:
             self.server.player.clear()
         elif command.startswith('jump_'):
             self.server.player.jump_to(int(command.split('_')[1]))
                                 tmpl_ctx: _TemplateContext
                                 ) -> None:
         tmpl = self.server.jinja.get_template(str(tmpl_name))
+        tmpl_ctx['redir_target'] = Path(self.path)
         tmpl_ctx['background_color'] = _ColorStr(
                 self.server.config.background_color)
         tmpl_ctx['page_names'] = PAGE_NAMES
+        tmpl_ctx['player_state'] = {
+                'running': self.server.player.is_running,
+                'paused': self.server.player.is_paused,
+                'title': (self.server.player.current_file_cached.rel_path
+                          if self.server.player.current_file_cached
+                          else 'none')}
         html = tmpl.render(**tmpl_ctx)
         self._send_http(bytes(html, 'utf8'))
 
         with DbConn() as conn:
             file = VideoFile.get_one(conn, digest)
             unused_tags = file.unused_tags(conn)
-        redir_target = Path('/').joinpath(PAGE_NAMES['file']).joinpath(
-                file.digest.b64)
-        self._send_rendered_template(_NAME_TEMPLATE_FILE_DATA,
-                                     {'file': file,
-                                      'flag_names': list(FILE_FLAGS),
-                                      'unused_tags': unused_tags,
-                                      'redir_target': redir_target})
+        self._send_rendered_template(
+                _NAME_TEMPLATE_FILE_DATA,
+                {'file': file,
+                 'flag_names': list(FILE_FLAGS),
+                 'unused_tags': unused_tags})
 
     def _send_files_index(self, params: _ReqMap) -> None:
         filter_path = FilterStr(params.single_value('filter_path'))
                 {'files': files,
                  'filter_path': filter_path,
                  'filter_tags': filter_tags,
-                 'show_absent': show_absent,
-                 'redir_target': Path(
-                     f'/{PAGE_NAMES["files"]}?{params.as_str}')})
+                 'show_absent': show_absent})
 
     def _send_missing_json(self) -> None:
         with DbConn() as conn:
             self.server.player.load_files_and_start(filter_path, filter_tags)
         current_file, unused_tags = None, set()
         with DbConn() as conn:
-            if self.server.player.current_file_digest:
+            if self.server.player.current_file_cached:
                 current_file = VideoFile.get_one(
-                        conn, self.server.player.current_file_digest)
+                        conn, self.server.player.current_file_cached.digest)
                 unused_tags = current_file.unused_tags(conn)
         self._send_rendered_template(
                 _NAME_TEMPLATE_PLAYLIST,
                  'current_file': current_file,
                  'filter_path': filter_path,
                  'filter_tags': filter_tags,
-                 'redir_target': Path(
-                     f'/{PAGE_NAMES["playlist"]}?{params.as_str}'),
                  'unused_tags': unused_tags,
                  'files_w_idx': list(enumerate(self.server.player.files))
                  })