| 1 | #!/usr/bin/python |
| 2 | |
| 3 | # Trivial xbmc file upload script for parties |
| 4 | # Copyright (c) 2014 Clinton Ebadi <clinton@unknownlamer.org> |
| 5 | # This program is free software: you can redistribute it and/or modify |
| 6 | # it under the terms of the GNU General Public License as published by |
| 7 | # the Free Software Foundation, either version 3 of the License, or |
| 8 | # (at your option) any later version. |
| 9 | |
| 10 | # This program is distributed in the hope that it will be useful, |
| 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | # GNU General Public License for more details. |
| 14 | |
| 15 | # You should have received a copy of the GNU General Public License |
| 16 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | |
| 18 | # todo: |
| 19 | # fix weird characters (see erica's song) |
| 20 | # use shutil.copyfileobj to possibly speed up copying |
| 21 | # - check if it actually causes chunked reads from the browser |
| 22 | # support multiple files |
| 23 | # - daemonize replaygain? |
| 24 | # track uploads |
| 25 | # - phone ip is hopefully good enough |
| 26 | # - track # of uses of asap/Next Please |
| 27 | # - track files we have queued (need at least next-please so we can queue those in order) |
| 28 | # integrate better with native queue |
| 29 | |
| 30 | |
| 31 | ## crazy idea: if the playlist can be watched with a script... (maybe |
| 32 | ## a json rpc notification? but ... reliability, and upload.cgi runs |
| 33 | ## infrequently enough that it cannot record the playlist and extract |
| 34 | ## a meaningful image of the queue ...). |
| 35 | |
| 36 | # diff playlist whenever item is inserted (or song changes, or whatever we can hook on). |
| 37 | # scan for common items (discarding the head of the old snapshot, since we could just be advancing) |
| 38 | # when the first different item is found... if it ain't the end of the list it's been queued |
| 39 | # keep going until we match up again and record the end of the queue position in a file |
| 40 | # what about when we delete in the list? |
| 41 | # |
| 42 | |
| 43 | # upload.html |
| 44 | # - show playlist length, # of next/asap available, likely queue position |
| 45 | # - show upcoming songs (5? just next-please?) |
| 46 | # - - just use SSI + python virtual includes, seriously |
| 47 | |
| 48 | import cgi, cgitb |
| 49 | import os, sys |
| 50 | import daemon |
| 51 | import subprocess |
| 52 | import random |
| 53 | from xbmcjson import XBMC |
| 54 | |
| 55 | cgitb.enable() |
| 56 | |
| 57 | print "content-type: text/html\n\n" |
| 58 | |
| 59 | music_dir = "/srv/archive/incoming/stolen-moosic" |
| 60 | form = cgi.FieldStorage () |
| 61 | |
| 62 | # Evil: just run replaygain/mp3gain/metaflac on the file and hope one |
| 63 | # works instead of dealing with MIME. For now. |
| 64 | def attempt_rpgain (file_name): |
| 65 | subprocess.call (["/usr/bin/vorbisgain", "-q", file_name]) |
| 66 | subprocess.call (["/usr/bin/mp3gain", "-q", "-s", "i", file_name]) |
| 67 | subprocess.call (["/usr/bin/metaflac", "--add-replay-gain", file_name]) |
| 68 | |
| 69 | def save_uploaded_file (form_field, upload_dir): |
| 70 | if form_field not in form: |
| 71 | print "<p>No file provided.</p>" |
| 72 | sys.exit () |
| 73 | fileitem = form[form_field] |
| 74 | fout = file (os.path.join(upload_dir, fileitem.filename), 'wb') |
| 75 | fout.write (fileitem.value) |
| 76 | fout.close() |
| 77 | return fileitem.filename |
| 78 | |
| 79 | song_name = save_uploaded_file ("song", music_dir) |
| 80 | |
| 81 | print '<p><a href="upload.html">Upload another song</a></p>' |
| 82 | sys.stdout.flush () |
| 83 | |
| 84 | #with daemon.DaemonContext (): |
| 85 | attempt_rpgain ("{0}/{1}".format (music_dir, song_name)) |
| 86 | |
| 87 | xbmc = XBMC ("http://localhost:8080/jsonrpc") |
| 88 | |
| 89 | # todo: use REMOTE_ADDR to limit how many asap requests a person can |
| 90 | # make in a time period |
| 91 | totalitems = xbmc.Playlist.GetItems (playlistid=0)['result']['limits']['total'] |
| 92 | playpos = random.randint (1, totalitems / (1 if 'asap' not in form else 3)) |
| 93 | |
| 94 | print xbmc.Playlist.Insert (playlistid=0, item={"file": "{0}/{1}".format (music_dir, song_name)}, position=playpos) |
| 95 | |
| 96 | print '<p style="font-size: x-large">Your song is number {0} in the queue ({1} songs in playlist).</p>'.format (playpos, totalitems+1) |
| 97 | |
| 98 | |