From 3edfa67eef0fa003f9fa1687c12e008c0ee98781 Mon Sep 17 00:00:00 2001 From: Groovylein Date: Wed, 31 Jan 2024 17:22:54 +0100 Subject: [PATCH] display folder content in webapp --- .../components/player/backends/__init__.py | 9 ++- .../player/backends/mpd/interfacing_mpd.py | 57 ++++++++++++++++++- .../components/player/core/__init__.py | 4 +- src/jukebox/jukebox/playlistgenerator.py | 5 +- 4 files changed, 68 insertions(+), 7 deletions(-) diff --git a/src/jukebox/components/player/backends/__init__.py b/src/jukebox/components/player/backends/__init__.py index 14e0bd4c3..cf3169f14 100644 --- a/src/jukebox/components/player/backends/__init__.py +++ b/src/jukebox/components/player/backends/__init__.py @@ -74,5 +74,12 @@ def get_song_by_url(self, song_url): pass @abstractmethod - def get_folder_content(self): + def get_folder_content(self, folder): + """ + Get the folder content as content list with meta-information. Depth is always 1. + + Call repeatedly to descend in hierarchy + + :param folder: Folder path relative to music library path + """ pass diff --git a/src/jukebox/components/player/backends/mpd/interfacing_mpd.py b/src/jukebox/components/player/backends/mpd/interfacing_mpd.py index 22eeb7c30..fa2e816fc 100644 --- a/src/jukebox/components/player/backends/mpd/interfacing_mpd.py +++ b/src/jukebox/components/player/backends/mpd/interfacing_mpd.py @@ -5,13 +5,16 @@ import logging import os.path import re +from typing import Optional import jukebox.plugs as plugin import jukebox.cfghandler +import jukebox.playlistgenerator as playlistgenerator from mpd.asyncio import MPDClient from components.player.backends import BackendPlayer + logger = logging.getLogger('jb.mpd') cfg = jukebox.cfghandler.get_handler('player') @@ -294,8 +297,11 @@ def list_dirs(self): def get_song_by_url(self, song_url): pass - def get_folder_content(self): - pass + def get_folder_content(self, folder): + logger.debug(f"get_folder_content param: {folder}") + plc = playlistgenerator.PlaylistCollector(get_music_library_path()) + plc.get_directory_content(folder) + return plc.playlist # ---------------------------------- # Get podcasts / livestreams @@ -344,3 +350,50 @@ def _restore_state(self): Restore the configuration state and last played status for current active URI """ pass + + +#ToDo: refactor code +def _get_music_library_path(conf_file): + """Parse the music directory from the mpd.conf file""" + pattern = re.compile(r'^\s*music_directory\s*"(.*)"', re.I) + directory = None + with open(conf_file, 'r') as f: + for line in f: + res = pattern.match(line) + if res: + directory = res.group(1) + break + else: + logger.error(f"Could not find music library path in {conf_file}") + logger.debug(f"MPD music lib path = {directory}; from {conf_file}") + return directory + + +class MusicLibPath: + """Extract the music directory from the mpd.conf file""" + def __init__(self): + self._music_library_path = None + mpd_conf_file = cfg.setndefault('playermpd', 'mpd_conf', value='~/.config/mpd/mpd.conf') + try: + self._music_library_path = _get_music_library_path(os.path.expanduser(mpd_conf_file)) + except Exception as e: + logger.error(f"Could not determine music library directory from '{mpd_conf_file}'") + logger.error(f"Reason: {e.__class__.__name__}: {e}") + + @property + def music_library_path(self): + return self._music_library_path + + +# --------------------------------------------------------------------------- + + +_MUSIC_LIBRARY_PATH: Optional[MusicLibPath] = None + + +def get_music_library_path(): + """Get the music library path""" + global _MUSIC_LIBRARY_PATH + if _MUSIC_LIBRARY_PATH is None: + _MUSIC_LIBRARY_PATH = MusicLibPath() + return _MUSIC_LIBRARY_PATH.music_library_path diff --git a/src/jukebox/components/player/core/__init__.py b/src/jukebox/components/player/core/__init__.py index 0a607ce04..c314eeec2 100644 --- a/src/jukebox/components/player/core/__init__.py +++ b/src/jukebox/components/player/core/__init__.py @@ -188,8 +188,8 @@ def get_song_by_url(self, song_url): return self._active.get_song_by_url(song_url) @plugin.tag - def get_folder_content(self): - return self._active.get_folder_content() + def get_folder_content(self, folder): + return self._active.get_folder_content(folder) def _save_state(self): diff --git a/src/jukebox/jukebox/playlistgenerator.py b/src/jukebox/jukebox/playlistgenerator.py index c304a76ae..e61fd5e9f 100755 --- a/src/jukebox/jukebox/playlistgenerator.py +++ b/src/jukebox/jukebox/playlistgenerator.py @@ -269,6 +269,7 @@ def get_directory_content(self, path='.'): """ self.playlist = [] self._folder = os.path.abspath(os.path.join(self._music_library_base_path, path)) + logger.debug(self._folder) try: content = self._get_directory_content(self._folder) except NotADirectoryError as e: @@ -278,10 +279,10 @@ def get_directory_content(self, path='.'): else: logger.debug(f"Playlist Content: {content}") for m in content: - self.playlist.append({'type': TYPE_DECODE[m.filetype], 'name': m.name, 'path': m.path, 'uri': m.uri}) + self.playlist.append({'type': TYPE_DECODE[m.filetype], 'name': m.name, 'path': m.uri}) def _parse_nonrecusive(self, path='.'): - return [x.path for x in self._get_directory_content(path) if x.filetype != TYPE_DIR] + return [x.uri for x in self._get_directory_content(path) if x.filetype != TYPE_DIR] def _parse_recursive(self, path='.'): # This can certainly be optimized, as os.walk is called on all