Commit | Line | Data |
---|---|---|
fffe2166 CE |
1 | #!/usr/bin/python |
2 | ||
3 | # ADD COMMAND TO RESTART PARTY MODE | |
4 | # (probably should require confirmation) | |
5 | # also add undelete link to post-del link just in case (reinsert at old pos) | |
6 | ||
7 | # Trivial xbmc admin script to view active playlist, control volume, | |
8 | # etc. | |
9 | ||
10 | # I would not recommend putting this online, no attempt is made at | |
11 | # being even trivially secure (e.g. form values are passed directly to | |
12 | # kodi with zero verification) | |
13 | ||
14 | # todo | |
15 | # any kind of error checking | |
16 | ||
17 | from __future__ import unicode_literals | |
18 | ||
19 | # Python is being obnoxious as hell and refusing to .format() utf-8 | |
20 | # strings. I have no idea. Just hack around it and deal with the | |
21 | # actual problem later instead of scattering the code with .encode | |
22 | # calls. | |
23 | ||
24 | import sys | |
25 | reload(sys) | |
26 | sys.setdefaultencoding ('utf-8') | |
27 | ||
28 | import cgi, cgitb | |
29 | import os | |
30 | import subprocess | |
31 | import random | |
32 | from xbmcjson import XBMC | |
33 | ||
34 | cgitb.enable() | |
35 | ||
36 | print ("content-type: text/html; charset=utf-8\n\n") | |
37 | ||
38 | print (u''' | |
39 | <style> | |
40 | input, select, button { font-size: 200%} | |
41 | .horiz-menu li { display: inline } | |
42 | body { /* background-image: url("fire-under-construction-animation.gif"); */ | |
43 | color: white; | |
44 | background-color: black; | |
45 | } | |
46 | </style> | |
47 | ||
48 | <ul class="horiz-menu""> | |
49 | <li><a href="admin.cgi">reload</a></li> | |
50 | <li><a href="#playlist">playlist</a></li> | |
51 | <li><a href="#controls">control</a></li> | |
52 | <li><a href="javascript:document.getElementById("quicksearch").focus()">search</a></li> | |
53 | </ul> | |
54 | ''') | |
55 | ||
56 | music_dir = "/srv/archive/incoming/stolen-moosic" | |
57 | form = cgi.FieldStorage () | |
58 | ||
59 | xbmc = XBMC ("http://localhost:8080/jsonrpc") | |
60 | ||
61 | def show_quick_search (term="",thereal=False): | |
62 | print (u''' | |
63 | <form method="get" action="admin.cgi" style="display: inline-block"> | |
64 | <input type="text" name="searchterm" value="{}" {} /> | |
65 | <select name="searchfield"> | |
66 | <option value="title">name</option> | |
67 | <option value="albumartist">artist</option> | |
68 | <option value="album">album</option> | |
69 | </select> | |
70 | <button type="submit" name="searchgo" value="1">Search</button> | |
71 | </form> | |
72 | ''').format(term, 'id="quicksearch"' if thereal else '') | |
73 | ||
74 | def show_search_results (songs): | |
75 | print (u"<h1>Results</h1>") | |
76 | print (u"<ol>") | |
77 | for song in songs: | |
78 | print (u'<li>{} ({}) {}'.format (song['albumartist'][0], song['album'], song['label'])) | |
79 | print ('<form method="post" action="admin.cgi" style="display: inline-block">') | |
80 | print ('<button type="submit" name="randomqueue" value="{}">yeh</button>'.format(song['songid'])) | |
81 | print ('</form>') | |
82 | print ('</li>') | |
83 | print (u"</ol>") | |
84 | ||
85 | if 'songdel' in form: | |
86 | songid = int(form['songdel'].value) | |
87 | print (songid) | |
88 | (pos,name) = next ((i,s) for i,s in enumerate(xbmc.Playlist.GetItems (playlistid=0)['result']['items']) if s['id'] == songid) | |
89 | print (u"<p>Deleted {}</p>".format(name['label'])) | |
90 | print (xbmc.Playlist.Remove (playlistid=0, position=pos)) | |
91 | elif 'songup' in form: | |
92 | songid = int(form['songup'].value) | |
93 | print (songid) | |
94 | (pos,name) = next ((i,s) for i,s in enumerate(xbmc.Playlist.GetItems (playlistid=0)['result']['items']) if s['id'] == songid) | |
95 | print (u"<p>Promoted {}</p>".format(name['label'])) | |
96 | print (xbmc.Playlist.Swap (playlistid=0, position1=pos, position2=pos-1)) | |
97 | elif 'songdown' in form: | |
98 | songid = int(form['songdown'].value) | |
99 | print (songid) | |
100 | (pos,name) = next ((i,s) for i,s in enumerate(xbmc.Playlist.GetItems (playlistid=0)['result']['items']) if s['id'] == songid) | |
101 | print (u"<p>Demoted {}</p>".format(name['label'])) | |
102 | print (xbmc.Playlist.Swap (playlistid=0, position1=pos, position2=pos+1)) | |
103 | elif 'volchange' in form: | |
104 | curvolume = xbmc.Application.GetProperties (properties=['volume'])['result']['volume'] | |
105 | newvolume = max (0, min (int (form['volchange'].value) + curvolume, 100)) | |
106 | print (xbmc.Application.SetVolume (volume=newvolume)) | |
107 | elif 'volmute' in form: | |
108 | print (xbmc.Application.SetMute (mute="toggle")) | |
109 | elif 'navigate' in form: | |
110 | action = form['navigate'].value | |
111 | if action == 'prev': | |
112 | print xbmc.Player.GoTo (to="previous", playerid=0) | |
113 | elif action == 'next': | |
114 | print xbmc.Player.GoTo (to="next", playerid=0) | |
115 | elif action == 'playpause': | |
116 | print xbmc.Player.PlayPause (play="toggle", playerid=0) | |
117 | elif 'searchgo' in form: | |
118 | term = form['searchterm'].value | |
119 | field = form['searchfield'].value | |
120 | results = xbmc.AudioLibrary.GetSongs (filter={'operator': "contains", 'field': field, 'value': term}, properties=['album', 'albumartist'], sort={'order': 'ascending', 'method': 'artist'})['result']['songs'] | |
121 | show_quick_search (term) | |
122 | show_search_results (results) | |
123 | elif 'randomqueue' in form: | |
124 | songid = int(form['randomqueue'].value) | |
125 | totalitems = xbmc.Playlist.GetItems (playlistid=0)['result']['limits']['total'] | |
126 | playpos = random.randint (1, totalitems / 3 + 1) | |
127 | print xbmc.Playlist.Insert (playlistid=0, item={"songid": songid}, position=playpos) | |
128 | print '<p style="font-size: x-large">Your song is number {0} in the queue ({1} songs in playlist).</p>'.format (playpos, totalitems+1) | |
129 | ||
130 | ||
131 | ||
132 | ||
133 | ||
134 | playlist = xbmc.Playlist.GetItems (playlistid=0, properties=['album', 'albumartist'])['result']['items'] | |
135 | #playpos = random.randint (1, totalitems / (1 if 'asap' not in form else 3)) | |
136 | ||
137 | print ('<a name="controls"></a>') | |
138 | print ('<p>Volume: {}%</p>'.format(xbmc.Application.GetProperties (properties=['volume'])['result']['volume'])) | |
139 | print (''' | |
140 | <form method="post" action="admin.cgi" style="display: inline-block"> | |
141 | <button name="volchange" value="5" type="submit">+5</button> | |
142 | <button name="volchange" value="-5" type="submit">-5</button> | |
143 | ||
144 | <button name="volchange" value="10" type="submit">+10</button> | |
145 | <button name="volchange" value="-10" type="submit">-10</button> | |
146 | ||
147 | <button name="volmute" value="1">Toggle Mute</button> | |
148 | ||
149 | </form> | |
150 | ''') | |
151 | ||
152 | print (''' | |
153 | <form method="post" action="admin.cgi" style="display: inline-block"> | |
154 | <button name="navigate" value="prev" type="submit">⏮</button> | |
155 | <button name="navigate" value="next" type="submit">⏭</button> | |
156 | <button name="navigate" value="playpause" type="submit">⏯</button> | |
157 | </form> | |
158 | ''') | |
159 | ||
160 | ||
161 | print ('<a name="playlist"></a><h1>Playlist</h1>') | |
162 | print ("<ol>") | |
163 | for song in playlist: | |
164 | print (u'<li>{} {}'.format(song['albumartist'][0], song['label']).encode('UTF-8')) | |
165 | ||
166 | print ('<form method="post" action="admin.cgi" style="display: inline-block">') | |
167 | print ('<button name="songdel" value="{}">del</button>'.format(song['id'])) | |
168 | print ('<button name="songup" value="{}">up</button>'.format(song['id'])) | |
169 | print ('<button name="songdown" value="{}">down</button>'.format(song['id'])) | |
170 | print ('</form>' ) | |
171 | print ("</li>") | |
172 | print ("</ol>") | |
173 | ||
174 | print ('<a name="search"></a>') | |
175 | show_quick_search (thereal=True) |