Separate Playlist
This commit is contained in:
parent
a9c71ac940
commit
31963968cc
7 changed files with 184 additions and 128 deletions
19
webserver.py
19
webserver.py
|
@ -143,8 +143,23 @@ class AnimationHandler(tornado.web.RequestHandler):
|
||||||
self.set_header("Content-Type", "application/json")
|
self.set_header("Content-Type", "application/json")
|
||||||
# filename = self.get_argument("file", None)
|
# filename = self.get_argument("file", None)
|
||||||
if filename == '':
|
if filename == '':
|
||||||
names = sorted([f"/files/{name[:-16]}" for name in os.listdir(self.config.storage) if name.endswith('json_appendable')])
|
files = []
|
||||||
self.write(json.dumps(names))
|
names = [name for name in os.listdir(self.config.storage) if name.endswith('json_appendable')]
|
||||||
|
for name in names:
|
||||||
|
with open(os.path.join(self.config.storage, name), 'r') as fp:
|
||||||
|
first_line = fp.readline().strip()
|
||||||
|
if first_line.endswith(','):
|
||||||
|
first_line = first_line[:-1]
|
||||||
|
print(first_line)
|
||||||
|
metadata = json.loads(first_line)
|
||||||
|
files.append({
|
||||||
|
'name': f"/files/{name[:-16]}",
|
||||||
|
"time": metadata[0],
|
||||||
|
"dimensions": [metadata[1], metadata[2]],
|
||||||
|
})
|
||||||
|
|
||||||
|
files.sort(key=lambda k: k['time'])
|
||||||
|
self.write(json.dumps(files))
|
||||||
else:
|
else:
|
||||||
path = os.path.join(self.config.storage,os.path.basename(filename)+".json_appendable")
|
path = os.path.join(self.config.storage,os.path.basename(filename)+".json_appendable")
|
||||||
drawing = {
|
drawing = {
|
||||||
|
|
|
@ -71,29 +71,7 @@
|
||||||
background: rgba(255, 255, 255, 0.7);
|
background: rgba(255, 255, 255, 0.7);
|
||||||
}
|
}
|
||||||
|
|
||||||
html,
|
|
||||||
body {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
margin: 0;
|
|
||||||
font-family: sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
.playlist {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
z-index: 50;
|
|
||||||
}
|
|
||||||
|
|
||||||
.playlist li {
|
|
||||||
cursor: pointer;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.playlist li:hover {
|
|
||||||
color: blue;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type='range'] {
|
input[type='range'] {
|
||||||
/* position: absolute;
|
/* position: absolute;
|
||||||
|
@ -151,7 +129,8 @@
|
||||||
transition: width .3s;
|
transition: width .3s;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
border: none;
|
border: none;
|
||||||
direction: rtl; /* hide behind bar, instead into nothing */
|
direction: rtl;
|
||||||
|
/* hide behind bar, instead into nothing */
|
||||||
}
|
}
|
||||||
|
|
||||||
.selected-annotation .tags li.annotation-rm {
|
.selected-annotation .tags li.annotation-rm {
|
||||||
|
@ -230,6 +209,7 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<link rel="stylesheet" href="assets/nouislider-15.5.0.css">
|
<link rel="stylesheet" href="assets/nouislider-15.5.0.css">
|
||||||
|
<link rel="stylesheet" href="core.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -238,12 +218,17 @@
|
||||||
<script src="assets/nouislider-15.5.0.js"></script>
|
<script src="assets/nouislider-15.5.0.js"></script>
|
||||||
<script src="assets/wNumb-1.2.0.min.js"></script>
|
<script src="assets/wNumb-1.2.0.min.js"></script>
|
||||||
<script src="annotate.js"></script>
|
<script src="annotate.js"></script>
|
||||||
|
<script src="playlist.js"></script>
|
||||||
<script type='text/javascript'>
|
<script type='text/javascript'>
|
||||||
const player = new Annotator(
|
if (location.search) {
|
||||||
document.getElementById("interface"),
|
const player = new Annotator(
|
||||||
["test", "another", "google"]
|
document.getElementById("interface"),
|
||||||
);
|
["test", "another", "google"],
|
||||||
player.playlist('/files/');
|
location.search.substring(1)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
const playlist = new Playlist(document.getElementById("interface"), '/files/');
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,7 @@ class StrokeSlice {
|
||||||
}
|
}
|
||||||
|
|
||||||
class Annotator {
|
class Annotator {
|
||||||
constructor(wrapperEl, tags) {
|
constructor(wrapperEl, tags, fileurl) {
|
||||||
this.wrapperEl = wrapperEl;
|
this.wrapperEl = wrapperEl;
|
||||||
this.svgEl = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
this.svgEl = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
||||||
this.wrapperEl.appendChild(this.svgEl);
|
this.wrapperEl.appendChild(this.svgEl);
|
||||||
|
@ -184,7 +184,9 @@ class Annotator {
|
||||||
this.strokeGroups[group] = new StrokeGroup(groupEl, this);
|
this.strokeGroups[group] = new StrokeGroup(groupEl, this);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.annotations = []
|
this.annotations = [];
|
||||||
|
|
||||||
|
this.play(fileurl);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateAnnotations(save) {
|
updateAnnotations(save) {
|
||||||
|
@ -263,41 +265,6 @@ class Annotator {
|
||||||
this.updateAnnotations(false); // selects the right tag & highlights the annotation
|
this.updateAnnotations(false); // selects the right tag & highlights the annotation
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: to separate class which then instantiates a player for the given file
|
|
||||||
playlist(url) {
|
|
||||||
const request = new Request(url, {
|
|
||||||
method: 'GET',
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
fetch(request)
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
let playlist = this.wrapperEl.querySelector('.playlist');
|
|
||||||
if (!playlist) {
|
|
||||||
playlist = document.createElement('nav');
|
|
||||||
playlist.classList.add('playlist');
|
|
||||||
this.wrapperEl.appendChild(playlist)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
playlist.innerHTML = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
const listEl = document.createElement("ul");
|
|
||||||
for (let fileUrl of data) {
|
|
||||||
const liEl = document.createElement("li");
|
|
||||||
liEl.innerText = fileUrl
|
|
||||||
liEl.addEventListener('click', (e) => {
|
|
||||||
this.play(fileUrl);
|
|
||||||
playlist.style.display = "none";
|
|
||||||
});
|
|
||||||
listEl.appendChild(liEl);
|
|
||||||
}
|
|
||||||
playlist.appendChild(listEl);
|
|
||||||
// do something with the data sent in the request
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
play(file) {
|
play(file) {
|
||||||
const request = new Request(file, {
|
const request = new Request(file, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
|
@ -491,11 +458,11 @@ class Annotator {
|
||||||
this.updateAnnotations(false);
|
this.updateAnnotations(false);
|
||||||
|
|
||||||
this.setupAudioConfig();
|
this.setupAudioConfig();
|
||||||
|
|
||||||
// this.playStrokePosition(0, 1);
|
// this.playStrokePosition(0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
setupAudioConfig(){
|
setupAudioConfig() {
|
||||||
// audio config
|
// audio config
|
||||||
let audioConfigEl = document.createElement('div');
|
let audioConfigEl = document.createElement('div');
|
||||||
audioConfigEl.classList.add('audioconfig')
|
audioConfigEl.classList.add('audioconfig')
|
||||||
|
@ -532,7 +499,7 @@ class Annotator {
|
||||||
|
|
||||||
|
|
||||||
this.audioEl = document.createElement('audio');
|
this.audioEl = document.createElement('audio');
|
||||||
if(this.audioFile) {
|
if (this.audioFile) {
|
||||||
this.audioEl.setAttribute('src', this.audioFile);
|
this.audioEl.setAttribute('src', this.audioFile);
|
||||||
}
|
}
|
||||||
this.audioEl.addEventListener('canplaythrough', (ev) => {
|
this.audioEl.addEventListener('canplaythrough', (ev) => {
|
||||||
|
|
57
www/core.css
Normal file
57
www/core.css
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
z-index: 50;
|
||||||
|
/* font-size: 15px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist::before {
|
||||||
|
content: 'files';
|
||||||
|
padding: 20px;
|
||||||
|
margin: 20px;
|
||||||
|
font-size: 300%;
|
||||||
|
/* display: list-item?; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist li {
|
||||||
|
/* cursor: pointer; */
|
||||||
|
list-style: none;
|
||||||
|
;
|
||||||
|
line-height: 1.5;
|
||||||
|
/* margin: 20px; */
|
||||||
|
border-bottom: solid darkgray 1px;
|
||||||
|
padding: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist li a:hover {
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist .links {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist li .name {
|
||||||
|
padding-left: 20px
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist .links::before {
|
||||||
|
content: '[';
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist .links::after {
|
||||||
|
content: ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist .links a {
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
|
@ -62,37 +62,27 @@
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.playlist {
|
|
||||||
|
input[type='range'] {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
z-index: 100;
|
||||||
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
right: 0;
|
||||||
z-index: 50;
|
width: 90%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.playlist li{
|
.scrubber {
|
||||||
cursor: pointer;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
.playlist li:hover{
|
|
||||||
color: blue;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type='range']{
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left:0;
|
left: 0;
|
||||||
right: 0;width: 90%;
|
right: 0;
|
||||||
}
|
width: 90%;
|
||||||
.scrubber{
|
|
||||||
position: absolute;
|
|
||||||
z-index: 100;
|
|
||||||
bottom: 0;
|
|
||||||
left:0;
|
|
||||||
right: 0;width: 90%;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<link rel="stylesheet" href="assets/nouislider-15.5.0.css">
|
<link rel="stylesheet" href="assets/nouislider-15.5.0.css">
|
||||||
|
<link rel="stylesheet" href="core.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -100,9 +90,16 @@
|
||||||
</div>
|
</div>
|
||||||
<script src="assets/nouislider-15.5.0.js"></script>
|
<script src="assets/nouislider-15.5.0.js"></script>
|
||||||
<script src="play.js"></script>
|
<script src="play.js"></script>
|
||||||
|
<script src="playlist.js"></script>
|
||||||
<script type='text/javascript'>
|
<script type='text/javascript'>
|
||||||
const player = new Player(document.getElementById("interface"));
|
if (location.search) {
|
||||||
player.playlist('/files/');
|
const player = new Player(
|
||||||
|
document.getElementById("interface"),
|
||||||
|
location.search.substring(1)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
const playlist = new Playlist(document.getElementById("interface"), '/files/');
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|
36
www/play.js
36
www/play.js
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
class Player {
|
class Player {
|
||||||
constructor(wrapperEl) {
|
constructor(wrapperEl, fileurl) {
|
||||||
this.wrapperEl = wrapperEl;
|
this.wrapperEl = wrapperEl;
|
||||||
this.svgEl = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
this.svgEl = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
||||||
this.wrapperEl.appendChild(this.svgEl);
|
this.wrapperEl.appendChild(this.svgEl);
|
||||||
|
@ -23,40 +23,8 @@ class Player {
|
||||||
this.outPointPosition = null;
|
this.outPointPosition = null;
|
||||||
this.currentTime = 0;
|
this.currentTime = 0;
|
||||||
this.isPlaying = false;
|
this.isPlaying = false;
|
||||||
}
|
|
||||||
|
|
||||||
playlist(url) {
|
this.play(fileurl);
|
||||||
const request = new Request(url, {
|
|
||||||
method: 'GET',
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
fetch(request)
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
let playlist = this.wrapperEl.querySelector('.playlist');
|
|
||||||
if (!playlist) {
|
|
||||||
playlist = document.createElement('nav');
|
|
||||||
playlist.classList.add('playlist');
|
|
||||||
this.wrapperEl.appendChild(playlist)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
playlist.innerHTML = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
const listEl = document.createElement("ul");
|
|
||||||
for (let fileUrl of data) {
|
|
||||||
const liEl = document.createElement("li");
|
|
||||||
liEl.innerText = fileUrl
|
|
||||||
liEl.addEventListener('click', (e) => {
|
|
||||||
this.play(fileUrl);
|
|
||||||
playlist.style.display = "none";
|
|
||||||
});
|
|
||||||
listEl.appendChild(liEl);
|
|
||||||
}
|
|
||||||
playlist.appendChild(listEl);
|
|
||||||
// do something with the data sent in the request
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
play(file) {
|
play(file) {
|
||||||
|
|
67
www/playlist.js
Normal file
67
www/playlist.js
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
class Playlist {
|
||||||
|
constructor(wrapperEl, url) {
|
||||||
|
this.wrapperEl = wrapperEl;
|
||||||
|
|
||||||
|
const request = new Request(url, {
|
||||||
|
method: 'GET',
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch(request)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
let playlist = this.wrapperEl.querySelector('.playlist');
|
||||||
|
if (!playlist) {
|
||||||
|
playlist = document.createElement('nav');
|
||||||
|
playlist.classList.add('playlist');
|
||||||
|
this.wrapperEl.appendChild(playlist)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
playlist.innerHTML = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const listEl = document.createElement("ul");
|
||||||
|
for (let file of data) {
|
||||||
|
const liEl = document.createElement("li");
|
||||||
|
|
||||||
|
const dateEl = document.createElement("span");
|
||||||
|
dateEl.classList.add('date');
|
||||||
|
dateEl.innerText = file.time;
|
||||||
|
liEl.append(dateEl);
|
||||||
|
|
||||||
|
const nameEl = document.createElement("span");
|
||||||
|
nameEl.classList.add('name');
|
||||||
|
nameEl.innerText = file.name;
|
||||||
|
liEl.append(nameEl);
|
||||||
|
|
||||||
|
const linksEl = document.createElement("span");
|
||||||
|
linksEl.classList.add('links');
|
||||||
|
liEl.append(linksEl);
|
||||||
|
|
||||||
|
const playEl = document.createElement("a");
|
||||||
|
playEl.classList.add('play');
|
||||||
|
playEl.innerText = "Play";
|
||||||
|
playEl.href = location;
|
||||||
|
playEl.pathname = "play.html";
|
||||||
|
playEl.search = "?"+file.name;
|
||||||
|
linksEl.append(playEl);
|
||||||
|
|
||||||
|
const annotateEl = document.createElement("a");
|
||||||
|
annotateEl.classList.add('annotate');
|
||||||
|
annotateEl.innerText = "Annotate";
|
||||||
|
annotateEl.href = location;
|
||||||
|
annotateEl.pathname = "annotate.html";
|
||||||
|
annotateEl.search = "?"+file.name;
|
||||||
|
linksEl.append(annotateEl);
|
||||||
|
|
||||||
|
// liEl.addEventListener('click', (e) => {
|
||||||
|
// this.play(fileUrl);
|
||||||
|
// playlist.style.display = "none";
|
||||||
|
// });
|
||||||
|
listEl.appendChild(liEl);
|
||||||
|
}
|
||||||
|
playlist.appendChild(listEl);
|
||||||
|
// do something with the data sent in the request
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue