2018-09-12 13:04:00 -04:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
"""
|
|
|
|
Music streaming.
|
|
|
|
"""
|
2018-09-13 14:22:27 -04:00
|
|
|
import os
|
|
|
|
import json
|
2018-09-14 08:02:24 -04:00
|
|
|
import random
|
2018-09-12 13:04:00 -04:00
|
|
|
import subprocess
|
2018-09-13 14:22:27 -04:00
|
|
|
from urllib import parse
|
2018-09-12 13:04:00 -04:00
|
|
|
|
2019-05-31 10:28:21 -04:00
|
|
|
from flask import Flask, Response, render_template, send_file, url_for, request, abort
|
|
|
|
|
|
|
|
import database
|
2019-09-25 19:48:19 -04:00
|
|
|
import buckler_flask
|
2018-09-12 13:04:00 -04:00
|
|
|
|
|
|
|
FFMPEG_CMD = [
|
|
|
|
'ffmpeg', '-y',
|
|
|
|
'-loglevel', 'panic',
|
|
|
|
'-i', '',
|
|
|
|
'-b:a', '64k',
|
|
|
|
'-f', 'opus',
|
|
|
|
'-'
|
|
|
|
]
|
|
|
|
|
2019-02-25 13:40:36 -05:00
|
|
|
|
2018-09-12 13:04:00 -04:00
|
|
|
app = Flask(__name__)
|
2019-09-25 19:48:19 -04:00
|
|
|
app.session_interface = buckler_flask.BucklerSessionInterface()
|
|
|
|
app.before_request(buckler_flask.require_auth)
|
2019-05-31 10:28:21 -04:00
|
|
|
database.init_database()
|
2018-09-12 13:04:00 -04:00
|
|
|
|
|
|
|
@app.route('/')
|
|
|
|
def index():
|
|
|
|
"""Main index page."""
|
2019-05-31 10:28:21 -04:00
|
|
|
artists = database.get_all_artists()
|
2018-09-13 14:22:27 -04:00
|
|
|
return render_template('index.html', **locals())
|
2018-09-12 13:04:00 -04:00
|
|
|
|
|
|
|
|
2019-05-31 10:28:21 -04:00
|
|
|
@app.route('/select')
|
|
|
|
def select():
|
|
|
|
"""Retrieve information about an artist, album or track."""
|
|
|
|
artist = request.args.get('artist')
|
|
|
|
album = request.args.get('album')
|
|
|
|
discnumber = request.args.get('discnumber')
|
|
|
|
tracknumber = request.args.get('tracknumber')
|
2019-02-04 10:06:58 -05:00
|
|
|
|
2019-05-31 10:28:21 -04:00
|
|
|
if tracknumber:
|
|
|
|
result = database.get_track(artist, album, discnumber, tracknumber)
|
|
|
|
if not result:
|
|
|
|
return ("Valid artist, album, discnumber and tracknumber "
|
|
|
|
"parameters must be supplied.")
|
|
|
|
else:
|
|
|
|
result.pop('filepath')
|
|
|
|
elif album:
|
|
|
|
result = database.get_album_tracks(artist, album)
|
|
|
|
if not result:
|
|
|
|
return "Valid artist and album parameters must be supplied."
|
|
|
|
elif artist:
|
|
|
|
result = database.get_artist_albums(artist)
|
|
|
|
if not result:
|
|
|
|
return "Valid artist parameter must be supplied."
|
|
|
|
else:
|
|
|
|
return "Invalid query."
|
|
|
|
return json.dumps(result)
|
2019-02-05 12:44:31 -05:00
|
|
|
|
|
|
|
|
2019-05-31 10:28:21 -04:00
|
|
|
@app.route('/select/random')
|
|
|
|
def select_random():
|
|
|
|
"""
|
|
|
|
Selects a random track.
|
|
|
|
"""
|
|
|
|
track = database.get_random_track()
|
|
|
|
track.pop('filepath')
|
|
|
|
return json.dumps(track)
|
2019-02-04 10:06:58 -05:00
|
|
|
|
|
|
|
|
2019-05-31 10:28:21 -04:00
|
|
|
@app.route('/stream')
|
|
|
|
def stream():
|
2018-09-12 13:04:00 -04:00
|
|
|
"""View for the raw audio file."""
|
2019-05-31 10:28:21 -04:00
|
|
|
artist = parse.unquote(request.args.get('artist'))
|
|
|
|
album = parse.unquote(request.args.get('album'))
|
|
|
|
discnumber = parse.unquote(request.args.get('discnumber'))
|
|
|
|
tracknumber = parse.unquote(request.args.get('tracknumber'))
|
|
|
|
|
|
|
|
track = database.get_track(artist, album, discnumber, tracknumber)
|
|
|
|
if not track:
|
|
|
|
return "Track does not exist."
|
2019-02-05 11:23:41 -05:00
|
|
|
|
2019-05-31 10:28:21 -04:00
|
|
|
FFMPEG_CMD[5] = track['filepath']
|
2018-09-12 13:04:00 -04:00
|
|
|
|
|
|
|
def generate():
|
|
|
|
with subprocess.Popen(FFMPEG_CMD, stdout=subprocess.PIPE) as proc:
|
|
|
|
data = proc.stdout.read(1024)
|
|
|
|
while data:
|
|
|
|
yield data
|
|
|
|
data = proc.stdout.read(1024)
|
|
|
|
return Response(generate(), mimetype="audio/ogg")
|
|
|
|
|
|
|
|
|
2019-05-31 10:28:21 -04:00
|
|
|
@app.route('/coverart')
|
|
|
|
def coverart():
|
2018-09-20 10:00:07 -04:00
|
|
|
"""View for the raw audio file."""
|
2019-05-31 10:28:21 -04:00
|
|
|
artist = parse.unquote(request.args.get('artist'))
|
|
|
|
album = parse.unquote(request.args.get('album'))
|
|
|
|
discnumber = parse.unquote(request.args.get('discnumber'))
|
|
|
|
tracknumber = parse.unquote(request.args.get('tracknumber'))
|
|
|
|
|
|
|
|
track = database.get_track(artist, album, discnumber, tracknumber)
|
|
|
|
if not track:
|
|
|
|
return "Track does not exist."
|
|
|
|
|
|
|
|
cover_path = os.path.join(os.path.dirname(track['filepath']), 'folder.jpg')
|
|
|
|
if os.path.isfile(cover_path):
|
|
|
|
return send_file(cover_path)
|
2019-02-05 13:04:10 -05:00
|
|
|
else:
|
2019-03-13 12:49:38 -04:00
|
|
|
return "No cover art for this track found."
|
2018-09-20 10:00:07 -04:00
|
|
|
|
|
|
|
|
2018-09-12 13:04:00 -04:00
|
|
|
if __name__ == "__main__":
|
|
|
|
app.run(host='0.0.0.0', port=5150)
|