#!/usr/bin/python3
from functools import wraps
-from flask import Flask, render_template, request, redirect, send_file, Response
+from flask import Flask, render_template, request, redirect, send_file, Response, jsonify
import variables as var
import util
from datetime import datetime
return decorated
-@web.route("/", methods=['GET', 'POST'])
+@web.route("/", methods=['GET'])
@requires_auth
def index():
folder_path = var.music_folder
for file in files:
music_library.add_file(file)
+
+ return render_template('index.html',
+ all_files=files,
+ music_library=music_library,
+ os=os,
+ playlist=var.playlist,
+ user=var.user
+ )
+
+@web.route("/playlist", methods=['GET'])
+@requires_auth
+def playlist():
+ if var.playlist.length() == 0:
+ return jsonify([render_template('playlist.html',
+ m=False,
+ index=-1
+ )]
+ )
+
+ data = []
+
+ for index, item in enumerate(var.playlist.playlist):
+ data.append(render_template('playlist.html',
+ index=index,
+ m=item,
+ playlist=var.playlist
+ )
+ )
+
+ return jsonify(data)
+
+@web.route("/post", methods=['POST'])
+@requires_auth
+def post():
if request.method == 'POST':
logging.debug("Post request: "+ str(request.form))
if 'add_file_bottom' in request.form and ".." not in request.form['add_file_bottom']:
elif 'add_url' in request.form:
var.playlist.append({'type':'url',
- 'url': request.form['add_url'],
- 'user': 'Web',
- 'ready': 'validation'})
+ 'url': request.form['add_url'],
+ 'user': 'Web',
+ 'ready': 'validation'})
logging.info("web: add to playlist: " + request.form['add_url'])
media.url.get_url_info()
var.playlist.playlist[-1]['ready'] = "no"
elif 'add_radio' in request.form:
var.playlist.append({'type': 'radio',
- 'path': request.form['add_radio'],
- 'user': "Web"})
+ 'path': request.form['add_radio'],
+ 'user': "Web"})
logging.info("web: add to playlist: " + request.form['add_radio'])
elif 'delete_music' in request.form:
elif 'action' in request.form:
action = request.form['action']
if action == "randomize":
- random.shuffle(var.playlist.playlist)
+ var.playlist.randomize()
elif action == "stop":
var.botamusique.pause()
elif action == "clear":
var.botamusique.volume = 0
logging.info("web: volume down to %d" % (var.botamusique.volume * 100))
- return render_template('index.html',
- all_files=files,
- music_library=music_library,
- os=os,
- playlist=var.playlist,
- user=var.user
- )
-
+ return jsonify({'ver': var.playlist.version})
@web.route('/upload', methods=["POST"])
def upload():
return redirect("./", code=406)
logging.info('Uploading file:')
- logging.info(' - filename:', filename)
- logging.info(' - targetdir:', targetdir)
- logging.info(' - mimetype:', file.mimetype)
+ logging.info(' - filename: ' + filename)
+ logging.info(' - targetdir: ' + targetdir)
+ logging.info(' - mimetype: ' + file.mimetype)
if "audio" in file.mimetype:
storagepath = os.path.abspath(os.path.join(var.music_folder, targetdir))
return redirect("./", code=500)
filepath = os.path.join(storagepath, filename)
- logging.info(' - filepath: ', filepath)
+ logging.info(' - filepath: ' + filepath)
if os.path.exists(filepath):
return redirect("./", code=406)
<li class="directory list-group-item list-group-item-primary">
<div class="btn-group" role="group">
<div class="btn-group" role="group">
- <form method="post" class="directory">
- <input type="text" value="{{ subdirpath }}" name="add_folder" hidden>
- <button type="button" class="btn btn-success btn-sm btn-submit"><i class="fa fa-plus" aria-hidden="true"></i></button>
- </form>
+ <button type="button" class="btn btn-success btn-sm"
+ onclick="request('/post', {add_folder : '{{ subdirpath }}'})">
+ <i class="fa fa-plus" aria-hidden="true"></i>
+ </button>
<div class="btn-group" role="group">
<button id="btnGroupDrop2" type="button" class="btn btn-success btn-sm dropdown-toggle btn-space" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button>
<div class="dropdown-menu" aria-labelledby="btnGroupDrop2" style="">
- <form method="post" class="directory">
- <input type="text" value="{{ subdirpath }}" name="add_folder" hidden>
- <a href="#" class="dropdown-item a-submit"><i class="fa fa-folder" aria-hidden="true"></i> Entire folder</a>
- </form>
- <form method="post" class="directory">
- <input type="text" value="{{ subdirpath }}" name="add_folder_recursively" hidden>
- <a href="#" class="dropdown-item a-submit"><i class="fa fa-folder" aria-hidden="true"></i> Entire folder and sub-folders</a>
- </form>
+ <a class="dropdown-item"
+ onclick="request('/post', {add_folder : '{{ subdirpath }}'})">
+ <i class="fa fa-folder" aria-hidden="true"></i> Entire folder
+ </a>
+ <a class="dropdown-item"
+ onclick="request('/post', {add_folder_recursively : '{{ subdirpath }}'})">
+ <i class="fa fa-folder" aria-hidden="true"></i> Entire folder and sub-folders
+ </a>
</div>
</div>
</div>
<li class="file list-group-item">
<div class="btn-group" role="group">
<div class="btn-group" role="group">
- <form method="post" class="file file_add">
- <input type="text" value="{{ filepath }}" name="add_file_bottom" hidden>
- <button type="button" class="btn btn-success btn-sm btn-submit"><i class="fa fa-plus" aria-hidden="true"></i></button>
- </form>
+ <button type="button" class="btn btn-success btn-sm"
+ onclick="request('/post', {add_file_bottom : '{{ filepath }}'})">
+ <i class="fa fa-plus" aria-hidden="true"></i>
+ </button>
<div class="btn-group" role="group">
<button id="btnGroupDrop2" type="button" class="btn btn-success btn-sm dropdown-toggle btn-space" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button>
<div class="dropdown-menu" aria-labelledby="btnGroupDrop2" style="">
- <form method="post" class="file file_add">
- <input type="text" value="{{ filepath }}" name="add_file_bottom" hidden>
- <a href="#" class="dropdown-item a-submit"><i class="fa fa-angle-down" aria-hidden="true"></i> To bottom of play list</a>
- </form>
- <form method="post" class="file file_add">
- <input type="text" value="{{ filepath }}" name="add_file_next" hidden>
- <a href="#" class="dropdown-item a-submit"><i class="fa fa-angle-right" aria-hidden="true"></i> After current song</a>
- </form>
+ <a class="dropdown-item"
+ onclick="request('/post', {add_file_bottom : '{{ filepath }}'})">
+ <i class="fa fa-angle-down" aria-hidden="true"></i> To bottom of play list
+ </a>
+ <a class="dropdown-item"
+ onclick="request('/post', {add_file_next : '{{ filepath }}'})">
+ <i class="fa fa-angle-right" aria-hidden="true"></i> After current song
+ </a>
</div>
</div>
</div>
<div class="card-body">
<div class="btn-group" style="margin-bottom: 5px;">
- <form method="post">
- <input type="text" value="randomize" name="action" hidden>
- <button type="submit" class="btn btn-primary btn-space"><i class="fas fa-random"></i></button>
- </form>
- <form method="post">
- <input type="text" value="stop" name="action" hidden>
- <button type="submit" class="btn btn-danger btn-space"><i class="fas fa-stop"></i></button>
- </form>
+ <button type="button" class="btn btn-primary btn-space"
+ onclick="request('/post', {action : 'randomize'})">
+ <i class="fas fa-random" aria-hidden="true"></i>
+ </button>
+ <button type="button" class="btn btn-danger btn-space"
+ onclick="request('/post', {action : 'stop'})">
+ <i class="fas fa-stop" aria-hidden="true"></i>
+ </button>
</div>
<div class="btn-group" style="float: right;">
- <form method="post">
- <input type="text" value="volume_down" name="action" hidden>
- <button type="submit" class="btn btn-warning btn-space"><i class="fa fa-volume-down" aria-hidden="true"></i></button>
- </form>
- <form method="post">
- <input type="text" value="volume_up" name="action" hidden>
- <button type="submit" class="btn btn-warning btn-space"><i class="fa fa-volume-up" aria-hidden="true"></i></button>
- </form>
+ <button type="button" class="btn btn-warning btn-space"
+ onclick="request('/post', {action : 'volume_down'})">
+ <i class="fa fa-volume-down" aria-hidden="true"></i>
+ </button>
+ <button type="button" class="btn btn-warning btn-space"
+ onclick="request('/post', {action : 'volume_up'})">
+ <i class="fa fa-volume-up" aria-hidden="true"></i>
+ </button>
</div>
<table class="table">
<th scope="col">Action</th>
</tr>
</thead>
- <tbody>
- {% if playlist.length() == 0 %}
- <tr class="table-dark">
- <td colspan="4" class="text-muted" style="text-align:center;"> Play list is empty. </td>
- </tr>
- {% else %}
- {% for m in playlist.playlist %}
- {% if loop.index0 == playlist.current_index %}
- <tr class="table-active">
- {% else %}
- <tr>
- {% endif %}
- <th scope="row">{{ loop.index }}</th>
- <td>
- <div class="playlist-title">
- {% if 'thumbnail' in m %}
- <img width="80" src="data:image/PNG;base64,{{ m['thumbnail'] }}"/>
- {% else %}
- <img width="80" src="/static/image/unknown-album.png"/>
- {% endif %}
- </div>
- <div class="playlist-artwork">
- {% if 'title' in m and m['title'].strip() %}
- <b>{{ m['title'] }}</b>
- {% else %}
- <b>{{ m['url'] }}</b>
- {% endif %}
- <span class="badge badge-secondary">{{ m['type'].capitalize() }}</span>
- <br>
- {% if 'artist' in m %}
- {{ m['artist'] }}
- {% else %}
- Unknown Artist
- {% endif %}
- </div>
- </td>
- <td>
- {% if 'url' in m %}
- <small><a href="{{ m['url'] }}"><i>{{ m['url']|truncate(50) }}</i></a></small>
- {% elif 'path' in m %}
- <small>{{ m['path']|truncate(50) }}</small>
- {% endif %}
- </td>
- <td>
- <div class="btn-group">
- <form method="post">
- <input type="text" value="{{ loop.index0 }}" name="play_music" hidden>
- <button type="submit" class="btn btn-success btn-sm btn-space"><i class="fas fa-play"></i></button>
- </form>
- <form method="post">
- <input type="text" value="{{ loop.index0 }}" name="delete_music" hidden>
- <button type="submit" class="btn btn-danger btn-sm btn-space"><i class="fas fa-trash-alt"></i></button>
- </form>
- </div>
- </td>
+ <tbody id="playlist-table">
+ <tr class="table-dark">
+ <td colspan="4" class="text-muted" style="text-align:center;"> Play list is empty. </td>
</tr>
- {% endfor %}
- {% endif %}
</tbody>
</table>
<div class="btn-group">
- <form method="post">
- <input type="text" value="clear" name="action" hidden>
- <button type="submit" class="btn btn-danger btn-space"><i class="fas fa-trash-alt"></i> Clear Playlist</button>
- </form>
+ <button type="button" class="btn btn-danger btn-space"
+ onclick="request('/post', {action : 'clear'})">
+ <i class="fas fa-trash-alt" aria-hidden="true"></i> Clear Playlist
+ </button>
</div>
</div>
</div>
$('a.a-submit, button.btn-submit').on('click', function (event) {
$(event.target).closest('form').submit();
});
+
+ var playlist_ver = 0;
+
+ function request(url, _data){
+ $.ajax({
+ type: 'POST',
+ url: '/post',
+ data : _data,
+ statusCode : {
+ 200 : function(data) {
+ if (data.ver > playlist_ver) {
+ updatePlaylist();
+ playlist_ver = data.ver;
+ }
+ }
+ }
+ });
+ }
+
+ function displayPlaylist(data){
+ $("#playlist-table tr").remove();
+ $.each(data, function(index, item){
+ $("#playlist-table").append(item);
+ })
+ }
+
+ function updatePlaylist(){
+ $.ajax({
+ type: 'GET',
+ url: '/playlist',
+ statusCode : {
+ 200 : displayPlaylist
+ }
+ });
+ }
+
+
+ // Check the version of playlist to see if update is needed.
+ setInterval(function(){
+ $.ajax({
+ type: 'POST',
+ url : '/post',
+ statusCode : {
+ 200 : function(data){
+ if(data.ver > playlist_ver){
+ updatePlaylist();
+ playlist_ver = data.ver;
+ }
+ }
+ }
+ });
+ } , 3000);
+
</script>
</body>