add feature: read album picture from file/url
This commit is contained in:
parent
30879db7b8
commit
98f096f08f
@ -56,6 +56,10 @@ class PlayList:
|
|||||||
|
|
||||||
return self.playlist[self.next_index()]
|
return self.playlist[self.next_index()]
|
||||||
|
|
||||||
|
def jump(self, index):
|
||||||
|
self.current_index = index
|
||||||
|
return self.playlist[index]
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
self.playlist = []
|
self.playlist = []
|
||||||
self.current_index = 0
|
self.current_index = 0
|
||||||
|
121
mumbleBot.py
121
mumbleBot.py
@ -20,6 +20,7 @@ import util
|
|||||||
import base64
|
import base64
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
import mutagen
|
||||||
from mutagen.easyid3 import EasyID3
|
from mutagen.easyid3 import EasyID3
|
||||||
import re
|
import re
|
||||||
import media.url
|
import media.url
|
||||||
@ -37,7 +38,8 @@ type : url
|
|||||||
title
|
title
|
||||||
path
|
path
|
||||||
duration
|
duration
|
||||||
thundnail
|
artist
|
||||||
|
thumbnail
|
||||||
user
|
user
|
||||||
ready (validation, no, downloading, yes)
|
ready (validation, no, downloading, yes)
|
||||||
from_playlist (yes,no)
|
from_playlist (yes,no)
|
||||||
@ -53,7 +55,9 @@ type : radio
|
|||||||
type : file
|
type : file
|
||||||
path
|
path
|
||||||
title
|
title
|
||||||
|
artist
|
||||||
duration
|
duration
|
||||||
|
thumbnail
|
||||||
user
|
user
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -101,6 +105,7 @@ class MumbleBot:
|
|||||||
self.nb_exit = 0
|
self.nb_exit = 0
|
||||||
self.thread = None
|
self.thread = None
|
||||||
self.is_playing = False
|
self.is_playing = False
|
||||||
|
self.is_pause = False
|
||||||
|
|
||||||
if var.config.getboolean("webinterface", "enabled"):
|
if var.config.getboolean("webinterface", "enabled"):
|
||||||
wi_addr = var.config.get("webinterface", "listening_addr")
|
wi_addr = var.config.get("webinterface", "listening_addr")
|
||||||
@ -155,8 +160,6 @@ class MumbleBot:
|
|||||||
self.mumble.channels.find_by_name(self.channel).move_in()
|
self.mumble.channels.find_by_name(self.channel).move_in()
|
||||||
self.mumble.set_bandwidth(200000)
|
self.mumble.set_bandwidth(200000)
|
||||||
|
|
||||||
self.loop()
|
|
||||||
|
|
||||||
# Set the CTRL+C shortcut
|
# Set the CTRL+C shortcut
|
||||||
def ctrl_caught(self, signal, frame):
|
def ctrl_caught(self, signal, frame):
|
||||||
logging.info(
|
logging.info(
|
||||||
@ -602,10 +605,15 @@ class MumbleBot:
|
|||||||
logging.debug("Next into the queue")
|
logging.debug("Next into the queue")
|
||||||
return var.playlist.next()
|
return var.playlist.next()
|
||||||
|
|
||||||
def launch_music(self):
|
def launch_music(self, index=-1):
|
||||||
uri = ""
|
uri = ""
|
||||||
music = var.playlist.next()
|
music = None
|
||||||
logging.debug("launch_music asked" + str(music))
|
if index == -1:
|
||||||
|
music = var.playlist.next()
|
||||||
|
else:
|
||||||
|
music = var.playlist.jump(index)
|
||||||
|
|
||||||
|
logging.debug("launch_music asked" + str(music['path']))
|
||||||
if music["type"] == "url":
|
if music["type"] == "url":
|
||||||
# Delete older music is the tmp folder is too big
|
# Delete older music is the tmp folder is too big
|
||||||
media.system.clear_tmp_folder(var.config.get(
|
media.system.clear_tmp_folder(var.config.get(
|
||||||
@ -619,42 +627,31 @@ class MumbleBot:
|
|||||||
self.download_music(music)
|
self.download_music(music)
|
||||||
if music == False:
|
if music == False:
|
||||||
var.playlist.remove()
|
var.playlist.remove()
|
||||||
|
return
|
||||||
|
|
||||||
# get the Path
|
if self.update_music_tag_info():
|
||||||
uri = music['path']
|
music = var.playlist.current_item()
|
||||||
if os.path.isfile(uri):
|
|
||||||
audio = EasyID3(uri)
|
|
||||||
print(audio["title"])
|
|
||||||
title = ""
|
|
||||||
if audio["title"]:
|
|
||||||
# take the title from the file tag
|
|
||||||
title = audio["title"][0]
|
|
||||||
|
|
||||||
# Remove .mp3 and add .jpg
|
thumbnail_html = '<img width="80" src="data:image/jpge;base64,' + \
|
||||||
path_thumbnail = music['path'][:-4] + '.jpg'
|
music['thumbnail'] + '"/>'
|
||||||
thumbnail_html = ""
|
|
||||||
if os.path.isfile(path_thumbnail):
|
|
||||||
# Create the image message
|
|
||||||
im = Image.open(path_thumbnail)
|
|
||||||
im.thumbnail((100, 100), Image.ANTIALIAS)
|
|
||||||
buffer = BytesIO()
|
|
||||||
im.save(buffer, format="JPEG")
|
|
||||||
thumbnail_base64 = base64.b64encode(buffer.getvalue())
|
|
||||||
thumbnail_html = '<img src="data:image/PNG;base64,' + \
|
|
||||||
thumbnail_base64.decode() + '"/>'
|
|
||||||
|
|
||||||
logging.debug("Thumbail data " + thumbnail_html)
|
|
||||||
if var.config.getboolean('bot', 'announce_current_music'):
|
if var.config.getboolean('bot', 'announce_current_music'):
|
||||||
self.send_msg(var.config.get(
|
self.send_msg(var.config.get(
|
||||||
'strings', 'now_playing') % (title, thumbnail_html))
|
'strings', 'now_playing') % (music['title'], thumbnail_html))
|
||||||
else:
|
|
||||||
logging.error("Error with the path during launch_music")
|
|
||||||
pass
|
|
||||||
|
|
||||||
elif music["type"] == "file":
|
elif music["type"] == "file":
|
||||||
uri = var.config.get('bot', 'music_folder') + \
|
uri = var.config.get('bot', 'music_folder') + \
|
||||||
var.playlist.current_item()["path"]
|
var.playlist.current_item()["path"]
|
||||||
|
|
||||||
|
if self.update_music_tag_info(uri):
|
||||||
|
music = var.playlist.current_item()
|
||||||
|
|
||||||
|
thumbnail_html = '<img width="80" src="data:image/jpge;base64,' + \
|
||||||
|
music['thumbnail'] + '"/>'
|
||||||
|
#logging.debug("Thumbnail data " + thumbnail_html)
|
||||||
|
if var.config.getboolean('bot', 'announce_current_music'):
|
||||||
|
self.send_msg(var.config.get(
|
||||||
|
'strings', 'now_playing') % (music['title'], thumbnail_html))
|
||||||
|
|
||||||
elif music["type"] == "radio":
|
elif music["type"] == "radio":
|
||||||
uri = music["url"]
|
uri = music["url"]
|
||||||
title = media.radio.get_radio_server_description(uri)
|
title = media.radio.get_radio_server_description(uri)
|
||||||
@ -744,6 +741,51 @@ class MumbleBot:
|
|||||||
break
|
break
|
||||||
var.playlist.playlist[index] = music
|
var.playlist.playlist[index] = music
|
||||||
|
|
||||||
|
def update_music_tag_info(self, uri=""):
|
||||||
|
music = var.playlist.current_item()
|
||||||
|
if not music['type'] == 'file' and not music['type'] == 'url':
|
||||||
|
return False
|
||||||
|
|
||||||
|
# get the Path
|
||||||
|
if uri == "":
|
||||||
|
uri = music['path']
|
||||||
|
|
||||||
|
if os.path.isfile(uri):
|
||||||
|
music = self.get_music_tag_info(music, uri)
|
||||||
|
var.playlist.update(music)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
logging.error("Error with the path during launch_music")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_music_tag_info(self, music, uri=""):
|
||||||
|
if not uri:
|
||||||
|
uri = music['path']
|
||||||
|
|
||||||
|
if os.path.isfile(uri):
|
||||||
|
audio = EasyID3(uri)
|
||||||
|
if audio["title"]:
|
||||||
|
# take the title from the file tag
|
||||||
|
music['title'] = audio["title"][0]
|
||||||
|
music['artist'] = ', '.join(audio["artist"])
|
||||||
|
|
||||||
|
path_thumbnail = uri[:-3] + "jpg"
|
||||||
|
if os.path.isfile(path_thumbnail):
|
||||||
|
im = Image.open(path_thumbnail)
|
||||||
|
im.thumbnail((100, 100), Image.ANTIALIAS)
|
||||||
|
buffer = BytesIO()
|
||||||
|
im.save(buffer, format="JPEG")
|
||||||
|
music['thumbnail'] = base64.b64encode(buffer.getvalue()).decode('utf-8')
|
||||||
|
|
||||||
|
# try to extract artwork from mp3 ID3 tag
|
||||||
|
elif uri[-3:] == "mp3":
|
||||||
|
tags = mutagen.File(uri)
|
||||||
|
if "APIC:" in tags:
|
||||||
|
music['thumbnail'] = base64.b64encode(tags["APIC:"].data).decode('utf-8')
|
||||||
|
|
||||||
|
return music
|
||||||
|
|
||||||
|
|
||||||
def async_download_next(self):
|
def async_download_next(self):
|
||||||
# Function start if the next music isn't ready
|
# Function start if the next music isn't ready
|
||||||
# Do nothing in case the next music is already downloaded
|
# Do nothing in case the next music is already downloaded
|
||||||
@ -795,7 +837,7 @@ class MumbleBot:
|
|||||||
# get next music
|
# get next music
|
||||||
self.is_playing = False
|
self.is_playing = False
|
||||||
self.next()
|
self.next()
|
||||||
if len(var.playlist.playlist) > 0:
|
if not self.is_pause and len(var.playlist.playlist) > 0:
|
||||||
if var.playlist.current_item()['type'] in ['radio', 'file'] \
|
if var.playlist.current_item()['type'] in ['radio', 'file'] \
|
||||||
or (var.playlist.current_item()['type'] == 'url' and var.playlist.current_item()['ready'] not in ['validation', 'downloading']):
|
or (var.playlist.current_item()['type'] == 'url' and var.playlist.current_item()['ready'] not in ['validation', 'downloading']):
|
||||||
# Check if the music can be start before launch the music
|
# Check if the music can be start before launch the music
|
||||||
@ -819,6 +861,14 @@ class MumbleBot:
|
|||||||
var.playlist.clear()
|
var.playlist.clear()
|
||||||
self.is_playing = False
|
self.is_playing = False
|
||||||
|
|
||||||
|
def pause(self):
|
||||||
|
# Kill the ffmpeg thread
|
||||||
|
if self.thread:
|
||||||
|
self.thread.kill()
|
||||||
|
self.thread = None
|
||||||
|
self.is_playing = False
|
||||||
|
self.is_pause = True
|
||||||
|
|
||||||
def set_comment(self):
|
def set_comment(self):
|
||||||
self.mumble.users.myself.comment(var.config.get('bot', 'comment'))
|
self.mumble.users.myself.comment(var.config.get('bot', 'comment'))
|
||||||
|
|
||||||
@ -892,4 +942,5 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
var.config = config
|
var.config = config
|
||||||
var.db = db
|
var.db = db
|
||||||
botamusique = MumbleBot(args)
|
var.botamusique = MumbleBot(args)
|
||||||
|
var.botamusique.loop()
|
Loading…
x
Reference in New Issue
Block a user