From 5dfff5000585cb987817c8b11c9ae2d48492fd06 Mon Sep 17 00:00:00 2001 From: J0J0 T Date: Wed, 13 Jul 2022 08:49:53 +0200 Subject: [PATCH] convert: playlist: Refactor m3u writing to class and also implement a currently untested load() method. --- beets/util/__init__.py | 50 ++++++++++++++++++++++++++++++++++++++++++ beetsplug/convert.py | 7 +++--- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/beets/util/__init__.py b/beets/util/__init__.py index 2319890a3..3d27edd5e 100644 --- a/beets/util/__init__.py +++ b/beets/util/__init__.py @@ -135,6 +135,56 @@ class MoveOperation(Enum): REFLINK_AUTO = 5 +class M3UFile(): + def __init__(self, path): + """Reads and writes m3u or m3u8 playlist files. + + ``path`` is the full path to the playlist file. + + The playlist file type, m3u or m3u8 is determined by 1) the ending + being m3u8 and 2) the file paths contained in the list being utf-8 + encoded. Since the list is passed from the outside, this is currently + out of control of this class. + """ + self.path = path + self.extm3u = False + self.media_list = [] + + def load(self): + """Reads the m3u file from disk and sets the object's attributes. + """ + with open(self.name, "r") as playlist_file: + raw_contents = playlist_file.readlines() + self.extm3u = True if raw_contents[0] == "#EXTM3U" else False + for line in raw_contents[1:]: + if line.startswith("#"): + # Some EXTM3U comment, do something. FIXME + continue + self.media_list.append(line) + + def set_contents(self, media_files, extm3u=True): + """Sets self.media_files to a list of media file paths, + + and sets additional flags, changing the final m3u-file's format. + + ``media_files`` is a list of paths to media files that should be added + to the playlist (relative or absolute paths, that's the responsibility + of the caller). By default the ``extm3u`` flag is set, to ensure a + save-operation writes an m3u-extended playlist (comment "#EXTM3U" at + the top of the file). + """ + self.media_files = media_files + self.extm3u = extm3u + + def write(self): + """Writes the m3u file to disk.""" + header = ["#EXTM3U"] if self.extm3u else [] + contents = header + self.media_files + with open(self.path, "w") as playlist_file: + playlist_file.writelines('\n'.join(contents)) + playlist_file.write('\n') # Final linefeed to prevent noeol file. + + def normpath(path): """Provide the canonical form of the path suitable for storing in the database. diff --git a/beetsplug/convert.py b/beetsplug/convert.py index ebac336d5..2856363ab 100644 --- a/beetsplug/convert.py +++ b/beetsplug/convert.py @@ -31,6 +31,7 @@ from beets import art from beets.util.artresizer import ArtResizer from beets.library import parse_query_string from beets.library import Item +from beets.util import M3UFile _fs_lock = threading.Lock() _temp_files = [] # Keep track of temporary transcoded files for deletion. @@ -485,10 +486,10 @@ class ConvertPlugin(BeetsPlugin): basedir=dest, path_formats=path_formats, fragment=True ) for item in items ] - items_paths = ["#EXTM3U"] + items_paths if not pretend: - with open(playlist, "w") as playlist_file: - playlist_file.writelines('\n'.join(items_paths)) + m3ufile = M3UFile(playlist) + m3ufile.set_contents(items_paths) + m3ufile.write() self._parallel_convert(dest, opts.keep_new, path_formats, fmt, pretend, link, hardlink, threads, items)