summaryrefslogtreecommitdiff
path: root/app.py
diff options
context:
space:
mode:
Diffstat (limited to 'app.py')
-rwxr-xr-xapp.py112
1 files changed, 112 insertions, 0 deletions
diff --git a/app.py b/app.py
new file mode 100755
index 0000000..1da175f
--- /dev/null
+++ b/app.py
@@ -0,0 +1,112 @@
+#!/usr/bin/env python2
+
+import os, mimetypes, json, cgi, recode, time, urllib, events, threading
+
+from config import config
+from directory import Directory, File
+
+class Application(object):
+ # Application handlers
+
+ def files(self, environ, start_response, path):
+ full_path = os.path.join(config.get('music_root'), *path[1:])
+ 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)
+
+ 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:
+ start_response('404 Not Found', [])
+ return []
+
+ mime = mimetypes.guess_type(filename, strict = False)[0] or 'application/octet-stream'
+ start_response('200 OK', [('Content-Type', mime)])
+ return open(filename, 'rb')
+
+
+ # JSON handlers
+
+ def json_list(self, environ, start_response, path):
+ args = cgi.FieldStorage(environ = environ)
+ directory = args.getvalue('directory') if 'directory' in args else '/'
+ d = Directory(directory)
+
+ contents = d.listdir()
+
+ start_response('200 OK', [('Content-Type', 'text/plain')])
+ s = json.dumps([x.json() for x in contents])
+ return s
+
+ def json_cache(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))
+ t.start()
+
+ start_response('200 OK', [('Content-Type', 'text/plain')])
+ return []
+
+ def json_is_cached(self, environ, start_response, path):
+ args = cgi.FieldStorage(environ = environ)
+ path = args.getvalue('path') if 'path' in args else None
+
+ cache_file = os.path.join(config.get('cache_dir'), path)
+ cache_file = os.path.splitext(cache_file)[0] + '.mp3'
+
+ start_response('200 OK', [('Content-Type', 'text/plain')])
+ return json.dumps(os.path.exists(cache_file))
+
+ handlers = {
+ 'files': files,
+ 'static': static,
+ 'list': json_list,
+ 'cache': json_cache,
+ 'is_cached': json_is_cached,
+ 'events': events.EventSubscriber,
+ }
+
+ # WSGI handler
+
+ def __call__(self, environ, start_response):
+ path = urllib.unquote(environ['PATH_INFO'])
+ path = path.split('/')[1:]
+ module = path[0] or None
+ if not module:
+ module = 'static'
+ path = ['static', 'index.html']
+
+ if module in self.handlers:
+ return self.handlers[module](self, environ, start_response, path)
+
+ start_response('404 Not Found', [('Content-Type', 'text/plain')])
+ return [str(path)]
+
+if __name__ == '__main__':
+ import sys
+ if len(sys.argv) == 3:
+ from flup.server.fcgi import WSGIServer
+ WSGIServer(Application(), bindAddress = (sys.argv[1], int(sys.argv[2]))).run()
+ else:
+ from wsgiref.simple_server import make_server, WSGIServer
+ # enable IPv6
+ WSGIServer.address_family |= 10
+ httpd = make_server('', 8000, Application())
+ httpd.serve_forever()