From deec840c0d9bb017ffb167f3ebd3348bf095fe75 Mon Sep 17 00:00:00 2001 From: Clinton Ebadi Date: Sun, 23 Nov 2014 22:15:25 -0500 Subject: [PATCH 1/1] xbmc file upload / playlist insert example XBMC party mode is good for background music at parties, but sometimes guests want to listen to their music and not mine. After trying to get UPnP/DLNA and bluetooth streaming to work I gave up and threw together a trivial file upload + python script. Primitive, so far. It lets users upload a single file to a specified directory, replaygains it (if it is mp3/flac/vorbis at least), and then inserts it at a random position on the playlist. --- xbmc/upload.html | 18 +++++++++ xbmc/upload.py.cgi | 98 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 xbmc/upload.html create mode 100755 xbmc/upload.py.cgi diff --git a/xbmc/upload.html b/xbmc/upload.html new file mode 100644 index 0000000..3f7eae0 --- /dev/null +++ b/xbmc/upload.html @@ -0,0 +1,18 @@ + + + + + +
+

+ /> + + + +

+
+ + diff --git a/xbmc/upload.py.cgi b/xbmc/upload.py.cgi new file mode 100755 index 0000000..a5d8682 --- /dev/null +++ b/xbmc/upload.py.cgi @@ -0,0 +1,98 @@ +#!/usr/bin/python + +# Trivial xbmc file upload script for parties +# Copyright (c) 2014 Clinton Ebadi +# 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 . + +# todo: +# fix weird characters (see erica's song) +# use shutil.copyfileobj to possibly speed up copying +# - check if it actually causes chunked reads from the browser +# support multiple files +# - daemonize replaygain? +# track uploads +# - phone ip is hopefully good enough +# - track # of uses of asap/Next Please +# - track files we have queued (need at least next-please so we can queue those in order) +# integrate better with native queue + + +## crazy idea: if the playlist can be watched with a script... (maybe +## a json rpc notification? but ... reliability, and upload.cgi runs +## infrequently enough that it cannot record the playlist and extract +## a meaningful image of the queue ...). + +# diff playlist whenever item is inserted (or song changes, or whatever we can hook on). +# scan for common items (discarding the head of the old snapshot, since we could just be advancing) +# when the first different item is found... if it ain't the end of the list it's been queued +# keep going until we match up again and record the end of the queue position in a file +# what about when we delete in the list? +# + +# upload.html +# - show playlist length, # of next/asap available, likely queue position +# - show upcoming songs (5? just next-please?) +# - - just use SSI + python virtual includes, seriously + +import cgi, cgitb +import os, sys +import daemon +import subprocess +import random +from xbmcjson import XBMC + +cgitb.enable() + +print "content-type: text/html\n\n" + +music_dir = "/srv/archive/incoming/stolen-moosic" +form = cgi.FieldStorage () + +# Evil: just run replaygain/mp3gain/metaflac on the file and hope one +# works instead of dealing with MIME. For now. +def attempt_rpgain (file_name): + subprocess.call (["/usr/bin/vorbisgain", "-q", file_name]) + subprocess.call (["/usr/bin/mp3gain", "-q", "-s", "i", file_name]) + subprocess.call (["/usr/bin/metaflac", "--add-replay-gain", file_name]) + +def save_uploaded_file (form_field, upload_dir): + if form_field not in form: + print "

No file provided.

" + sys.exit () + fileitem = form[form_field] + fout = file (os.path.join(upload_dir, fileitem.filename), 'wb') + fout.write (fileitem.value) + fout.close() + return fileitem.filename + +song_name = save_uploaded_file ("song", music_dir) + +print '

Upload another song

' +sys.stdout.flush () + +#with daemon.DaemonContext (): +attempt_rpgain ("{0}/{1}".format (music_dir, song_name)) + +xbmc = XBMC ("http://localhost:8080/jsonrpc") + +# todo: use REMOTE_ADDR to limit how many asap requests a person can +# make in a time period +totalitems = xbmc.Playlist.GetItems (playlistid=0)['result']['limits']['total'] +playpos = random.randint (1, totalitems / (1 if 'asap' not in form else 3)) + +print xbmc.Playlist.Insert (playlistid=0, item={"file": "{0}/{1}".format (music_dir, song_name)}, position=playpos) + +print '

Your song is number {0} in the queue ({1} songs in playlist).

'.format (playpos, totalitems+1) + + -- 2.20.1