diff --git a/MANIFEST.in b/MANIFEST.in
index 97464d1..ae4b02e 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,2 +1,3 @@
include README.md
-include beetsplug/webm3u/config_default.yaml
+include beetsplug/webm3u/templates/*.html
+include beetsplug/webm3u/static/**
diff --git a/beetsplug/webm3u/__init__.py b/beetsplug/webm3u/__init__.py
index 9789944..44b242a 100644
--- a/beetsplug/webm3u/__init__.py
+++ b/beetsplug/webm3u/__init__.py
@@ -1,4 +1,4 @@
-from flask import Flask
+from flask import Flask, render_template
from beets.plugins import BeetsPlugin
from beets.ui import Subcommand, decargs
from optparse import OptionParser
@@ -6,7 +6,7 @@
from beetsplug.webm3u.routes import bp
-class PlaylistServerPlugin(BeetsPlugin):
+class WebM3UPlugin(BeetsPlugin):
def __init__(self):
super().__init__()
self.config.add(
@@ -63,7 +63,7 @@ def create_app():
@app.route('/')
def home():
- return '
'
+ return render_template('index.html')
app.register_blueprint(bp)
diff --git a/beetsplug/webm3u/routes.py b/beetsplug/webm3u/routes.py
index cbc6340..7e1c58c 100644
--- a/beetsplug/webm3u/routes.py
+++ b/beetsplug/webm3u/routes.py
@@ -1,13 +1,16 @@
import os
-from flask import Flask, Blueprint, send_from_directory, send_file, abort
+from flask import Flask, Blueprint, send_from_directory, send_file, abort, render_template, request, jsonify
from beets import config
+from pathlib import Path
+MIMETYPE_HTML = 'text/html'
+MIMETYPE_JSON = 'application/json'
bp = Blueprint('webm3u_bp', __name__, template_folder='templates')
@bp.route('/playlists/', defaults={'path': ''})
@bp.route('/playlists/')
-def index_page(path):
+def playlists(path):
root_dir = config['webm3u']['playlist_dir'].get()
if not root_dir:
root_dir = config['smartplaylist']['playlist_dir'].get()
@@ -19,12 +22,64 @@ def index_page(path):
# TODO: transform item URIs within playlist
return send_file(abs_path)
else:
- # Generate html/json directory listing
- return 'playlist dir'
- #return send_from_directory(root_dir, path, as_attachment=True)
+ pl = _playlists(abs_path)
+ dirs = _directories(abs_path)
+ mimetypes = (MIMETYPE_JSON, MIMETYPE_HTML)
+ mimetype = request.accept_mimetypes.best_match(mimetypes, MIMETYPE_JSON)
+ if mimetype == MIMETYPE_HTML:
+ return render_template('playlists.html',
+ path=path,
+ playlists=pl,
+ directories=dirs,
+ humanize=_humanize_size,
+ )
+ else:
+ return jsonify({
+ 'directories': [{'name': d} for d in dirs],
+ 'playlists': pl,
+ })
+
+@bp.route('/music/', defaults={'path': ''})
+@bp.route('/music/')
+def music(path):
+ root_dir = config['directory'].get()
+ return send_from_directory(root_dir, path)
+
+def _playlists(dir):
+ l = [f for f in os.listdir(dir) if _is_playlist(dir, f)]
+ l.sort()
+ return [_playlist_dto(dir, f) for f in l]
+
+def _playlist_dto(dir, filename):
+ st = os.stat(os.path.join(dir, filename))
+ return {
+ 'name': Path(filename).stem,
+ 'path': filename,
+ 'size': st.st_size,
+ }
+
+def _is_playlist(dir, filename):
+ f = os.path.join(dir, filename)
+ return os.path.isfile(f) and (f.endswith('.m3u') or f.endswith('.m3u8'))
+
+def _directories(dir):
+ l = [d for d in os.listdir(dir) if os.path.isdir(_join(dir, d))]
+ l.sort()
+ return l
+
+def _join(dir, filename):
+ return os.path.join(dir, filename)
def _check_path(root_dir, path):
path = os.path.normpath(path)
root_dir = os.path.normpath(root_dir)
if path != root_dir and not path.startswith(root_dir+os.sep):
raise Exception('request path {} is outside the root directory {}'.format(path, root_dir))
+
+def _humanize_size(num):
+ suffix = 'B'
+ for unit in ("", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"):
+ if abs(num) < 1024.0:
+ return f"{num:3.1f}{unit}{suffix}"
+ num /= 1024.0
+ return f"{num:.1f}Yi{suffix}"
diff --git a/beetsplug/webm3u/static/style.css b/beetsplug/webm3u/static/style.css
new file mode 100644
index 0000000..aff351c
--- /dev/null
+++ b/beetsplug/webm3u/static/style.css
@@ -0,0 +1,23 @@
+body {
+ font-family: Verdana, sans-serif;
+ font-size: 1.2em;
+ line-height: 1.5em;
+}
+ul, li {
+ margin: 0;
+ padding: 0;
+ list-style-type: none;
+}
+li a {
+ display: block;
+ padding: 0.5em 1em;
+}
+li a span {
+ font-size: 0.7em
+}
+li:nth-child(odd) {
+ background-color: #fafafa;
+}
+li a:hover, li a:active {
+ background: #eeeeee;
+}
diff --git a/beetsplug/webm3u/templates/index.html b/beetsplug/webm3u/templates/index.html
new file mode 100644
index 0000000..446e0fd
--- /dev/null
+++ b/beetsplug/webm3u/templates/index.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+ Beets music library
+
+
+
+Beets music library
+
+
+ 🢘 back
+
+
+
+
+
diff --git a/beetsplug/webm3u/templates/playlists.html b/beetsplug/webm3u/templates/playlists.html
new file mode 100644
index 0000000..c2da6ac
--- /dev/null
+++ b/beetsplug/webm3u/templates/playlists.html
@@ -0,0 +1,34 @@
+
+
+
+
+
+ Playlists
+
+
+
+Playlists
+
+
+ 🢘 back
+
+
+
+
+
\ No newline at end of file
diff --git a/example_beets_config.yaml b/example_beets_config.yaml
index 68fb008..b59ac0d 100644
--- a/example_beets_config.yaml
+++ b/example_beets_config.yaml
@@ -24,6 +24,8 @@ smartplaylist:
playlists:
- name: all.m3u8
query: ''
+ - name: subdir/another.m3u8
+ query: ''
ytimport:
directory: /data/ytimport