refactor, fix uri encoding
This commit is contained in:
parent
0ec22ee2a2
commit
3382579b47
|
@ -4,7 +4,7 @@ Stream some music.
|
||||||
## Requirements
|
## Requirements
|
||||||
Python 3.6+
|
Python 3.6+
|
||||||
FFmpeg compiled with `--enable-libopus`
|
FFmpeg compiled with `--enable-libopus`
|
||||||
Python packages: `flask gunicorn`
|
Python packages: `flask gunicorn mutagen`
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
1. Get on the floor
|
1. Get on the floor
|
||||||
|
|
23
musik.py
23
musik.py
|
@ -3,10 +3,12 @@
|
||||||
Music streaming.
|
Music streaming.
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import json
|
import json
|
||||||
import random
|
import random
|
||||||
import subprocess
|
import subprocess
|
||||||
from urllib import parse
|
from urllib import parse
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
from flask import Flask, Response, render_template, send_file
|
from flask import Flask, Response, render_template, send_file
|
||||||
from werkzeug.utils import secure_filename
|
from werkzeug.utils import secure_filename
|
||||||
|
@ -23,6 +25,23 @@ FFMPEG_CMD = [
|
||||||
'-'
|
'-'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def build_tree(root_dir):
|
||||||
|
"""Walks the music directory and builds a tree."""
|
||||||
|
print("Building tree.")
|
||||||
|
tree = defaultdict(dict)
|
||||||
|
for dirName, subDirs, files in os.walk(root_dir):
|
||||||
|
if dirName == root_dir:
|
||||||
|
continue
|
||||||
|
reg = re.search(".*/(.+?) - (.+) \(\d{4}\)", dirName)
|
||||||
|
if not reg:
|
||||||
|
print(dirName)
|
||||||
|
continue
|
||||||
|
artist, album = reg.groups()
|
||||||
|
tracks = [f for f in files if f.rpartition('.')[2] in MUSIC_EXT]
|
||||||
|
tree[artist][album] = tracks
|
||||||
|
return tree
|
||||||
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
|
@ -40,6 +59,7 @@ def index():
|
||||||
@app.route('/stream/<path:track>')
|
@app.route('/stream/<path:track>')
|
||||||
def stream(track):
|
def stream(track):
|
||||||
"""View for the raw audio file."""
|
"""View for the raw audio file."""
|
||||||
|
track = parse.unquote(track)
|
||||||
path = os.path.join(MUSIC_DIR, track)
|
path = os.path.join(MUSIC_DIR, track)
|
||||||
path = os.path.abspath(path)
|
path = os.path.abspath(path)
|
||||||
if not path.startswith(MUSIC_DIR):
|
if not path.startswith(MUSIC_DIR):
|
||||||
|
@ -58,7 +78,8 @@ def stream(track):
|
||||||
|
|
||||||
|
|
||||||
@app.route('/get_dir/<path:directory>/')
|
@app.route('/get_dir/<path:directory>/')
|
||||||
def get_dir(directory):
|
@app.route('/get_dir/')
|
||||||
|
def get_dir(directory=""):
|
||||||
"""Returns the contents of the requested directory."""
|
"""Returns the contents of the requested directory."""
|
||||||
directory = directory.replace("DOTDOT", "..")
|
directory = directory.replace("DOTDOT", "..")
|
||||||
directory = os.path.join(MUSIC_DIR, directory)
|
directory = os.path.join(MUSIC_DIR, directory)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
font-family: Helvetica, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
|
@ -33,6 +34,7 @@ img {
|
||||||
}
|
}
|
||||||
|
|
||||||
#playerContainer {
|
#playerContainer {
|
||||||
|
height: 30vh;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
@ -42,6 +44,8 @@ img {
|
||||||
#albumCover {
|
#albumCover {
|
||||||
padding-right: 1em;
|
padding-right: 1em;
|
||||||
padding-left: 1em;
|
padding-left: 1em;
|
||||||
|
padding-bottom: 3px;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
#playerControls {
|
#playerControls {
|
||||||
|
|
|
@ -1,23 +1,26 @@
|
||||||
var httpRequest
|
|
||||||
|
|
||||||
function load() {
|
function load() {
|
||||||
// track has ended
|
// track has ended
|
||||||
document.getElementById('player').addEventListener('ended', function() {
|
document.getElementById('player').addEventListener('ended', function() {
|
||||||
// shuffle
|
// shuffle
|
||||||
if (document.getElementById('shuffle').checked) {
|
if (document.getElementById('shuffle').checked) {
|
||||||
httpRequest = new XMLHttpRequest();
|
ajax('/musik/get_shuffle', function() {
|
||||||
httpRequest.onreadystatechange = function() {
|
|
||||||
if (httpRequest.readyState !== XMLHttpRequest.DONE) { return; }
|
if (httpRequest.readyState !== XMLHttpRequest.DONE) { return; }
|
||||||
if (httpRequest.status !== 200) { return; }
|
if (httpRequest.status !== 200) { return; }
|
||||||
let track = httpRequest.responseText;
|
let track = httpRequest.responseText;
|
||||||
change_track(track);
|
change_track(track);
|
||||||
}
|
});
|
||||||
httpRequest.open('GET', '/musik/get_shuffle', true);
|
|
||||||
httpRequest.send();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var httpRequest;
|
||||||
|
function ajax(url, func) {
|
||||||
|
httpRequest = new XMLHttpRequest();
|
||||||
|
httpRequest.onreadystatechange = func;
|
||||||
|
httpRequest.open('GET', url, true);
|
||||||
|
httpRequest.send();
|
||||||
|
}
|
||||||
|
|
||||||
function navigate(item) {
|
function navigate(item) {
|
||||||
if (/\..{3,5}$/.test(item)) {
|
if (/\..{3,5}$/.test(item)) {
|
||||||
select_track(item);
|
select_track(item);
|
||||||
|
@ -35,7 +38,7 @@ function select_track(item) {
|
||||||
|
|
||||||
function change_track(track) {
|
function change_track(track) {
|
||||||
let source = document.getElementById('stream');
|
let source = document.getElementById('stream');
|
||||||
source.src = '/musik/stream' + track;
|
source.src = '/musik/stream' + encodeURIComponent(track);
|
||||||
let player = document.getElementById('player');
|
let player = document.getElementById('player');
|
||||||
player.load();
|
player.load();
|
||||||
player.play();
|
player.play();
|
||||||
|
@ -48,12 +51,18 @@ function change_track(track) {
|
||||||
|
|
||||||
function get_dir(item) {
|
function get_dir(item) {
|
||||||
let cd = document.getElementById('currentDirectory').innerText;
|
let cd = document.getElementById('currentDirectory').innerText;
|
||||||
item = cd + item;
|
if (item === "../") {
|
||||||
item = item.replace(/\.\./g, 'DOTDOT');
|
if (cd !== "/") {
|
||||||
httpRequest = new XMLHttpRequest();
|
item = cd.slice(0, cd.slice(0, -1).lastIndexOf("/")+1);
|
||||||
httpRequest.onreadystatechange = update_nav_items;
|
}
|
||||||
httpRequest.open('GET', '/musik/get_dir' + item, true);
|
else {
|
||||||
httpRequest.send();
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
item = cd + item;
|
||||||
|
}
|
||||||
|
ajax('/musik/get_dir/' + item, update_nav_items);
|
||||||
}
|
}
|
||||||
|
|
||||||
function update_nav_items() {
|
function update_nav_items() {
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="playerContainer">
|
<div id="playerContainer">
|
||||||
<div id="albumCover"><img src="/musik/album_cover{{ initial_cover }}"/></div>
|
<span id="albumCover"><img src="/musik/album_cover{{ initial_cover }}"/></span>
|
||||||
<div id="playerControls">
|
<span id="playerControls">
|
||||||
<h3 id="nowPlaying">{{ initial_track }}</h3>
|
<h3 id="nowPlaying">{{ initial_track }}</h3>
|
||||||
<audio id="player" controls>
|
<audio id="player" controls>
|
||||||
<source id="stream" src="{{ url_for('stream', track=initial_track) }}" type="audio/ogg">
|
<source id="stream" src="{{ url_for('stream', track=initial_track) }}" type="audio/ogg">
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
<input type="checkbox" name="shuffle" id="shuffle" checked="true">
|
<input type="checkbox" name="shuffle" id="shuffle" checked="true">
|
||||||
<label for="shuffle">Shuffle</label>
|
<label for="shuffle">Shuffle</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user