From 5dfdc275b279117c9a7bd7d842bc2d9c8de3e598 Mon Sep 17 00:00:00 2001 From: Max Goltzsche Date: Thu, 14 Dec 2023 23:59:21 +0100 Subject: [PATCH] smartplaylist: add --uri-template option Beets web API already allows remote players to access audio files but it doesn't provide a way to expose the playlists defined using the smartplaylist plugin. Now the smartplaylist plugin provides an option to generate ID-based item URIs/URLs instead of paths. Once playlists are generated this way, they can be served using a regular HTTP server such as nginx. To support integrations with more APIs than just the beets web API (e.g. AURA API), the new option has been defined as a template with an `$id` placeholder (assuming each integration requires a different path schema but they all rely on using the beets item `id` as identifier/path segment). Usage example: `beet splupdate --uri-template 'http://beets:8337/item/$id/file'` (While it was already possible to generate playlists with URLs previously using the `prefix` option, it did not allow to generate ID-based URLs pointing to the beets web API but required to expose the audio files using a web server directly and refer to them using their file system path.) Relates to #5037 --- beetsplug/smartplaylist.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/beetsplug/smartplaylist.py b/beetsplug/smartplaylist.py index c892a6040d..30ce5d575c 100644 --- a/beetsplug/smartplaylist.py +++ b/beetsplug/smartplaylist.py @@ -45,6 +45,7 @@ def __init__(self): "playlist_dir": ".", "auto": True, "playlists": [], + "uri_template": None, "forward_slash": False, "prefix": "", "urlencode": False, @@ -72,6 +73,13 @@ def commands(self): action="store_true", help="display query results but don't write playlist files.", ) + spl_update.parser.add_option( + "--uri-template", + dest="uri_template", + metavar="TPL", + type="string", + help="playlist item URI template, e.g. http://beets/item/$id/file.", + ) spl_update.parser.add_option( "--extm3u", action="store_true", @@ -208,6 +216,7 @@ def update_playlists(self, lib, extm3u=None, pretend=False): "Updating {0} smart playlists...", len(self._matched_playlists) ) + tpl = self.config["uri_template"].get() playlist_dir = self.config["playlist_dir"].as_filename() playlist_dir = bytestring_path(playlist_dir) relative_to = self.config["relative_to"].get() @@ -239,8 +248,13 @@ def update_playlists(self, lib, extm3u=None, pretend=False): if m3u_name not in m3us: m3us[m3u_name] = [] item_path = item.path - if relative_to: - item_path = os.path.relpath(item.path, relative_to) + if tpl: + item_path = tpl.replace("$id", str(item.id)).encode("utf-8") + else: + if relative_to: + item_path = os.path.relpath(item.path, relative_to) + item_path = prefix + item_path + if item_path not in m3us[m3u_name]: m3us[m3u_name].append({"item": item, "path": item_path}) if pretend and self.config["pretend_paths"]: @@ -272,7 +286,7 @@ def update_playlists(self, lib, extm3u=None, pretend=False): comment = "#EXTINF:{},{} - {}\n".format( int(item.length), item.artist, item.title ) - f.write(comment.encode("utf-8") + prefix + path + b"\n") + f.write(comment.encode("utf-8") + path + b"\n") # Send an event when playlists were updated. send_event("smartplaylist_update")