summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xapp.py59
-rw-r--r--directory.py33
-rw-r--r--static/index.html17
-rw-r--r--static/player.js36
4 files changed, 82 insertions, 63 deletions
diff --git a/app.py b/app.py
index 9120ea4..f288646 100755
--- a/app.py
+++ b/app.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python2
-import os, mimetypes, json, cgi, recode, time, urllib, events, threading
+import os, mimetypes, json, cgi, recode, time, urllib, events
from config import config
from directory import Directory, File
@@ -11,26 +11,22 @@ class Application(object):
def files(self, environ, start_response, path):
full_path = os.path.join(config.get('music_root'), *path[1:])
+
+ if not os.path.exists(full_path) or '..' in path:
+ start_response('404 Not Found', [])
+ return []
+
rel_path = os.path.join(*path[1:] or '.')
if os.path.isdir(full_path):
start_response('200 OK', [('Content-Type', 'text/html; charset=UTF-8')])
return (str(x) for x in Directory(rel_path).listdir())
else:
- args = cgi.FieldStorage(environ = environ)
-
- decoder = args.getvalue('decoder') if 'decoder' in args else None
- encoder = args.getvalue('encoder') if 'encoder' in args else None
-
- if decoder and encoder:
- cache_file = File(rel_path).get_cache_file()
- return File(cache_file, True).send(environ, start_response)
- else:
- return File(rel_path).send(environ, start_response)
+ return File(rel_path).send(environ, start_response)
def static(self, environ, start_response, path):
filename = os.path.join('static', *path[1:])
- if not os.access(filename, os.F_OK) or '..' in path:
+ if not os.path.exists(filename) or '..' in path:
start_response('404 Not Found', [])
return []
@@ -38,6 +34,16 @@ class Application(object):
start_response('200 OK', [('Content-Type', mime)])
return open(filename, 'rb')
+ def cache(self, environ, start_response, path):
+ path = os.path.join(*path[1:])
+ cache_path = File(path).get_cache_path()
+
+ if not os.path.exists(cache_path) or '..' in path:
+ start_response('404 Not Found', [])
+ return []
+
+ f = File(cache_path, True)
+ return f.send(environ, start_response)
# JSON handlers
@@ -52,15 +58,34 @@ class Application(object):
s = json.dumps([x.json() for x in contents])
return s
- def json_cache(self, environ, start_response, path):
+ def json_recode(self, environ, start_response, path):
args = cgi.FieldStorage(environ = environ)
path = args.getvalue('path') if 'path' in args else None
decoder = args.getvalue('decoder') if 'decoder' in args else None
encoder = args.getvalue('encoder') if 'encoder' in args else None
f = File(path)
- t = threading.Thread(target = f.recode, args = (decoder, encoder, environ['sessionid']))
- t.start()
+ f.start_recode(decoder, encoder, environ['sessionid'])
+
+ start_response('200 OK', [('Content-Type', 'text/plain')])
+ return []
+
+ def json_play(self, environ, start_response, path):
+ args = cgi.FieldStorage(environ = environ)
+
+ path = args.getvalue('path')
+
+ f = File(path)
+ # TODO: replace this with some sane logic
+ if not os.path.splitext(path)[1] in ('.mp3', '.ogg'):
+ cache_path = f.get_cache_path()
+ decoder, encoder = ('ffmpeg',)*2
+ if not os.path.exists(cache_path):
+ f.start_recode(decoder, encoder, environ['sessionid'])
+ else:
+ events.event_pub.play(environ['sessionid'], '/cache/{0}'.format(path))
+ else:
+ events.event_pub.play(environ['sessionid'], '/files/{0}'.format(path))
start_response('200 OK', [('Content-Type', 'text/plain')])
return []
@@ -68,8 +93,10 @@ class Application(object):
handlers = {
'files': files,
'static': static,
+ 'cache': cache,
'list': json_list,
- 'cache': json_cache,
+ 'recode': json_recode,
+ 'play': json_play,
'events': events.EventSubscriber,
}
diff --git a/directory.py b/directory.py
index 33391c6..48dfaa9 100644
--- a/directory.py
+++ b/directory.py
@@ -1,4 +1,4 @@
-import os, mimetypes, recode, events
+import os, mimetypes, recode, events, threading
from config import config
@@ -84,32 +84,39 @@ class File(DirectoryEntry):
('Content-Length', str(size))])
return open(self.abs_path, 'rb')
+ def get_cache_path(self):
+ cache_path = os.path.join(config.get('cache_dir'), self.path)
+ cache_path = os.path.splitext(cache_path)[0] + '.mp3'
+ return cache_path
+
def get_cache_file(self):
- cache_file = os.path.join(config.get('cache_dir'), self.path)
- cache_file = os.path.splitext(cache_file)[0] + '.mp3'
- return cache_file
+ return File(self.get_cache_path(), True)
def recode(self, decoder, encoder, sessionid = None):
decoder = recode.decoders[decoder]()
encoder = recode.encoders[encoder]()
recoder = recode.Recoder(decoder, encoder)
- cache_file = self.get_cache_file()
- cache_file_dir = os.path.dirname(cache_file)
+ cache_path = self.get_cache_path()
+ cache_path_dir = os.path.dirname(cache_path)
# check and create cache directory
- if not os.path.exists(cache_file_dir):
- os.mkdir(cache_file_dir)
+ if not os.path.exists(cache_path_dir):
+ os.mkdir(cache_path_dir)
# check if file is cached
- if not os.path.exists(cache_file):
+ if not os.path.exists(cache_path):
events.event_pub.recoding(self.path)
- recoder.recode(self.abs_path, cache_file)
+ recoder.recode(self.abs_path, cache_path)
events.event_pub.cached(self.path)
if sessionid:
- events.event_pub.play(sessionid, '/files/{0}'.format(self.path))
+ events.event_pub.play(sessionid, '/cache/{0}'.format(self.path))
+
+ def start_recode(self, decoder, encoder, sessionid = None):
+ t = threading.Thread(target = self.recode, args = (decoder, encoder, sessionid))
+ t.start()
def json(self):
- cache_file = self.get_cache_file()
+ cache_path = self.get_cache_path()
d = DirectoryEntry.json(self)
- d.update({'cached': os.path.exists(cache_file)})
+ d.update({'cached': os.path.exists(cache_path)})
return d
diff --git a/static/index.html b/static/index.html
index ea20792..15384aa 100644
--- a/static/index.html
+++ b/static/index.html
@@ -7,19 +7,12 @@
<link rel="stylesheet" href="/static/style.css" type="text/css" />
</head>
<body>
- <div id="transcode-div">
- <label for="trans_enabled"><input type="checkbox" id="trans_enabled" /> Transcode</label>
- from
- <select id="trans_from">
- <option value="ffmpeg">FFmpeg</option>
- </select>
- to
- <select id="trans_to">
- <option value="ffmpeg">FFmpeg</option>
- </select>
- </div>
<textarea id="logbox" readonly="readonly" rows="10" cols="50"></textarea>
- <div><input type="button" value="Close event source" onclick="source.close()" /></div>
+ <div>
+ <input type="button" value="Close event source" onclick="source.close()" />
+ <input type="button" value="Open event source" onclick="event_open()" />
+ <input type="button" value="Refresh directory" onclick="list(document.getElementById('current-dir').innerHTML.split(': ', 2)[1])" />
+ </div>
<div id="current-dir"></div>
<ul id="song-links"></ul>
<div id="audio-src-url">none</div>
diff --git a/static/player.js b/static/player.js
index ce75249..c0cf6ff 100644
--- a/static/player.js
+++ b/static/player.js
@@ -19,19 +19,14 @@ function MusicListing(type, path, name, cached) {
this.a.tag = path;
this.play = function() {
- var transcode = document.getElementById('trans_enabled').checked;
- var trans_from = document.getElementById('trans_from').value;
- var trans_to = document.getElementById('trans_to').value;
- var p = path;
- if(transcode)
- p += '?decoder=' + trans_from + '&encoder=' + trans_to;
- log('playing ' + p);
- change_url('/files/' + p);
- audio.play();
+ log('playing ' + path);
+ xmlhttp = new XMLHttpRequest();
+ xmlhttp.open('GET', '/play?path=' + encodeURIComponent(path));
+ xmlhttp.send(null);
}
- this.cache = function() {
- var path = '/cache?path=' + encodeURIComponent(this.path) +
+ this.recode = function() {
+ var path = '/recode?path=' + encodeURIComponent(this.path) +
'&decoder=' + document.getElementById('trans_from').value +
'&encoder=' + document.getElementById('trans_to').value;
var a = this.a;
@@ -56,16 +51,7 @@ function MusicListing(type, path, name, cached) {
if(type == 'dir') {
list(path);
} else if(type == 'file') {
- var transcode = document.getElementById('trans_enabled').checked;
- var trans_from = document.getElementById('trans_from').value;
- var trans_to = document.getElementById('trans_to').value;
-
- var p = path;
- if(transcode) {
- ml.cache(p);
- } else {
- ml.play();
- }
+ ml.play();
}
return false;
}
@@ -163,12 +149,18 @@ function event_handler(event) {
}
}
-window.onload = function() {
+function event_open() {
+ if(source)
+ source.close();
source = new EventSource('/events');
source.onopen = function() { log('event source opened'); }
source.onmessage = event_handler;
source.onerror = function(event) { log('event source error'); }
log('event source status: ' + source.readyState);
+}
+
+window.onload = function() {
+ event_open();
audio = new Audio();
list('/');