Anonymous avatar Anonymous committed 6abb260

Imported from svn by Bitbucket

Comments (0)

Files changed (5)

+clementine-webremote
+
+Instructions:
+ - Uncompress it.
+ - Launch with: ./http.py --port 3000
+ - If you get an error, try launching it with: python2 http.py --port 3000
+ - Open in your browser: http://<host>:3000
+
+Requirements:
+ - Python2
+ - python-qt4-dbus 
+ - Clementine
+
+http://code.google.com/p/clementine-webremote/
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#	 This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation, either version 3 of the License, or
+#    (at your option) any later version.
+
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+
+#    You should have received a copy of the GNU General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import dbus
+import dbus.service
+from dbus.mainloop.qt import DBusQtMainLoop
+
+class Clementine:
+  
+  def __init__(self):
+    self.bus = dbus.SessionBus()
+    self.server = self.bus.get_object('org.mpris.clementine', '/Player')
+  
+  def Next(self):
+    self.server.Next()
+    return True
+  
+  def Prev(self):
+    self.server.Prev()
+    return True
+    
+  def Stop(self):
+    self.server.Stop()
+    return True
+    
+  def Pause(self):
+    self.server.Pause()
+    return True
+    
+  def GetInfo(self):
+    return self.server.GetMetadata()
+  
+  def VolumeUp(self):
+    self.server.VolumeUp(10)
+    return True
+    
+  def VolumeDown(self):
+    self.server.VolumeDown(10)
+    return True
+    
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation, either version 3 of the License, or
+#    (at your option) any later version.
+
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+
+#    You should have received a copy of the GNU General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import urlparse
+import getopt
+import sys
+import BaseHTTPServer
+import clementine as Clementine
+import web as Web
+
+class RequestHandler (BaseHTTPServer.BaseHTTPRequestHandler):
+    def do_GET (self):
+        self.clementine = Clementine.Clementine()
+        web = None
+        web = Web.Web(self.clementine.GetInfo())
+        if self.path.endswith("refresh"):
+        
+          self.send_response(200)
+          self.send_header("Content-type", "text/html")
+          self.end_headers()
+          self.wfile.write(web.PrintInfo())
+          return
+              
+        else:
+            if self.path.endswith(".png"):
+                self.show_button()
+            if self.path.endswith(".jpg"):
+              self.show_cover()
+            elif self.path.endswith(".css"):
+              f = open('style.css')
+              self.send_response(200)
+              self.send_header('Content-type', 'text/css')
+              self.end_headers()
+              self.wfile.write(f.read())
+              f.close()
+            else:
+              self.send_response(200)
+              self.send_header("Content-type", "text/html")
+              self.check_function()
+              self.end_headers()
+              self.wfile.write(web.PrintHeader())
+              self.wfile.write(web.PrintInfo())
+              self.wfile.write(web.PrintCover())
+              self.wfile.write(web.PrintControls())
+              self.wfile.write(web.PrintFooter())
+            return
+    
+    def show_button (self):
+        btn = str(self.path)
+        btn = btn.replace('/','',1)
+        f = open(btn, 'r')
+        self.send_response(200)
+        self.send_header('Content-type', 'image/png')
+        self.end_headers()
+        self.wfile.write(f.read())
+
+    def show_cover (self):
+      cover = str(self.clementine.GetInfo()['arturl'])
+      cover = cover.replace('file://','')
+      f = open(cover, 'r')
+      self.send_response(200)
+      self.send_header('Content-type', 'image/jpg')
+      self.end_headers()
+      self.wfile.write(f.read())
+    
+    def check_function (self):
+        path = self.path
+        cmd = None
+        if '?' in path:
+          path, tmp = path.split('?', 1)
+          cmd = urlparse.parse_qs(tmp)
+          if str(cmd['action']) == "['Pause']":
+            self.clementine.Pause()
+          elif str(cmd['action']) == "['Next']":
+            self.clementine.Next()
+          elif str(cmd['action']) == "['Prev']":
+            self.clementine.Prev()
+          elif str(cmd['action']) == "['Stop']":
+            self.clementine.Stop()
+          elif str(cmd['action']) == "['VolumeUp']":
+            self.clementine.VolumeUp()
+          elif str(cmd['action']) == "['VolumeDown']":
+            self.clementine.VolumeDown()
+                   
+    
+def main (argv):
+    port = 3000
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], "hp:d", ["help", "port"])
+    except getopt.GetoptError:
+        usage()
+        sys.exit()
+    for opt, arg in opts:
+        if opt in ("-h", "--help"):
+            usage()
+            sys.exit()
+        elif opt in ("-p", "--port"):
+            try:
+                port = int(arg)
+            except ValueError:
+                print   "Incorrect port, launching at 3000."
+    print "Using port: " + str(port)
+    httpd = BaseHTTPServer.HTTPServer(('', port), RequestHandler)
+    httpd.serve_forever()
+    
+def usage ():
+    print "\
+    Usage: http.py [options]\n\
+    -h, --help                  Display this help and exit.\n\
+    -p <port>, --port <port>    Launch remote listening on the specified port.\n\n\
+    Examples:\n\
+    http.py -p 8080             Launch remote listening the 8080 port"
+
+if __name__ == "__main__":
+    sys.exit(main(sys.argv))
+body {
+	background-color: black;
+	margin: 0px;
+	text-align: center;
+}
+.cover {
+	padding-top: 10px;
+	margin: 0px;
+	width: 80%;
+	
+	max-width: 300px;
+	
+}
+.info {
+	margin: 0px;
+	color: white;
+}
+.artist {
+	font-weight: bold;
+}
+
+.cbutton img {
+	width: 45px;
+}
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation, either version 3 of the License, or
+#    (at your option) any later version.
+
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+
+#    You should have received a copy of the GNU General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import random
+import unicodedata
+
+class Web:
+  def __init__(self, info):
+    self.info = info
+    return
+    
+  def PrintHeader(self):
+    return "\
+    <?xml version='1.0' encoding='UTF-8'?>\
+    <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML Basic 1.1//EN\"\
+    \"http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd\">\
+    <html>\n\
+    <head>\n\
+      <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1'>\n\
+      <link rel='stylesheet' href='style.css' type='text/css' media='screen' />\n\
+      <!--<title>" + self.info['artist'].encode('utf-8') + " - " + self.info['title'].encode('utf-8') + "</title>\n\-->\
+      <title>Clementine Remote Control</title>\n\
+      <script type='text/javascript'>\n\
+			var cur='';\
+			function loadXMLDoc()\n\
+			{ \n\
+			if (window.XMLHttpRequest)\n\
+			  {// code for IE7+, Firefox, Chrome, Opera, Safari \n\
+			  xmlhttp=new XMLHttpRequest();\n\
+			  }\n\
+			else\n\
+			  {// code for IE6, IE5\n\
+			  xmlhttp=new ActiveXObject('Microsoft.XMLHTTP');\n\
+			  }\n\
+			xmlhttp.onreadystatechange=function()\n\
+			  {\n\
+			  if (xmlhttp.readyState==4 && xmlhttp.status==200)\n\
+				{\n\
+				document.getElementById('info').innerHTML=xmlhttp.responseText;\n\
+				if (xmlhttp.responseText!=cur){\n\
+				    cur=xmlhttp.responseText;\
+				    document.getElementById('cover').src=Math.random()+'.jpg'; \
+				}\
+				}\n\
+			  }\n\
+			xmlhttp.open('GET','refresh',true);\n\
+			xmlhttp.send();\n\
+			setTimeout('loadXMLDoc()',1000);\n\
+			}\n\
+		 </script>\n\
+		 </head>\n<body onload='loadXMLDoc()'>"
+  
+  def PrintCover(self):
+    cover = str(self.info['arturl'])
+    cover = cover.replace('file://','')
+    return "\
+    <img class='cover' src='" + str(random.random()) + ".jpg' alt='" + self.info['album'].encode('utf-8') + "'id='cover' />"
+    
+  def PrintInfo(self):
+    
+    if not(self.info.has_key('album')):
+        self.info['album']="unknown album"
+    if not(self.info.has_key('title')):
+        self.info['title']="unknown title"
+    if not(self.info.has_key('artist')):
+        self.info['artist']="unknown artist"
+
+    title = self.info['title'].encode('utf-8')
+    return "\
+    <div class='info' id='info'>\n\
+      <span class='artist'>" + self.info['artist'].encode('utf-8') + "</span><br />\
+      " + self.info['album'].encode('utf-8') + "<br />\
+      " + title + "<br />\
+    </div>\n"
+    
+  def PrintControls(self):
+    return "\
+    <div class='info'>\n\
+        <a class='cbutton' href='?action=Prev'><img src='images/prev.png' alt='Previous' /></a>\
+        <a class='cbutton' href='?action=Pause'><img src='images/pause.png' alt='Pause' /></a>\
+        <a class='cbutton' href='?action=Stop'><img src='images/stop.png' alt='Stop' /></a>\
+        <a class='cbutton' href='?action=Next'><img src='images/next.png' alt='Next' /></a>\
+        <a class='cbutton' href='?action=VolumeDown'><img src='images/down.png' alt='VolumeDown' /></a>\
+        <a class='cbutton' href='?action=VolumeUp'><img src='images/up.png' alt='VolumeUp' /></a>\
+        </div>\n"
+    
+  def PrintFooter(self):
+    return "\
+    </body>\n\
+</html>\n"
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.