refactor: optimized playlist logic
This commit is contained in:
parent
3d3c55a0fb
commit
b2e5efec93
12
command.py
12
command.py
@ -708,7 +708,7 @@ def cmd_remove(bot, user, text, command, parameter):
|
|||||||
if index == var.playlist.current_index:
|
if index == var.playlist.current_index:
|
||||||
removed = var.playlist[index]
|
removed = var.playlist[index]
|
||||||
bot.send_msg(constants.strings('removing_item',
|
bot.send_msg(constants.strings('removing_item',
|
||||||
item=removed.format_short_string()), text)
|
item=removed.format_title()), text)
|
||||||
log.info("cmd: delete from playlist: " + removed.format_debug_string())
|
log.info("cmd: delete from playlist: " + removed.format_debug_string())
|
||||||
|
|
||||||
var.playlist.remove(index)
|
var.playlist.remove(index)
|
||||||
@ -781,10 +781,10 @@ def cmd_queue(bot, user, text, command, parameter):
|
|||||||
tags = "<sup>{}</sup>".format(", ".join(music.item().tags))
|
tags = "<sup>{}</sup>".format(", ".join(music.item().tags))
|
||||||
if i == var.playlist.current_index:
|
if i == var.playlist.current_index:
|
||||||
newline = "<b style='color:orange'>{} ({}) {} </b> {}".format(i + 1, music.display_type(),
|
newline = "<b style='color:orange'>{} ({}) {} </b> {}".format(i + 1, music.display_type(),
|
||||||
music.format_short_string(), tags)
|
music.format_title(), tags)
|
||||||
else:
|
else:
|
||||||
newline = '<b>{}</b> ({}) {} {}'.format(i + 1, music.display_type(),
|
newline = '<b>{}</b> ({}) {} {}'.format(i + 1, music.display_type(),
|
||||||
music.format_short_string(), tags)
|
music.format_title(), tags)
|
||||||
|
|
||||||
msgs.append(newline)
|
msgs.append(newline)
|
||||||
|
|
||||||
@ -883,7 +883,7 @@ def cmd_add_tag(bot, user, text, command, parameter):
|
|||||||
var.playlist[int(index) - 1].format_debug_string()))
|
var.playlist[int(index) - 1].format_debug_string()))
|
||||||
bot.send_msg(constants.strings("added_tags",
|
bot.send_msg(constants.strings("added_tags",
|
||||||
tags=", ".join(tags),
|
tags=", ".join(tags),
|
||||||
song=var.playlist[int(index) - 1].format_short_string()), text)
|
song=var.playlist[int(index) - 1].format_title()), text)
|
||||||
return
|
return
|
||||||
|
|
||||||
elif index == "*":
|
elif index == "*":
|
||||||
@ -922,13 +922,13 @@ def cmd_remove_tag(bot, user, text, command, parameter):
|
|||||||
var.playlist[int(index) - 1].format_debug_string()))
|
var.playlist[int(index) - 1].format_debug_string()))
|
||||||
bot.send_msg(constants.strings("removed_tags",
|
bot.send_msg(constants.strings("removed_tags",
|
||||||
tags=", ".join(tags),
|
tags=", ".join(tags),
|
||||||
song=var.playlist[int(index) - 1].format_short_string()), text)
|
song=var.playlist[int(index) - 1].format_title()), text)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
var.playlist[int(index) - 1].clear_tags()
|
var.playlist[int(index) - 1].clear_tags()
|
||||||
log.info("cmd: clear tags from song %s" % (var.playlist[int(index) - 1].format_debug_string()))
|
log.info("cmd: clear tags from song %s" % (var.playlist[int(index) - 1].format_debug_string()))
|
||||||
bot.send_msg(constants.strings("cleared_tags",
|
bot.send_msg(constants.strings("cleared_tags",
|
||||||
song=var.playlist[int(index) - 1].format_short_string()), text)
|
song=var.playlist[int(index) - 1].format_title()), text)
|
||||||
return
|
return
|
||||||
|
|
||||||
elif index == "*":
|
elif index == "*":
|
||||||
|
63
interface.py
63
interface.py
@ -7,11 +7,14 @@ import util
|
|||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import shutil
|
|
||||||
from werkzeug.utils import secure_filename
|
|
||||||
import errno
|
import errno
|
||||||
|
from typing import Type
|
||||||
import media
|
import media
|
||||||
from media.item import dicts_to_items, dict_to_item
|
from media.item import dicts_to_items, dict_to_item, BaseItem
|
||||||
|
from media.file import FileItem
|
||||||
|
from media.url import URLItem
|
||||||
|
from media.url_from_playlist import PlaylistURLItem
|
||||||
|
from media.radio import RadioItem
|
||||||
from media.cache import get_cached_wrapper_from_scrap, get_cached_wrapper_by_id, get_cached_wrappers_by_tags, \
|
from media.cache import get_cached_wrapper_from_scrap, get_cached_wrapper_by_id, get_cached_wrappers_by_tags, \
|
||||||
get_cached_wrapper
|
get_cached_wrapper
|
||||||
from database import MusicDatabase, Condition
|
from database import MusicDatabase, Condition
|
||||||
@ -58,7 +61,7 @@ class ReverseProxied(object):
|
|||||||
|
|
||||||
|
|
||||||
web = Flask(__name__)
|
web = Flask(__name__)
|
||||||
#web.config['TEMPLATES_AUTO_RELOAD'] = True
|
web.config['TEMPLATES_AUTO_RELOAD'] = True
|
||||||
log = logging.getLogger("bot")
|
log = logging.getLogger("bot")
|
||||||
user = 'Remote Control'
|
user = 'Remote Control'
|
||||||
|
|
||||||
@ -160,11 +163,7 @@ def index():
|
|||||||
@requires_auth
|
@requires_auth
|
||||||
def playlist():
|
def playlist():
|
||||||
if len(var.playlist) == 0:
|
if len(var.playlist) == 0:
|
||||||
return jsonify({'items': [render_template('playlist.html',
|
return ('', 204)
|
||||||
m=False,
|
|
||||||
index=None
|
|
||||||
)]
|
|
||||||
})
|
|
||||||
|
|
||||||
tags_color_lookup = build_tags_color_lookup() # TODO: cached this?
|
tags_color_lookup = build_tags_color_lookup() # TODO: cached this?
|
||||||
items = []
|
items = []
|
||||||
@ -174,27 +173,55 @@ def playlist():
|
|||||||
for tag in item_wrapper.item().tags:
|
for tag in item_wrapper.item().tags:
|
||||||
tag_tuples.append([tag, tags_color_lookup[tag]])
|
tag_tuples.append([tag, tags_color_lookup[tag]])
|
||||||
|
|
||||||
items.append(render_template('playlist.html',
|
item: Type[BaseItem] = item_wrapper.item()
|
||||||
index=index,
|
|
||||||
tag_tuples=tag_tuples,
|
|
||||||
m=item_wrapper.item(),
|
|
||||||
playlist=var.playlist
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
return jsonify({'items': items})
|
title = item.format_title()
|
||||||
|
artist = "??"
|
||||||
|
path = ""
|
||||||
|
if isinstance(item, FileItem):
|
||||||
|
path = item.path
|
||||||
|
if item.artist:
|
||||||
|
artist = item.artist
|
||||||
|
elif isinstance(item, URLItem):
|
||||||
|
path = f" <a href=\"{ item.url }\"><i>{ item.url }</i></a>"
|
||||||
|
elif isinstance(item, PlaylistURLItem):
|
||||||
|
path = f" <a href=\"{ item.url }\"><i>{ item.url }</i></a>"
|
||||||
|
artist = f" <a href=\"{ item.playlist_url }\"><i>{ item.playlist_title }</i></a>"
|
||||||
|
elif isinstance(item, RadioItem):
|
||||||
|
path = f" <a href=\"{ item.url }\"><i>{ item.url }</i></a>"
|
||||||
|
|
||||||
|
thumb = ""
|
||||||
|
if item.type != 'radio' and item.thumbnail:
|
||||||
|
thumb = f"data:image/PNG;base64,{item.thumbnail}"
|
||||||
|
else:
|
||||||
|
thumb = "static/image/unknown-album.png"
|
||||||
|
|
||||||
|
items.append({
|
||||||
|
'index': index,
|
||||||
|
'id': item.id,
|
||||||
|
'type': item.display_type(),
|
||||||
|
'path': path,
|
||||||
|
'title': title,
|
||||||
|
'artist': artist,
|
||||||
|
'thumbnail': thumb,
|
||||||
|
'tags': tag_tuples,
|
||||||
|
})
|
||||||
|
|
||||||
|
return jsonify({'items': items, 'current_index': var.playlist.current_index})
|
||||||
|
|
||||||
|
|
||||||
def status():
|
def status():
|
||||||
if len(var.playlist) > 0:
|
if len(var.playlist) > 0:
|
||||||
return jsonify({'ver': var.playlist.version,
|
return jsonify({'ver': var.playlist.version,
|
||||||
|
'current_index': var.playlist.current_index,
|
||||||
'empty': False,
|
'empty': False,
|
||||||
'play': not var.bot.is_pause,
|
'play': not var.bot.is_pause,
|
||||||
'mode': var.playlist.mode})
|
'mode': var.playlist.mode})
|
||||||
else:
|
else:
|
||||||
return jsonify({'ver': var.playlist.version,
|
return jsonify({'ver': var.playlist.version,
|
||||||
|
'current_index': var.playlist.current_index,
|
||||||
'empty': True,
|
'empty': True,
|
||||||
'play': False,
|
'play': not var.bot.is_pause,
|
||||||
'mode': var.playlist.mode})
|
'mode': var.playlist.mode})
|
||||||
|
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ class CachedItemWrapper:
|
|||||||
return self.item().format_song_string(self.user)
|
return self.item().format_song_string(self.user)
|
||||||
|
|
||||||
def format_short_string(self):
|
def format_short_string(self):
|
||||||
return self.item().format_short_string()
|
return self.item().format_title()
|
||||||
|
|
||||||
def format_debug_string(self):
|
def format_debug_string(self):
|
||||||
return self.item().format_debug_string()
|
return self.item().format_debug_string()
|
||||||
|
@ -151,7 +151,7 @@ class FileItem(BaseItem):
|
|||||||
|
|
||||||
def format_debug_string(self):
|
def format_debug_string(self):
|
||||||
return "[file] {descrip} ({path})".format(
|
return "[file] {descrip} ({path})".format(
|
||||||
descrip=self.format_short_string(),
|
descrip=self.format_title(),
|
||||||
path=self.path
|
path=self.path
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -171,7 +171,7 @@ class FileItem(BaseItem):
|
|||||||
|
|
||||||
return display
|
return display
|
||||||
|
|
||||||
def format_short_string(self):
|
def format_title(self):
|
||||||
title = self.title if self.title else self.path
|
title = self.title if self.title else self.path
|
||||||
if self.artist:
|
if self.artist:
|
||||||
return self.artist + " - " + title
|
return self.artist + " - " + title
|
||||||
|
@ -95,7 +95,7 @@ class BaseItem:
|
|||||||
def format_current_playing(self, user):
|
def format_current_playing(self, user):
|
||||||
return self.id
|
return self.id
|
||||||
|
|
||||||
def format_short_string(self):
|
def format_title(self):
|
||||||
return self.title
|
return self.title
|
||||||
|
|
||||||
def format_debug_string(self):
|
def format_debug_string(self):
|
||||||
|
@ -90,8 +90,6 @@ class BasePlaylist(list):
|
|||||||
if len(self) == 0:
|
if len(self) == 0:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.version += 1
|
|
||||||
|
|
||||||
if self.current_index < len(self) - 1:
|
if self.current_index < len(self) - 1:
|
||||||
self.current_index += 1
|
self.current_index += 1
|
||||||
return self[self.current_index]
|
return self[self.current_index]
|
||||||
@ -99,7 +97,6 @@ class BasePlaylist(list):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def point_to(self, index):
|
def point_to(self, index):
|
||||||
self.version += 1
|
|
||||||
if -1 <= index < len(self):
|
if -1 <= index < len(self):
|
||||||
self.current_index = index
|
self.current_index = index
|
||||||
|
|
||||||
@ -134,12 +131,14 @@ class BasePlaylist(list):
|
|||||||
return removed
|
return removed
|
||||||
|
|
||||||
def remove_by_id(self, id):
|
def remove_by_id(self, id):
|
||||||
self.version += 1
|
|
||||||
to_be_removed = []
|
to_be_removed = []
|
||||||
for index, wrapper in enumerate(self):
|
for index, wrapper in enumerate(self):
|
||||||
if wrapper.id == id:
|
if wrapper.id == id:
|
||||||
to_be_removed.append(index)
|
to_be_removed.append(index)
|
||||||
|
|
||||||
|
if to_be_removed:
|
||||||
|
self.version += 1
|
||||||
|
|
||||||
for index in to_be_removed:
|
for index in to_be_removed:
|
||||||
self.remove(index)
|
self.remove(index)
|
||||||
|
|
||||||
@ -312,8 +311,6 @@ class RepeatPlaylist(BasePlaylist):
|
|||||||
if len(self) == 0:
|
if len(self) == 0:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.version += 1
|
|
||||||
|
|
||||||
if self.current_index < len(self) - 1:
|
if self.current_index < len(self) - 1:
|
||||||
self.current_index += 1
|
self.current_index += 1
|
||||||
return self[self.current_index]
|
return self[self.current_index]
|
||||||
@ -345,12 +342,11 @@ class RandomPlaylist(BasePlaylist):
|
|||||||
if len(self) == 0:
|
if len(self) == 0:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.version += 1
|
|
||||||
|
|
||||||
if self.current_index < len(self) - 1:
|
if self.current_index < len(self) - 1:
|
||||||
self.current_index += 1
|
self.current_index += 1
|
||||||
return self[self.current_index]
|
return self[self.current_index]
|
||||||
else:
|
else:
|
||||||
|
self.version += 1
|
||||||
self.randomize()
|
self.randomize()
|
||||||
self.current_index = 0
|
self.current_index = 0
|
||||||
return self[0]
|
return self[0]
|
||||||
|
@ -157,7 +157,7 @@ class RadioItem(BaseItem):
|
|||||||
def format_current_playing(self, user):
|
def format_current_playing(self, user):
|
||||||
return constants.strings("now_playing", item=self.format_song_string(user))
|
return constants.strings("now_playing", item=self.format_song_string(user))
|
||||||
|
|
||||||
def format_short_string(self):
|
def format_title(self):
|
||||||
return self.title if self.title else self.url
|
return self.title if self.title else self.url
|
||||||
|
|
||||||
def display_type(self):
|
def display_type(self):
|
||||||
|
@ -242,7 +242,7 @@ class URLItem(BaseItem):
|
|||||||
|
|
||||||
return display
|
return display
|
||||||
|
|
||||||
def format_short_string(self):
|
def format_title(self):
|
||||||
return self.title if self.title.strip() else self.url
|
return self.title if self.title.strip() else self.url
|
||||||
|
|
||||||
def display_type(self):
|
def display_type(self):
|
||||||
|
@ -450,7 +450,7 @@ class MumbleBot:
|
|||||||
self.log.error("bot: with ffmpeg error: %s", self.last_ffmpeg_err)
|
self.log.error("bot: with ffmpeg error: %s", self.last_ffmpeg_err)
|
||||||
self.last_ffmpeg_err = ""
|
self.last_ffmpeg_err = ""
|
||||||
|
|
||||||
self.send_msg(constants.strings('unable_play', item=current.format_short_string()))
|
self.send_msg(constants.strings('unable_play', item=current.format_title()))
|
||||||
var.playlist.remove_by_id(current.id)
|
var.playlist.remove_by_id(current.id)
|
||||||
var.cache.free_and_delete(current.id)
|
var.cache.free_and_delete(current.id)
|
||||||
|
|
||||||
@ -466,7 +466,7 @@ class MumbleBot:
|
|||||||
self.log.info("bot: current music isn't ready, start downloading.")
|
self.log.info("bot: current music isn't ready, start downloading.")
|
||||||
self.wait_for_downloading = True
|
self.wait_for_downloading = True
|
||||||
var.playlist.async_prepare(var.playlist.current_index)
|
var.playlist.async_prepare(var.playlist.current_index)
|
||||||
self.send_msg(constants.strings('download_in_progress', item=current.format_short_string()))
|
self.send_msg(constants.strings('download_in_progress', item=current.format_title()))
|
||||||
else:
|
else:
|
||||||
var.playlist.remove_by_id(current.id)
|
var.playlist.remove_by_id(current.id)
|
||||||
var.cache.free_and_delete(current.id)
|
var.cache.free_and_delete(current.id)
|
||||||
|
@ -4,7 +4,13 @@
|
|||||||
.tag-space{margin-right:3px;}
|
.tag-space{margin-right:3px;}
|
||||||
.playlist-title-td{width:60%}
|
.playlist-title-td{width:60%}
|
||||||
.playlist-title{float:left; }
|
.playlist-title{float:left; }
|
||||||
.playlist-artwork{float:left; margin-left:10px;}
|
.playlist-item {transition: all 0.2s ease-in-out;}
|
||||||
|
.playlist-artwork{
|
||||||
|
float:left;
|
||||||
|
margin-left:10px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
.tag-click{
|
.tag-click{
|
||||||
cursor:pointer;
|
cursor:pointer;
|
||||||
transition: 400ms;
|
transition: 400ms;
|
||||||
|
@ -89,6 +89,44 @@
|
|||||||
<img style="margin: auto; width: 35px;" src="static/image/loading.svg" />
|
<img style="margin: auto; width: 35px;" src="static/image/loading.svg" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr id="playlist-empty" style="display: none;">
|
||||||
|
<td colspan="4" style="text-align:center;">
|
||||||
|
<img style="margin: auto; width: 35px;" src="static/image/empty_box.svg" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="playlist-item-template" style="display: none;">
|
||||||
|
<input hidden type="text" class="playlist-item-id" value="" />
|
||||||
|
<th scope="row" class="playlist-item-index"></th>
|
||||||
|
<td>
|
||||||
|
<div class="playlist-title">
|
||||||
|
<img width="80" class="playlist-item-thumbnail" src="static/image/unknown-album.png"/>
|
||||||
|
</div>
|
||||||
|
<div class="playlist-artwork">
|
||||||
|
<b class="playlist-item-title"></b>
|
||||||
|
<span class="playlist-item-type badge badge-secondary"></span>
|
||||||
|
<br />
|
||||||
|
<span class="playlist-item-artist"></span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<div class="playlist-item-tags">
|
||||||
|
<a class="playlist-item-edit tag-space tag-click"><i class="fas fa-edit" style="color: #AAAAAA"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<small class="playlist-item-path"></small>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="btn-group">
|
||||||
|
<button type="button" class="playlist-item-play btn btn-info btn-sm btn-space">
|
||||||
|
<i class="fa fa-play" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
<button type="button" class="playlist-item-trash btn btn-danger btn-sm btn-space">
|
||||||
|
<i class="fas fa-trash-alt" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@ -410,7 +448,34 @@
|
|||||||
$(event.target).closest('form').submit();
|
$(event.target).closest('form').submit();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
// ------ Playlist ------
|
||||||
|
// ----------------------
|
||||||
|
|
||||||
|
|
||||||
|
var pl_item_template = $(".playlist-item-template");
|
||||||
|
var pl_id_element = $(".playlist-item-id");
|
||||||
|
var pl_index_element = $(".playlist-item-index");
|
||||||
|
var pl_title_element = $(".playlist-item-title");
|
||||||
|
var pl_artist_element = $(".playlist-item-artist");
|
||||||
|
var pl_thumb_element = $(".playlist-item-thumbnail");
|
||||||
|
var pl_type_element = $(".playlist-item-type");
|
||||||
|
var pl_path_element = $(".playlist-item-path");
|
||||||
|
|
||||||
|
var pl_tag_edit_element = $(".playlist-item-edit");
|
||||||
|
|
||||||
|
var notag_element = $(".library-item-notag"); // these elements are shared with library
|
||||||
|
var tag_element = $(".library-item-tag");
|
||||||
|
|
||||||
|
var add_tag_modal = $("#addTagModal");
|
||||||
|
|
||||||
|
var playlist_loading = $("#playlist-loading");
|
||||||
|
var playlist_table = $("#playlist-table");
|
||||||
|
var playlist_empty = $("#playlist-empty");
|
||||||
|
|
||||||
var playlist_ver = 0;
|
var playlist_ver = 0;
|
||||||
|
var playlist_current_index = 0;
|
||||||
|
|
||||||
function request(_url, _data, refresh=false){
|
function request(_url, _data, refresh=false){
|
||||||
console.log(_data);
|
console.log(_data);
|
||||||
@ -433,38 +498,124 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var loading = $("#playlist-loading");
|
function addPlaylistItem(item){
|
||||||
var table = $("#playlist-table");
|
pl_id_element.val(item.id);
|
||||||
function displayPlaylist(data){
|
pl_index_element.html(item.index + 1);
|
||||||
// console.info(data);
|
pl_title_element.html(item.title);
|
||||||
table.animate({opacity: 0}, 200, function(){
|
pl_artist_element.html(item.artist);
|
||||||
loading.hide();
|
pl_thumb_element.attr("src", item.thumbnail);
|
||||||
$("#playlist-table .playlist-item").remove();
|
pl_type_element.html(item.type);
|
||||||
|
pl_path_element.html(item.path);
|
||||||
|
|
||||||
var items = data.items;
|
var item_copy = pl_item_template.clone();
|
||||||
$.each(items, function(index, item){
|
item_copy.attr("id", "playlist-item-" + item.index);
|
||||||
table.append(item);
|
item_copy.addClass("playlist-item");
|
||||||
|
|
||||||
|
var tags = item_copy.find(".playlist-item-tags");
|
||||||
|
tags.empty();
|
||||||
|
|
||||||
|
var tag_edit_copy = pl_tag_edit_element.clone();
|
||||||
|
tag_edit_copy.click(function(){
|
||||||
|
addTagModalShow(item.id, item.title, item.tags);
|
||||||
});
|
});
|
||||||
|
tag_edit_copy.appendTo(tags);
|
||||||
|
|
||||||
table.animate({opacity: 1}, 200);
|
if(item.tags.length > 0){
|
||||||
|
item.tags.forEach(function (tag_tuple){
|
||||||
|
tag_copy = tag_element.clone();
|
||||||
|
tag_copy.html(tag_tuple[0]);
|
||||||
|
tag_copy.addClass("badge-" + tag_tuple[1]);
|
||||||
|
tag_copy.appendTo(tags);
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
tag_copy = notag_element.clone();
|
||||||
|
tag_copy.appendTo(tags);
|
||||||
|
}
|
||||||
|
|
||||||
|
item_copy.appendTo(playlist_table);
|
||||||
|
item_copy.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayPlaylist(data){
|
||||||
|
playlist_table.animate({opacity: 0}, 200, function(){
|
||||||
|
playlist_loading.hide();
|
||||||
|
$(".playlist-item").remove();
|
||||||
|
var items = data.items;
|
||||||
|
items.forEach(
|
||||||
|
function (item) {
|
||||||
|
addPlaylistItem(item);
|
||||||
|
bindPlaylistEvent();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
displayActiveItem(data.current_index);
|
||||||
|
playlist_table.animate({opacity: 1}, 200);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function displayActiveItem(current_index){
|
||||||
|
$(".playlist-item").removeClass("table-active");
|
||||||
|
$("#playlist-item-"+current_index).addClass("table-active");
|
||||||
|
}
|
||||||
|
|
||||||
function updatePlaylist(){
|
function updatePlaylist(){
|
||||||
table.animate({opacity: 0}, 200, function(){
|
playlist_table.animate({opacity: 0}, 200, function(){
|
||||||
loading.show();
|
playlist_empty.hide();
|
||||||
|
playlist_loading.show();
|
||||||
$("#playlist-table .playlist-item").css("opacity", 0);
|
$("#playlist-table .playlist-item").css("opacity", 0);
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
url: 'playlist',
|
url: 'playlist',
|
||||||
statusCode : {
|
statusCode : {
|
||||||
200: displayPlaylist
|
200: displayPlaylist,
|
||||||
|
204: function(){
|
||||||
|
playlist_loading.hide();
|
||||||
|
playlist_empty.show();
|
||||||
|
$(".playlist-item").remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
table.animate({opacity: 1}, 200);
|
playlist_table.animate({opacity: 1}, 200);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkForPlaylistUpdate(){
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url : 'post',
|
||||||
|
statusCode : {
|
||||||
|
200 : function(data){
|
||||||
|
if(data.ver !== playlist_ver){
|
||||||
|
playlist_ver = data.ver;
|
||||||
|
updatePlaylist();
|
||||||
|
}
|
||||||
|
if(data.current_index !== playlist_current_index){
|
||||||
|
playlist_current_index = data.current_index;
|
||||||
|
displayActiveItem(data.current_index);
|
||||||
|
}
|
||||||
|
updateControls(data.empty, data.play, data.mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function bindPlaylistEvent() {
|
||||||
|
$(".playlist-item-play").unbind().click(
|
||||||
|
function (e) {
|
||||||
|
request('post', {
|
||||||
|
'play_music': ($(e.currentTarget).parent().parent().parent().find(".playlist-item-index").html() - 1)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$(".playlist-item-trash").unbind().click(
|
||||||
|
function (e) {
|
||||||
|
request('post', {
|
||||||
|
'delete_music': ($(e.currentTarget).parent().parent().parent().find(".playlist-item-index").html() - 1)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function updateControls(empty, play, mode){
|
function updateControls(empty, play, mode){
|
||||||
if(empty){
|
if(empty){
|
||||||
$("#play-btn").prop("disabled", true);
|
$("#play-btn").prop("disabled", true);
|
||||||
@ -531,23 +682,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check the version of playlist to see if update is needed.
|
// Check the version of playlist to see if update is needed.
|
||||||
setInterval(function(){
|
setInterval(checkForPlaylistUpdate , 3000);
|
||||||
$.ajax({
|
|
||||||
type: 'POST',
|
|
||||||
url : 'post',
|
|
||||||
statusCode : {
|
|
||||||
200 : function(data){
|
|
||||||
if(data.ver !== playlist_ver){
|
|
||||||
playlist_ver = data.ver;
|
|
||||||
updatePlaylist();
|
|
||||||
}
|
|
||||||
updateControls(data.empty, data.play, data.mode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} , 3000);
|
|
||||||
|
|
||||||
|
// ---------------------
|
||||||
// ------ Browser ------
|
// ------ Browser ------
|
||||||
|
// ---------------------
|
||||||
var filter_file = false;
|
var filter_file = false;
|
||||||
var filter_url = false;
|
var filter_url = false;
|
||||||
var filter_radio = false;
|
var filter_radio = false;
|
||||||
@ -665,10 +804,10 @@
|
|||||||
var path_element = $(".library-item-path");
|
var path_element = $(".library-item-path");
|
||||||
|
|
||||||
var tag_edit_element = $(".library-item-edit");
|
var tag_edit_element = $(".library-item-edit");
|
||||||
var notag_element = $(".library-item-notag");
|
//var notag_element = $(".library-item-notag");
|
||||||
var tag_element = $(".library-item-tag");
|
//var tag_element = $(".library-item-tag");
|
||||||
|
|
||||||
var add_tag_modal = $("#addTagModal");
|
//var add_tag_modal = $("#addTagModal");
|
||||||
|
|
||||||
function addResultItem(item){
|
function addResultItem(item){
|
||||||
id_element.val(item.id);
|
id_element.val(item.id);
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
{% if index == None %}
|
|
||||||
<tr id="playlist-empty" class="playlist-item">
|
|
||||||
<td colspan="4" style="text-align:center;">
|
|
||||||
<img style="margin: auto; width: 35px;" src="static/image/empty_box.svg" />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% else %}
|
|
||||||
{% if index == playlist.current_index %}
|
|
||||||
<tr class="playlist-item table-active">
|
|
||||||
{% else %}
|
|
||||||
<tr class="playlist-item">
|
|
||||||
{% endif %}
|
|
||||||
<th scope="row">{{ index + 1 }}</th>
|
|
||||||
<td>
|
|
||||||
<div class="playlist-title">
|
|
||||||
{% if m.type != 'radio' and m.thumbnail %}
|
|
||||||
<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 m.title.strip() %}
|
|
||||||
<b>{{ m.title|truncate(45) }}</b>
|
|
||||||
{% elif m.url %}
|
|
||||||
<b>{{ m.url|truncate(45) }}</b>
|
|
||||||
{% endif %}
|
|
||||||
<span class="badge badge-secondary">{{ m.display_type() }}</span>
|
|
||||||
<br />
|
|
||||||
{% if m.type == 'file' %}
|
|
||||||
{% if m.artist %}
|
|
||||||
{{ m.artist }}
|
|
||||||
{% else %}
|
|
||||||
??
|
|
||||||
{% endif %}
|
|
||||||
{% elif m.type == 'url_from_playlist' %}
|
|
||||||
<a href="{{ m.playlist_url }}"><i>{{ m.playlist_title|truncate(50) }}</i></a>
|
|
||||||
{% else %}
|
|
||||||
Unknown Artist
|
|
||||||
{% endif %}
|
|
||||||
<br />
|
|
||||||
|
|
||||||
<a class="tag-space tag-click"
|
|
||||||
onclick='addTagModalShow("{{ m.id }}", "{{ m.title }}", {{ tag_tuples | tojson }});'><i class="fas fa-edit" style="color: #AAAAAA"></i></a>
|
|
||||||
{% for tag_tuple in tag_tuples %}
|
|
||||||
<span class="badge badge-{{ tag_tuple[1] }}">{{ tag_tuple[0] }}</span>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{% if m.type == 'url' or m.type == 'radio' or m.type == 'url_from_playlist' %}
|
|
||||||
<small><a href="{{ m.url }}"><i>{{ m.url|truncate(50) }}</i></a></small>
|
|
||||||
{% elif m.type == 'file' %}
|
|
||||||
<small>{{ m.path|truncate(50) }}</small>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div class="btn-group">
|
|
||||||
<button type="button" class="btn btn-info btn-sm btn-space"
|
|
||||||
onclick="request('post', {play_music : '{{ index }}'})">
|
|
||||||
<i class="fa fa-play" aria-hidden="true"></i>
|
|
||||||
</button>
|
|
||||||
<button type="button" class="btn btn-danger btn-sm btn-space"
|
|
||||||
onclick="request('post', {delete_music : '{{ index }}'})">
|
|
||||||
<i class="fas fa-trash-alt" aria-hidden="true"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
|
Loading…
x
Reference in New Issue
Block a user