added rest api

This commit is contained in:
iou1name 2019-02-04 10:06:58 -05:00
parent 1d9037310e
commit a4af2a1fd5
4 changed files with 106 additions and 15 deletions

View File

@ -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 mutagen` Python packages: `flask gunicorn mutagen Flask-RESTful`
## Install ## Install
1. Get on the floor 1. Get on the floor

View File

@ -9,6 +9,7 @@ import subprocess
from urllib import parse from urllib import parse
from flask import Flask, Response, render_template, send_file from flask import Flask, Response, render_template, send_file
from flask_restful import reqparse, abort, Api, Resource
import mutagen import mutagen
MUSIC_DIR = "/mnt/music/Music" MUSIC_DIR = "/mnt/music/Music"
@ -71,18 +72,73 @@ def init_library():
app = Flask(__name__) app = Flask(__name__)
api = Api(app)
tracks = init_library() tracks = init_library()
@app.route('/') @app.route('/')
def index(): def index():
"""Main index page.""" """Main index page."""
nav_items = list(set(t.artist for t in tracks)) artist = list(set(t.artist for t in tracks))
nav_items.sort() artist.sort()
nav_items = [item + '/' for item in nav_items]
cd = "/"
return render_template('index.html', **locals()) return render_template('index.html', **locals())
parser = reqparse.RequestParser()
parser.add_argument('artist')
parser.add_argument('album')
parser.add_argument('track')
def validate_select_args(args):
"""
If a track is specified, both artist and album must also be specified.
If an album is specified, the artist must also be specified.
"""
if args.get('track'):
if not args.get('artist') or not args.get('album'):
abort(400, message="Artist and album must also be specified.")
elif args.get('album'):
if not args.get('artist'):
abort(400, message="Artist must also be specified.")
elif not args.get('artist'):
abort(400, message="You must specify at least an artist.")
class Selection(Resource):
def get(self):
global tracks
args = parser.parse_args()
print(args)
validate_select_args(args)
if args.get('track'):
track = [t for t in tracks
if (t.title == args.get('track') and
t.album == args.get('album') and
t.artist == args.get('artist'))]
if not track:
abort(404, message="Track does not exist.")
else:
return vars(track[0])
elif args.get('album'):
tracks = [t for t in tracks
if (t.album == args.get('album') and
t.artist == args.get('artist'))]
if not tracks:
abort(404, message="Album does not exist.")
else:
return [t.title for t in tracks]
elif args.get('artist'):
albums = list(set(t.album for t in tracks
if t.artist == args.get('artist')))
if not albums:
abort(404, message="Artist does not exist.")
else:
return sorted(albums)
api.add_resource(Selection, '/select')
@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."""

View File

@ -21,16 +21,41 @@ img {
#navigationContainer { #navigationContainer {
flex: auto; flex: auto;
overflow: auto; overflow: auto;
display: flex;
flex-direction: row;
height: 100%;
border-top: 2px solid #ccc; border-top: 2px solid #ccc;
border-bottom: 2px solid #ccc; border-bottom: 2px solid #ccc;
} }
#currentDirectory { #selectArtistContainer {
padding-left: 0.5em; height: 100%;
width: 100%;
} }
#navItems { #selectArtist {
list-style-type: none; height: 100%;
width: 100%;
}
#selectAlbumContainer {
height: 100%;
width: 100%;
}
#selectAlbum {
height: 100%;
width: 100%;
}
#selectTrackContainer {
height: 100%;
width: 100%;
}
#selectTrack {
height: 100%;
width: 100%;
} }
#playerContainer { #playerContainer {

View File

@ -10,12 +10,22 @@
<div id="globalContainer"> <div id="globalContainer">
<div id="titleContainer"><h1>Musik</h1></div> <div id="titleContainer"><h1>Musik</h1></div>
<div id="navigationContainer"> <div id="navigationContainer">
<div id="currentDirectory">{{ cd }}</div> <div id="selectArtistContainer">
<ul id="navItems"> <select id="selectArtist" size="2">
{% for item in nav_items %} {% for artist in artists %}
<li><a href="javascript:void(0);" onclick="navigate('{{ item }}')">{{ item }}</a></li> <!--<li><a href="javascript:void(0);" onclick="navigate('{{ item }}')">{{ item }}</a></li>-->
<option>{{ artist }}</option>
{% endfor %} {% endfor %}
</ul> </select>
</div>
<div id="selectAlbumContainer">
<select id="selectAlbum" size="2">
</select>
</div>
<div id="selectTrackContainer">
<select id="selectTrack" size="2">
</select>
</div>
</div> </div>
<div id="playerContainer"> <div id="playerContainer">
<span id="albumCover"><img src=""/></span> <span id="albumCover"><img src=""/></span>