作成者 | SHA1 | メッセージ | 日付 |
---|---|---|---|
choj | a014d9b1b9 | v2 initial python script | 3年前 |
choj | 8e6f937efb | UI stuff + audio player implementation | 4年前 |
choj | c4d7522dc7 | début refonte v2 | 4年前 |
@@ -1,6 +1,6 @@ | |||||
# Labelize | # Labelize | ||||
Music album web page generator : 1 folder with music files + 1 cover image = 1 single page app with audio player | |||||
Music band web page generator : 1 folder with music files + images + 1 optional configuration file = 1 single page app with audio player | |||||
# Installation | # Installation | ||||
@@ -11,10 +11,28 @@ $ pip install -r requirements.txt | |||||
``` | ``` | ||||
#Configuration | |||||
In a labelize.yaml file : | |||||
```` | |||||
band: band name | |||||
images: | |||||
cover: my_cover_image.png | |||||
contact: my_contact_image.png | |||||
albums_section : | |||||
title: Album section tile | |||||
albums: | |||||
- year : 2019 | |||||
title : my album title | |||||
- year : 2018 | |||||
title : my album title | |||||
```` | |||||
# Usage | # Usage | ||||
``` | ``` | ||||
$ python labelize.py inputDirectory outputDirectory | |||||
$ python labelize.py [inputDirectory] [outputDirectory] | |||||
``` | ``` | ||||
# Credentials | # Credentials | ||||
@@ -0,0 +1,102 @@ | |||||
@font-face { | |||||
font-family: "work-sans"; | |||||
src: url('../fonts/work-sans/WorkSans-Regular.otf'); | |||||
} | |||||
:root{ | |||||
--footer-font-family : 'work-sans'; | |||||
--pretty-margin: 0.5rem; | |||||
--main-color: red; | |||||
--secondary-color: rgb(0,42,255); | |||||
} | |||||
*{ | |||||
margin: 0; | |||||
padding: 0; | |||||
} | |||||
body{ | |||||
font-family: var(--footer-font-family); | |||||
font-size: 2rem; | |||||
letter-spacing: 0.1rem; | |||||
} | |||||
.point { | |||||
margin: 0px var(--pretty-margin); | |||||
} | |||||
.pipe { | |||||
margin: 0px calc(3 * var(--pretty-margin)); | |||||
} | |||||
section{ | |||||
height: 100vh; | |||||
} | |||||
section h2 { | |||||
font-size: 2rem; | |||||
} | |||||
section:nth-of-type(odd){ | |||||
background-color: white; | |||||
color: var(--secondary-color); | |||||
} | |||||
section:nth-of-type(even){ | |||||
background-color: var(--secondary-color); | |||||
color: white; | |||||
} | |||||
section.cover{ | |||||
background : url(../images/cover.png) no-repeat center center; | |||||
background-color: var(--main-color); | |||||
} | |||||
section.albums{ | |||||
background-color: black; | |||||
color:white; | |||||
display: flex; | |||||
flex-direction: column; | |||||
justify-content: center; | |||||
line-height: 200%; | |||||
} | |||||
section.albums > * { | |||||
padding-left: 10vw; | |||||
} | |||||
section.albums h2 { | |||||
padding-left: 20vw; | |||||
font-weight: normal; | |||||
} | |||||
section.albums ul { | |||||
list-style-type: none; | |||||
} | |||||
section.contact{ | |||||
display : flex; | |||||
flex-direction: column; | |||||
justify-content: center; | |||||
align-items: center; | |||||
position :relative; | |||||
background : url(../images/contact.png) no-repeat center center; | |||||
background-color: var(--secondary-color); | |||||
color:white; | |||||
} | |||||
footer{ | |||||
font-size: 0.92rem; | |||||
position: absolute; | |||||
width: 100%; | |||||
bottom: 0; | |||||
text-align: center; | |||||
} | |||||
.hidden{ | |||||
display: none; | |||||
} |
@@ -0,0 +1,108 @@ | |||||
:root{ | |||||
--one-dpi: 72px; | |||||
--dd-blue: rgb(0,42,255); | |||||
} | |||||
.dd-player{ | |||||
width: 25vw; | |||||
height: 100vh; | |||||
position:fixed; | |||||
top: 0px; | |||||
background-color: white; | |||||
right:0px; | |||||
color: black; | |||||
padding-top: var(--one-dpi); | |||||
padding-bottom: var(--one-dpi); | |||||
display: flex; | |||||
flex-direction: column; | |||||
justify-content: space-between; | |||||
} | |||||
.collapsed{ | |||||
display: none; | |||||
} | |||||
.dd-player-switch{ | |||||
position :fixed; | |||||
bottom: 0; | |||||
right: 0; | |||||
width: var(--one-dpi); | |||||
height:var(--one-dpi); | |||||
background-color: white; | |||||
cursor: pointer; | |||||
z-index:10; | |||||
} | |||||
.dd-player-switch.opened{ | |||||
background-color: var(--dd-blue); | |||||
} | |||||
.dd-player h3 { | |||||
font-size: 1rem; | |||||
/*margin-top: calc(2 * var(--one-dpi));*/ | |||||
margin: calc(var(--one-dpi) / 2); | |||||
/* margin-bottom : var(--one-dpi); */ | |||||
} | |||||
.dd-player ul { | |||||
margin-left : calc(var(--one-dpi) / 2); | |||||
color: var(--dd-blue); | |||||
font-size: 1.5rem; | |||||
list-style-type : none; | |||||
} | |||||
.dd-player ul li img{ | |||||
width:24px; | |||||
height:24px; | |||||
margin-right: 12px; | |||||
} | |||||
.playing{ | |||||
font-weight: bold; | |||||
color : black; | |||||
} | |||||
.progress-wrap{ | |||||
display:flex; | |||||
width: 100%; | |||||
justify-content: space-around; | |||||
} | |||||
.progress-wrap .time-info{ | |||||
font-size:0.66rem; | |||||
display: flex; | |||||
justify-content: center; | |||||
/* align-items: center; */ | |||||
} | |||||
progress{ | |||||
display: inline; | |||||
/* margin: 0 calc(var(--one-dpi) / 2); */ | |||||
/* max-width: calc(100% - var(--one-dpi)); */ | |||||
height: 10px; | |||||
width:66%; | |||||
} | |||||
#play-button{ | |||||
max-width: calc(var(--one-dpi) / 2); | |||||
max-height: calc(var(--one-dpi) / 2); | |||||
margin: calc(var(--one-dpi) / 2); | |||||
} | |||||
progress::-moz-progress-bar{ | |||||
background-color: black; | |||||
} | |||||
progress{ | |||||
background-color: #rgba(200,200,200,0.5); | |||||
} | |||||
.dd-player ul li, #play-button{ | |||||
cursor : pointer; | |||||
} | |||||
#wrap-playlist{ | |||||
flex: 1; | |||||
} |
@@ -1,4 +1,5 @@ | |||||
Copyright 2012 Google Inc. All Rights Reserved. | |||||
Copyright (c) 2014-2015 Wei Huang (wweeiihhuuaanngg@gmail.com) | |||||
This Font Software is licensed under the SIL Open Font License, Version 1.1. | This Font Software is licensed under the SIL Open Font License, Version 1.1. | ||||
This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL | This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL |
@@ -0,0 +1,70 @@ | |||||
import DedePlayer from './player.js'; | |||||
window.addEventListener('DOMContentLoaded', (event) => { | |||||
const player = new DedePlayer(document.getElementById('player')); | |||||
}) | |||||
//var current = undefined | |||||
//const progressMargin = 50; | |||||
//var progress = undefined; | |||||
//window.addEventListener('DOMContentLoaded', (event) => { | |||||
// progress = document.getElementById('player-progress'); | |||||
// document.getElementById('player-progress').addEventListener('click', (e) => { | |||||
// if(current){ | |||||
// let media = current.getElementsByTagName('audio')[0]; | |||||
// media.currentTime = e.layerX * media.duration / progress.offsetWidth; | |||||
// | |||||
// } | |||||
// }); | |||||
// | |||||
// let toggler = document.getElementById('player-toggler'); | |||||
// toggler.setAttribute('title','afficher/masquer la liste des morceaux'); | |||||
// toggler.addEventListener('click', (e) => { | |||||
// document.getElementsByTagName('ul')[0].classList.toggle('invisible'); | |||||
// }) | |||||
//}); | |||||
// | |||||
// | |||||
//function togglePlay(src) { | |||||
// let media = src.getElementsByTagName('audio')[0]; | |||||
// let icon = src.getElementsByTagName('img')[0]; | |||||
// if (current){//stops current media and reset its play icon | |||||
// pause(); | |||||
// } | |||||
// if(current != src){ | |||||
// //sets current media icon and plays media | |||||
// icon.setAttribute('src','assets/pause.png'); | |||||
// media.play(); | |||||
// progress.max = Math.floor(media.duration); | |||||
// current = src; | |||||
// document.getElementById('time-info').style.visibility = 'visible'; | |||||
// } | |||||
// else{ | |||||
// current = undefined; | |||||
// } | |||||
//} | |||||
// | |||||
//function pause(){ | |||||
// current.getElementsByTagName('audio')[0].pause(); | |||||
// current.getElementsByTagName('img')[0].setAttribute('src','assets/play.png'); | |||||
// document.getElementById('time-info').style.visibility = 'hidden'; | |||||
//} | |||||
// | |||||
//function updateProgress(media){ | |||||
// progress.value = Math.floor(media.currentTime); | |||||
// document.getElementById('time-info').innerHTML = | |||||
// prettyDuration(media.currentTime) + ' / ' + prettyDuration(media.duration); | |||||
//} | |||||
// | |||||
//function prettyDuration(duration) { | |||||
// let sec = Math.floor( duration ); | |||||
// let min = Math.floor( sec / 60 ); | |||||
// min = min >= 10 ? min : '0' + min; | |||||
// sec = Math.floor( sec % 60 ); | |||||
// sec = sec >= 10 ? sec : '0' + sec; | |||||
// return min + ':' + sec; | |||||
//} | |||||
// | |||||
//function togglePlayer(playerId, dpiId){ | |||||
// document.getElementById(playerId).classList.toggle('hidden'); | |||||
// document.getElementById(dpiId).classList.toggle('clicked'); | |||||
//} |
@@ -0,0 +1,173 @@ | |||||
export default class DedePlayer{ | |||||
constructor(container){ | |||||
this.currentAudio = null; | |||||
this.playing = false; | |||||
this.playerContainer = document.createElement("div"); | |||||
this.container = container; | |||||
this.playerContainer.classList.add('dd-player'); | |||||
this.switcher = document.createElement("div"); | |||||
this.switcher.classList.add('dd-player-switch'); | |||||
this.playerContainer.classList.add('collapsed'); | |||||
//document.body.appendChild(this.container); | |||||
document.body.appendChild(this.switcher); | |||||
this.switcher.addEventListener('click', event => { | |||||
this.playerContainer.classList.toggle('collapsed'); | |||||
this.switcher.classList.toggle('opened'); | |||||
}); | |||||
let title = document.createElement("h3"); | |||||
//title.innerHTML = playList.title; | |||||
title.appendChild(document.createTextNode(this.container.dataset.title)); | |||||
this.addProgressBar(); | |||||
// this.container.appendChild(title); | |||||
this.bindAudioTags(); | |||||
this.addPlayButton(); | |||||
//console.log(Math.floor(this.currentAudio.duration)); | |||||
// let playerLinks = document.querySelectorAll('.dd-player-link'); | |||||
// let self = this; | |||||
// playerLinks.forEach(function(pl){ | |||||
// pl.addEventListener('click', (e) => { | |||||
// self.container.classList.toggle('collapsed'); | |||||
// self.switcher.classList.toggle('opened'); | |||||
// }) | |||||
// }); | |||||
let wrap = document.createElement("div"); | |||||
wrap.setAttribute('id', 'wrap-playlist') | |||||
this.container.parentElement.appendChild(this.playerContainer); | |||||
this.playerContainer.appendChild(title); | |||||
this.playerContainer.appendChild(wrap); | |||||
wrap.appendChild(this.container); | |||||
}; | |||||
addProgressBar(){ | |||||
this.progressBar = document.createElement("progress"); | |||||
this.progressBar.setAttribute('value', 0); | |||||
this.startTimeInfo = document.createElement('div'); | |||||
this.endTimeInfo = document.createElement('div'); | |||||
let progressWrap = document.createElement("div"); | |||||
this.startTimeInfo.innerHTML = "00:00"; | |||||
this.endTimeInfo.innerHTML = "00:00"; | |||||
progressWrap.appendChild(this.startTimeInfo); | |||||
progressWrap.appendChild(this.progressBar); | |||||
progressWrap.appendChild(this.endTimeInfo); | |||||
this.startTimeInfo.classList.add('time-info'); | |||||
this.endTimeInfo.classList.add('time-info'); | |||||
progressWrap.classList.add('progress-wrap'); | |||||
this.playerContainer.append(progressWrap); | |||||
let self = this; | |||||
this.progressBar.addEventListener('click', (e) => { | |||||
if(self.currentAudio){ | |||||
self.currentAudio.currentTime = Math.floor(((e.layerX - self.progressBar.offsetLeft) * self.currentAudio.duration) / self.progressBar.offsetWidth); | |||||
self.progressBar.value = Math.floor(self.currentAudio.currentTime ); | |||||
} | |||||
}); | |||||
} | |||||
addPlayButton(){ | |||||
this.playButton = document.createElement("img"); | |||||
this.playButton.setAttribute('src','assets/images/play.png'); | |||||
this.playButton.setAttribute('id','play-button'); | |||||
let wrap = document.createElement("div"); | |||||
wrap.append(this.playButton); | |||||
this.container.append(wrap); | |||||
let self = this; | |||||
this.playButton.addEventListener('click', event => { | |||||
self.playing = !self.playing; | |||||
if(self.playing){ | |||||
self.currentAudio.play(); | |||||
self.currentAudio.parentElement.classList.add('playing'); | |||||
self.progressBar.setAttribute('max', Math.floor(self.currentAudio.duration)); | |||||
self.endTimeInfo.innerHTML = self.formatDuration(self.currentAudio.duration); | |||||
this.playButton.setAttribute('src','assets/images/pause.png'); | |||||
} | |||||
else{ | |||||
self.currentAudio.pause(); | |||||
self.currentAudio.parentElement.classList.remove('playing'); | |||||
this.playButton.setAttribute('src','assets/images/play.png'); | |||||
} | |||||
}) | |||||
} | |||||
bindAudioTags(){ | |||||
//let listElement = document.createElement("ul"); | |||||
let liTags = this.container.querySelectorAll('li') | |||||
let self = this; | |||||
let i = 0; | |||||
liTags.forEach(function(itemElement){ | |||||
// //let playBtn = document.createElement("img"); | |||||
// //playBtn.setAttribute('src','images/icons/play.png'); | |||||
// let itemElement = document.createElement("li"); | |||||
// //itemElement.appendChild(playBtn); | |||||
// itemElement.appendChild(document.createTextNode(track.title)); | |||||
// listElement.appendChild(itemElement); | |||||
// let audioElement = document.createElement('audio'); | |||||
// audioElement.setAttribute('src',track.src); | |||||
let audioTag = itemElement.querySelector('audio') | |||||
audioTag.addEventListener('timeupdate', (event) => { | |||||
self.audioTimeUpdate(audioTag); | |||||
}); | |||||
audioTag.addEventListener('ended', (event) => { | |||||
self.audioEnded(i); | |||||
}) | |||||
//itemElement.appendChild(audioElement); | |||||
audioTag.setAttribute('id','track-'+i); | |||||
if(i === 0) | |||||
self.currentAudio = audioTag; | |||||
itemElement.addEventListener('click', event => { | |||||
let items = self.container.getElementsByTagName('li'); | |||||
for(let i = 0; i < items.length; i++){ | |||||
items[i].classList.remove('playing'); | |||||
} | |||||
if(self.currentAudio) | |||||
self.currentAudio.pause(); | |||||
audioTag.play(); | |||||
self.playButton.setAttribute('src','assets/images/pause.png'); | |||||
self.playing = true; | |||||
itemElement.classList.add('playing'); | |||||
self.currentAudio = audioTag; | |||||
self.progressBar.setAttribute('max', Math.floor(self.currentAudio.duration)); | |||||
self.endTimeInfo.innerHTML = self.formatDuration(self.currentAudio.duration); | |||||
self.progressBar.setAttribute('value', 0); | |||||
}); | |||||
i++; | |||||
}); | |||||
} | |||||
audioTimeUpdate(audioElt){ | |||||
this.progressBar.value = Math.floor(audioElt.currentTime); | |||||
this.startTimeInfo.innerHTML = this.formatDuration(audioElt.currentTime); | |||||
} | |||||
audioEnded(n){ | |||||
let audios = document.getElementsByTagName('audio'); | |||||
let next = n == audios.length - 1 ? 0 : n + 1; | |||||
this.currentAudio.pause(); | |||||
this.currentAudio.currentTime = 0; | |||||
this.currentAudio = document.getElementsByTagName('audio')[next]; | |||||
this.currentAudio.parentElement.click(); | |||||
} | |||||
formatDuration(time){ | |||||
let s = parseInt(time% 60); | |||||
let m = parseInt((time / 60) % 60); | |||||
return (m < 10 ? ('0'+m) : m) + ':' + (s < 10 ? ('0'+s) : s); | |||||
} | |||||
} |
@@ -1,124 +0,0 @@ | |||||
@font-face { | |||||
font-family: "NotoSans"; | |||||
src: url(./fonts/noto-sans/NotoSans-Regular.ttf); | |||||
} | |||||
:root { | |||||
--main-bg-color: rgba(255,255,255,0.7); | |||||
} | |||||
*{ | |||||
margin: 0; | |||||
padding: 0; | |||||
box-sizing: border-box; | |||||
} | |||||
html{ | |||||
font-family: NotoSans; | |||||
color: black; | |||||
} | |||||
html, body{ | |||||
width: 100vw; | |||||
height: 100vh; | |||||
background-color: black; | |||||
} | |||||
body{ | |||||
display: flex; | |||||
align-items: center; | |||||
justify-content: center; | |||||
} | |||||
.track-list{ | |||||
width: 100vh; | |||||
height: 100vh; | |||||
background-image: url(../cover.jpg); | |||||
background-size: cover; | |||||
background-repeat: no-repeat; | |||||
display: flex; | |||||
flex-direction: column; | |||||
align-items: center; | |||||
justify-content: center; | |||||
} | |||||
ul.invisible{ | |||||
display: none; | |||||
} | |||||
ul{ | |||||
position: fixed; | |||||
right:0px; | |||||
top:0px; | |||||
padding-top: 30px; | |||||
list-style-type: none; | |||||
background-color: var(--main-bg-color); | |||||
height: 100vh; | |||||
font-size: 0.75rem; | |||||
} | |||||
div#player-toggler{ | |||||
position: fixed; | |||||
top: 0px; | |||||
right:0px; | |||||
margin-top:2px; | |||||
margin-right: 2px; | |||||
z-index: 10; | |||||
cursor: pointer; | |||||
} | |||||
li{ | |||||
/*background-color: var(--main-bg-color);*/ | |||||
padding: 2px; | |||||
} | |||||
li{ | |||||
margin-top:2px; | |||||
display: flex; | |||||
justify-content: center; | |||||
align-items: center; | |||||
} | |||||
button{ | |||||
background-color: rgba(0,0,0,0); | |||||
border: none; | |||||
margin-left: 5px; | |||||
cursor: pointer; | |||||
} | |||||
div#player-toggler > img{ | |||||
width: 24px; | |||||
height: 24px; | |||||
} | |||||
button img{ | |||||
width: 16px; | |||||
height: 16px; | |||||
} | |||||
progress::-moz-progress-bar { | |||||
background-color: black !important; | |||||
} | |||||
#player-progress{ | |||||
position: fixed; | |||||
left:0; | |||||
top:0; | |||||
height: 1vw; | |||||
width: 100vh; | |||||
background-color: var(--main-bg-color); | |||||
border: none; | |||||
border-top:2px solid var(--main-bg-color); | |||||
border-bottom:2px solid var(--main-bg-color); | |||||
cursor: pointer; | |||||
transform: rotate(90deg); | |||||
transform-origin: top left; | |||||
margin-left: 1vw; | |||||
/* margin-top:calc(50vh - 0.5vw); | |||||
margin-left:0; */ | |||||
} | |||||
#time-info{ | |||||
visibility: hidden; | |||||
position: fixed; | |||||
bottom: 2px; | |||||
left: 1%; | |||||
padding-left: 2px; | |||||
color:white; | |||||
font-size: 0.6rem; | |||||
} |
@@ -1,60 +0,0 @@ | |||||
var current = undefined | |||||
const progressMargin = 50; | |||||
var progress = undefined; | |||||
window.addEventListener('DOMContentLoaded', (event) => { | |||||
progress = document.getElementById('player-progress'); | |||||
document.getElementById('player-progress').addEventListener('click', (e) => { | |||||
if(current){ | |||||
let media = current.getElementsByTagName('audio')[0]; | |||||
media.currentTime = e.layerX * media.duration / progress.offsetWidth; | |||||
} | |||||
}); | |||||
let toggler = document.getElementById('player-toggler'); | |||||
toggler.setAttribute('title','afficher/masquer la liste des morceaux'); | |||||
toggler.addEventListener('click', (e) => { | |||||
document.getElementsByTagName('ul')[0].classList.toggle('invisible'); | |||||
}) | |||||
}); | |||||
function togglePlay(src) { | |||||
let media = src.getElementsByTagName('audio')[0]; | |||||
let icon = src.getElementsByTagName('img')[0]; | |||||
if (current){//stops current media and reset its play icon | |||||
pause(); | |||||
} | |||||
if(current != src){ | |||||
//sets current media icon and plays media | |||||
icon.setAttribute('src','assets/pause.png'); | |||||
media.play(); | |||||
progress.max = Math.floor(media.duration); | |||||
current = src; | |||||
document.getElementById('time-info').style.visibility = 'visible'; | |||||
} | |||||
else{ | |||||
current = undefined; | |||||
} | |||||
} | |||||
function pause(){ | |||||
current.getElementsByTagName('audio')[0].pause(); | |||||
current.getElementsByTagName('img')[0].setAttribute('src','assets/play.png'); | |||||
document.getElementById('time-info').style.visibility = 'hidden'; | |||||
} | |||||
function updateProgress(media){ | |||||
progress.value = Math.floor(media.currentTime); | |||||
document.getElementById('time-info').innerHTML = | |||||
prettyDuration(media.currentTime) + ' / ' + prettyDuration(media.duration); | |||||
} | |||||
function prettyDuration(duration) { | |||||
let sec = Math.floor( duration ); | |||||
let min = Math.floor( sec / 60 ); | |||||
min = min >= 10 ? min : '0' + min; | |||||
sec = Math.floor( sec % 60 ); | |||||
sec = sec >= 10 ? sec : '0' + sec; | |||||
return min + ':' + sec; | |||||
} |
@@ -1,67 +1,33 @@ | |||||
import eyed3 | import eyed3 | ||||
import os | import os | ||||
import sys | import sys | ||||
import shutil | import shutil | ||||
from html_writer import Html | |||||
#TracksDir class definition | |||||
class TracksDir: | |||||
def __init__(self, trackFiles): | |||||
self.trackFiles = trackFiles | |||||
#HTML Output | |||||
def toHTML(self): | |||||
head = Html() | |||||
head.self_close_tag('meta', attributes=dict(charset='utf-8')) | |||||
head.self_close_tag('link', attributes=dict(href='assets/labelize.css',rel='stylesheet')) | |||||
body = Html() | |||||
trackNumber = 0 | |||||
with body.tag('div',classes=['track-list']): | |||||
#body.tag_with_content('Track List', name='h2') | |||||
with body.tag('div',attributes=dict(id='player-toggler')): | |||||
body.self_close_tag('img', attributes=dict(src='assets/labelize.png')) | |||||
with body.tag('ul') as list: | |||||
for t in self.trackFiles: | |||||
trackNumber = trackNumber + 1 | |||||
trackId = 'track-' + str(trackNumber) | |||||
audiofile = eyed3.load("build/" + t) | |||||
with body.tag('li') as li: | |||||
print(audiofile.tag.title) | |||||
li += str(audiofile.tag.title or 'untitled')+ ' - ' | |||||
li += str(audiofile.tag.album or 'untitled')+ ' - ' | |||||
li += audiofile.tag.artist | |||||
with body.tag('button',attributes=dict(onclick="togglePlay(this)")): | |||||
body.self_close_tag('img', attributes=dict(src='assets/play.png')) | |||||
with body.tag('audio', attributes=dict(src=t, id=trackId, | |||||
ontimeupdate="updateProgress(this)")) as audio: | |||||
audio+="Your browser does not support the audio element" | |||||
# with body.tag('canvas',attributes=dict(id='player-progress')) as canvas: | |||||
# canvas += "player's progress bar" | |||||
with body.tag('progress',attributes=dict(id='player-progress',value='0')) as canvas: | |||||
canvas += "player's progress bar" | |||||
with body.tag('div',attributes=dict(id='time-info')) as timeInfo: | |||||
timeInfo += '00:00' | |||||
with body.tag('script', attributes=dict(src='assets/labelize.js')) as script: | |||||
script+=""#script tag is not added without that trick | |||||
return Html.html_template(head, body).to_raw_html(indent_size=2) | |||||
import yaml | |||||
from mako.template import Template | |||||
# TracksDir class definition | |||||
class Album: | |||||
def __init__(self, track_files): | |||||
self.trackFiles = track_files | |||||
# script usage function | # script usage function | ||||
def usage(): | def usage(): | ||||
print('USAGE : labelize.py [inputDirectory] [outputDirectory]') | print('USAGE : labelize.py [inputDirectory] [outputDirectory]') | ||||
# script beginning | # script beginning | ||||
arguments = len(sys.argv) - 1 | arguments = len(sys.argv) - 1 | ||||
if(arguments != 2): | |||||
if arguments != 2: | |||||
usage() | usage() | ||||
sys.exit(2) | sys.exit(2) | ||||
inputDirectory = sys.argv[1] | |||||
outputDirectory = sys.argv[2] | |||||
input_directory = sys.argv[1] | |||||
output_directory = sys.argv[2] | |||||
def copyDirectory(src, dest): | |||||
def copy_directory(src, dest): | |||||
try: | try: | ||||
shutil.copytree(src, dest) | shutil.copytree(src, dest) | ||||
except shutil.Error as e: | except shutil.Error as e: | ||||
@@ -69,23 +35,46 @@ def copyDirectory(src, dest): | |||||
except OSError as e: | except OSError as e: | ||||
print('Directory not copied. Error: %s' % e) | print('Directory not copied. Error: %s' % e) | ||||
#removes existing build directory if exists | |||||
if os.path.isdir(outputDirectory): | |||||
shutil.rmtree(outputDirectory) | |||||
#copies source files in the build directory | |||||
copyDirectory(inputDirectory, 'build') | |||||
# removes existing build directory if exists | |||||
if os.path.isdir(output_directory): | |||||
shutil.rmtree(output_directory) | |||||
# | |||||
# copies source files in the build directory | |||||
copy_directory(input_directory, output_directory + '/audio') | |||||
#copies assets in the build directory | |||||
copyDirectory('assets', outputDirectory + '/assets') | |||||
# copies assets in the build directory | |||||
copy_directory('assets', output_directory + '/assets') | |||||
for root, dirs, files in os.walk(inputDirectory): | |||||
trackFiles = [] | |||||
for f in files: | |||||
with open('labelize.yaml') as f: | |||||
data = yaml.load(f, Loader=yaml.FullLoader) | |||||
title = data['band'] | |||||
cover_img = data['images']['cover'] | |||||
contact_img = data['images']['contact'] | |||||
shutil.copyfile(input_directory + '/' + cover_img, output_directory + '/assets/images/cover.png'); | |||||
shutil.copyfile(input_directory + '/' + contact_img, output_directory + '/assets/images/contact.png'); | |||||
track_files = [] | |||||
for root, dirs, files in os.walk(input_directory): | |||||
for f in sorted(files): | |||||
if f.lower().endswith(('.mp3', '.wav', '.ogg')): | if f.lower().endswith(('.mp3', '.wav', '.ogg')): | ||||
trackFiles.append(f) | |||||
track_files.append(f) | |||||
print(f) | |||||
# td = TracksDir(trackFiles) | |||||
# f = open(output_directory + "/index.html", "w+") | |||||
# f.write(td.to_html()) | |||||
# f.close() | |||||
my_template = Template(filename='template.html') | |||||
f = open(output_directory + "/index.html", "w+") | |||||
# Write template data to the file created | |||||
f.write(my_template.render( | |||||
title=title, | |||||
tracks=track_files, | |||||
albums_section=data['albums_section'])) | |||||
td = TracksDir(trackFiles) | |||||
f = open(outputDirectory + "/index.html","w+") | |||||
f.write(td.toHTML()) | |||||
f.close() | |||||
# Close file | |||||
f.close() |
@@ -0,0 +1,11 @@ | |||||
band: Clou | |||||
images: | |||||
cover: image.png | |||||
contact: image2.png | |||||
albums_section : | |||||
title: CLOU albums | with LABELAR | |||||
albums: | |||||
- year : 2019 | |||||
title : p | |||||
- year : 2018 | |||||
title : x |
@@ -1,4 +1,8 @@ | |||||
eyeD3==0.8.10 | |||||
eyeD3==0.8.12 | |||||
html-writer==1.1.1 | html-writer==1.1.1 | ||||
Mako==1.1.2 | |||||
MarkupSafe==1.1.1 | |||||
pkg-resources==0.0.0 | |||||
python-magic==0.4.15 | python-magic==0.4.15 | ||||
PyYAML==5.3.1 | |||||
six==1.12.0 | six==1.12.0 |
@@ -0,0 +1,51 @@ | |||||
## -*- coding: utf-8 -*- | |||||
<!DOCTYPE html> | |||||
<html lang="fr"> | |||||
<head> | |||||
<meta charset="utf-8"> | |||||
<title>${title}</title> | |||||
<meta name="description" content="dedemo"> | |||||
<meta name="author" content="dede.space"> | |||||
<link rel="stylesheet" href="assets/css/player.css"> | |||||
<link rel="stylesheet" href="assets/css/labelize.css"> | |||||
</head> | |||||
<body> | |||||
<section class="cover"> | |||||
<!-- <img src="images/CLOU_Icono-1.png"/> --> | |||||
</section> | |||||
<!-- <section class="dates">--> | |||||
<!-- <h2><span class="scaps">${title}</span> live</h2>--> | |||||
<!-- </section>--> | |||||
<section class="albums"> | |||||
<h2>${albums_section['title']}</h2> | |||||
<ul> | |||||
% for a in albums_section['albums']: | |||||
<li>${a['year']} : ${a['title']}</li> | |||||
% endfor | |||||
</ul> | |||||
</section> | |||||
<section class="contact"> | |||||
<span>contact<span class="point">@</span>clou<span class="point">.</span>space</span> | |||||
<footer class="flex-center"> | |||||
dede<span class='point'>.</span>space<span class='pipe'>|</span>2019 | |||||
</footer> | |||||
</section> | |||||
<ul id="player" data-title="Album title"> | |||||
% for t in tracks: | |||||
<li>${loop.index}<audio src="audio/01.mp3" id="track-${loop.index}"></audio></li> | |||||
% endfor | |||||
</ul> | |||||
<script type="module" src="./assets/js/labelize.js"></script> | |||||
</body> | |||||
</html> | |||||
<!---nav footered-screen--> |