diff --git a/command.py b/command.py
index 3705fe5..9f24fd9 100644
--- a/command.py
+++ b/command.py
@@ -708,7 +708,7 @@ def cmd_remove(bot, user, text, command, parameter):
if index == var.playlist.current_index:
removed = var.playlist[index]
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())
var.playlist.remove(index)
@@ -781,10 +781,10 @@ def cmd_queue(bot, user, text, command, parameter):
tags = "{}".format(", ".join(music.item().tags))
if i == var.playlist.current_index:
newline = "{} ({}) {} {}".format(i + 1, music.display_type(),
- music.format_short_string(), tags)
+ music.format_title(), tags)
else:
newline = '{} ({}) {} {}'.format(i + 1, music.display_type(),
- music.format_short_string(), tags)
+ music.format_title(), tags)
msgs.append(newline)
@@ -883,7 +883,7 @@ def cmd_add_tag(bot, user, text, command, parameter):
var.playlist[int(index) - 1].format_debug_string()))
bot.send_msg(constants.strings("added_tags",
tags=", ".join(tags),
- song=var.playlist[int(index) - 1].format_short_string()), text)
+ song=var.playlist[int(index) - 1].format_title()), text)
return
elif index == "*":
@@ -922,13 +922,13 @@ def cmd_remove_tag(bot, user, text, command, parameter):
var.playlist[int(index) - 1].format_debug_string()))
bot.send_msg(constants.strings("removed_tags",
tags=", ".join(tags),
- song=var.playlist[int(index) - 1].format_short_string()), text)
+ song=var.playlist[int(index) - 1].format_title()), text)
return
else:
var.playlist[int(index) - 1].clear_tags()
log.info("cmd: clear tags from song %s" % (var.playlist[int(index) - 1].format_debug_string()))
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
elif index == "*":
diff --git a/interface.py b/interface.py
index e4e8d28..6096676 100644
--- a/interface.py
+++ b/interface.py
@@ -7,11 +7,14 @@ import util
import math
import os
import os.path
-import shutil
-from werkzeug.utils import secure_filename
import errno
+from typing import Type
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, \
get_cached_wrapper
from database import MusicDatabase, Condition
@@ -58,7 +61,7 @@ class ReverseProxied(object):
web = Flask(__name__)
-#web.config['TEMPLATES_AUTO_RELOAD'] = True
+web.config['TEMPLATES_AUTO_RELOAD'] = True
log = logging.getLogger("bot")
user = 'Remote Control'
@@ -160,11 +163,7 @@ def index():
@requires_auth
def playlist():
if len(var.playlist) == 0:
- return jsonify({'items': [render_template('playlist.html',
- m=False,
- index=None
- )]
- })
+ return ('', 204)
tags_color_lookup = build_tags_color_lookup() # TODO: cached this?
items = []
@@ -174,27 +173,55 @@ def playlist():
for tag in item_wrapper.item().tags:
tag_tuples.append([tag, tags_color_lookup[tag]])
- items.append(render_template('playlist.html',
- index=index,
- tag_tuples=tag_tuples,
- m=item_wrapper.item(),
- playlist=var.playlist
- )
- )
+ item: Type[BaseItem] = item_wrapper.item()
- 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" { item.url }"
+ elif isinstance(item, PlaylistURLItem):
+ path = f" { item.url }"
+ artist = f" { item.playlist_title }"
+ elif isinstance(item, RadioItem):
+ path = f" { item.url }"
+
+ 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():
if len(var.playlist) > 0:
return jsonify({'ver': var.playlist.version,
+ 'current_index': var.playlist.current_index,
'empty': False,
'play': not var.bot.is_pause,
'mode': var.playlist.mode})
else:
return jsonify({'ver': var.playlist.version,
+ 'current_index': var.playlist.current_index,
'empty': True,
- 'play': False,
+ 'play': not var.bot.is_pause,
'mode': var.playlist.mode})
diff --git a/media/cache.py b/media/cache.py
index b16e4eb..ba709a8 100644
--- a/media/cache.py
+++ b/media/cache.py
@@ -183,7 +183,7 @@ class CachedItemWrapper:
return self.item().format_song_string(self.user)
def format_short_string(self):
- return self.item().format_short_string()
+ return self.item().format_title()
def format_debug_string(self):
return self.item().format_debug_string()
diff --git a/media/file.py b/media/file.py
index 146faf7..91f52a3 100644
--- a/media/file.py
+++ b/media/file.py
@@ -151,7 +151,7 @@ class FileItem(BaseItem):
def format_debug_string(self):
return "[file] {descrip} ({path})".format(
- descrip=self.format_short_string(),
+ descrip=self.format_title(),
path=self.path
)
@@ -171,7 +171,7 @@ class FileItem(BaseItem):
return display
- def format_short_string(self):
+ def format_title(self):
title = self.title if self.title else self.path
if self.artist:
return self.artist + " - " + title
diff --git a/media/item.py b/media/item.py
index c8d7067..91a4e21 100644
--- a/media/item.py
+++ b/media/item.py
@@ -95,7 +95,7 @@ class BaseItem:
def format_current_playing(self, user):
return self.id
- def format_short_string(self):
+ def format_title(self):
return self.title
def format_debug_string(self):
diff --git a/media/playlist.py b/media/playlist.py
index 8affbb3..41798f1 100644
--- a/media/playlist.py
+++ b/media/playlist.py
@@ -90,8 +90,6 @@ class BasePlaylist(list):
if len(self) == 0:
return False
- self.version += 1
-
if self.current_index < len(self) - 1:
self.current_index += 1
return self[self.current_index]
@@ -99,7 +97,6 @@ class BasePlaylist(list):
return False
def point_to(self, index):
- self.version += 1
if -1 <= index < len(self):
self.current_index = index
@@ -134,12 +131,14 @@ class BasePlaylist(list):
return removed
def remove_by_id(self, id):
- self.version += 1
to_be_removed = []
for index, wrapper in enumerate(self):
if wrapper.id == id:
to_be_removed.append(index)
+ if to_be_removed:
+ self.version += 1
+
for index in to_be_removed:
self.remove(index)
@@ -312,8 +311,6 @@ class RepeatPlaylist(BasePlaylist):
if len(self) == 0:
return False
- self.version += 1
-
if self.current_index < len(self) - 1:
self.current_index += 1
return self[self.current_index]
@@ -345,12 +342,11 @@ class RandomPlaylist(BasePlaylist):
if len(self) == 0:
return False
- self.version += 1
-
if self.current_index < len(self) - 1:
self.current_index += 1
return self[self.current_index]
else:
+ self.version += 1
self.randomize()
self.current_index = 0
return self[0]
diff --git a/media/radio.py b/media/radio.py
index 65b1c59..f7e10e5 100644
--- a/media/radio.py
+++ b/media/radio.py
@@ -157,7 +157,7 @@ class RadioItem(BaseItem):
def format_current_playing(self, 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
def display_type(self):
diff --git a/media/url.py b/media/url.py
index 80ac818..2ae011f 100644
--- a/media/url.py
+++ b/media/url.py
@@ -242,7 +242,7 @@ class URLItem(BaseItem):
return display
- def format_short_string(self):
+ def format_title(self):
return self.title if self.title.strip() else self.url
def display_type(self):
diff --git a/mumbleBot.py b/mumbleBot.py
index 27268fd..01e7680 100644
--- a/mumbleBot.py
+++ b/mumbleBot.py
@@ -450,7 +450,7 @@ class MumbleBot:
self.log.error("bot: with ffmpeg error: %s", 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.cache.free_and_delete(current.id)
@@ -466,7 +466,7 @@ class MumbleBot:
self.log.info("bot: current music isn't ready, start downloading.")
self.wait_for_downloading = True
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:
var.playlist.remove_by_id(current.id)
var.cache.free_and_delete(current.id)
diff --git a/static/css/custom.css b/static/css/custom.css
index 77422b6..fd152eb 100644
--- a/static/css/custom.css
+++ b/static/css/custom.css
@@ -4,7 +4,13 @@
.tag-space{margin-right:3px;}
.playlist-title-td{width:60%}
.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{
cursor:pointer;
transition: 400ms;
diff --git a/templates/index.html b/templates/index.html
index 3a4d4db..ec653f9 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -89,6 +89,44 @@
+