wplayer

Check-in [c475684d4b]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Switch to Fossil. Add tinytag; update window title with artist/track.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | master | trunk
Files: files | file ages | folders
SHA3-256:c475684d4bfd5f1296c9ca452aa591c4ed004b0c46ca95062bcab324d12ab822
User & Date: vandys 2018-06-12 22:51:32
Context
2018-06-12
22:52
Do my own styling. check-in: 78829a79ef user: vandys tags: master, trunk
22:51
Switch to Fossil. Add tinytag; update window title with artist/track. check-in: c475684d4b user: vandys tags: master, trunk
2018-04-28
00:37
Side-by-side sucked on mobile. Try picture below queue, and click to make it go away. check-in: c3a1651815 user: vandyswa@gmail.com tags: master, trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Deleted .gitignore.

1
2
3
4
5
chore
*.pyc
css
certs
var
<
<
<
<
<










Changes to get.py.

8
9
10
11
12
13
14

15
16
17
18
19
20
21
..
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
...
132
133
134
135
136
137
138
































139
140
141
142
143
144
145
146

147
148

149
150
151
152
153
154
155
...
190
191
192
193
194
195
196







197
198
199
200
201
202
203
#  /media/<prefix>/...
#	For each prefix of files, its contents is served by
#	way of its path under here.
import os, sys, stat, urllib, time
import utils
from chore.utils import uncharenc
from chore.handlers import sketchy


# Max search results when filtering
MAXSEARCH=20

# Turn names into plain ASCII ones, with remap record so they
#  can still be opened
remaps = {}
................................................................................
	for tup in cpaths:
	    if tup[0] == elem:
		return tup[1]
        return None

    # Run sox and stream ogg
    # This lets us transcode, specifically from flac, to things
    #  which don't play it (Firefox Android, nice job
    #  Mozilla) or where the network's too slow for it (DSL
    #  uplink).
    def send_ogg(self, path):

        # Sanity check usually done by send_files()
        # We also indulge in some paranoia on shell quoting
        if sketchy(path) or ('"' in path) or ('\\' in path):
            self.send_error(404)
................................................................................
                    break
                self.wfile.write(b)
        finally:
            f.close()

        return None

































    # GET dispatcher
    # See if it's a configured path, and serve file or dir
    def send_path(self):
        global remaps

	app = self.server
	webroot = app.approot
	cpaths = webroot.config["files"]

        # Get URL level quoting out of the way
	pp = [urllib.unquote(p) for p in self.paths]

        # If we had to flatten out characters, restore
        #  to filesystem name
        pp = [remaps.get(p, p) for p in pp]

	# We serve /media/prefix/blah/blah...
	if pp[0] != "media":
	    return False,None
................................................................................
            #  conversion of foo.flac
            # This lets us stream to players without flac
            #  support, or where the flac bitrate is too
            #  high for the network path.
            if self.vals and ("asogg" in self.vals):
                print "GET converted file", path
                buf = self.send_ogg(path)







            else:
                print "GET file", path
                buf = self.send_files(path)
	return True,buf

    # A search request
    #







>







 







|
|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








>


>







 







>
>
>
>
>
>
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
...
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
#  /media/<prefix>/...
#	For each prefix of files, its contents is served by
#	way of its path under here.
import os, sys, stat, urllib, time
import utils
from chore.utils import uncharenc
from chore.handlers import sketchy
from tinytag import TinyTag

# Max search results when filtering
MAXSEARCH=20

# Turn names into plain ASCII ones, with remap record so they
#  can still be opened
remaps = {}
................................................................................
	for tup in cpaths:
	    if tup[0] == elem:
		return tup[1]
        return None

    # Run sox and stream ogg
    # This lets us transcode, specifically from flac, to things
    #  which don't play it (old Firefox Android, but they fixed
    #  it, yay!) or where the network's too slow for it (DSL
    #  uplink).
    def send_ogg(self, path):

        # Sanity check usually done by send_files()
        # We also indulge in some paranoia on shell quoting
        if sketchy(path) or ('"' in path) or ('\\' in path):
            self.send_error(404)
................................................................................
                    break
                self.wfile.write(b)
        finally:
            f.close()

        return None

    # Get tinytag's take on metadata in this file, and return it
    def metadata(self, fn):
	# Pull tags if we can
	try:
	    tags = TinyTag.get(fn)
	except:
	    return self.send_error(422)

	# Convert from attributes on object to JSON-able dict
	res = {}
	for k,v in tags.__dict__.iteritems():

	    # Internal stuff from TinyTag
	    if k[0] == '_':
		continue

	    # Straight ASCII here
	    if isinstance(v, unicode):
		v = str(v)

	    # Inherently numeric channels
	    if k in ("year", "channels", "track", "disc", "track_total",
		    "disc_total"):
		if v and isinstance(v, str) and v.isdigit():
		    v = int(v)

	    # Build our dict result
	    res[k] = v

	# JSON encoded result
	return self.send_json(res)

    # GET dispatcher
    # See if it's a configured path, and serve file or dir
    def send_path(self):
        global remaps

	app = self.server
	webroot = app.approot
	cpaths = webroot.config["files"]

        # Get URL level quoting out of the way
	pp = [urllib.unquote(p) for p in self.paths]

        # If we had to flatten out characters, restore
        #  to filesystem name
        pp = [remaps.get(p, p) for p in pp]

	# We serve /media/prefix/blah/blah...
	if pp[0] != "media":
	    return False,None
................................................................................
            #  conversion of foo.flac
            # This lets us stream to players without flac
            #  support, or where the flac bitrate is too
            #  high for the network path.
            if self.vals and ("asogg" in self.vals):
                print "GET converted file", path
                buf = self.send_ogg(path)

	    # get /path/to/foo.mp3?meta
	    # Send back JSON of the metadata of the file
	    elif self.vals and ("metadata" in self.vals):
		print "Metadata for", path
		buf = self.metadata(path)

            else:
                print "GET file", path
                buf = self.send_files(path)
	return True,buf

    # A search request
    #

Changes to html/top.html.

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<link rel="stylesheet" type="text/css" href="/css/player.css" />
<head>
 <meta charset="utf-8">
 <meta name="viewport" content="width=device-width, initial-scale=1">
 <title>Web Player</title>
</head>
<body>
 <textarea rows="8" cols="80" readonly id="pqueue"></textarea><br>
 <img onclick="unplayart();" style="display: none;" id="playart">
 <hr>
 <span id="nowplaying"></span><br>
 <table>
  <tr>
   <td>
    <audio controls autoplay id="player" style="text-align: center;"></audio>







|







2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<link rel="stylesheet" type="text/css" href="/css/player.css" />
<head>
 <meta charset="utf-8">
 <meta name="viewport" content="width=device-width, initial-scale=1">
 <title>Web Player</title>
</head>
<body>
 <textarea rows="8" readonly id="pqueue"></textarea><br>
 <img onclick="unplayart();" style="display: none;" id="playart">
 <hr>
 <span id="nowplaying"></span><br>
 <table>
  <tr>
   <td>
    <audio controls autoplay id="player" style="text-align: center;"></audio>

Changes to js/player.js.

214
215
216
217
218
219
220






















221
222
223
224
225
226
227
...
234
235
236
237
238
239
240

241

242
243
244

245
246
247
248
249
250
251
...
281
282
283
284
285
286
287

288
289
290
291
292
293
294
    }
}

// Does this path look art-ish?
function isart(fn) {
    return (fn.endsWith(".jpg") || fn.endsWith(".png"));
}























// End of current track, try to advance
function playNext() {
    lovebtn.style.background = "";
    while (playlist.length > 0) {
	var s = playlist.shift();

................................................................................
	}

	// Play it
	player.src = s;

	// For good measure
	player.play();



	nowplaying.textContent = do_trim(unescape(s));
	paintQueue();
	playing = true;


	return;
    }

    // Nothing to play
    nowplaying.textContent = '';
    playing = false;
................................................................................

    // Play or queue a track
    if (!playing) {
	player.src = fname;
	nowplaying.textContent = do_trim(unescape(fname));
	player.play();
	playing = true;

    } else {
	playlist.push(fname);
	paintQueue();
    }
    return false;
}








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>

>


<
>







 







>







214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
...
256
257
258
259
260
261
262
263
264
265
266
267

268
269
270
271
272
273
274
275
...
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
    }
}

// Does this path look art-ish?
function isart(fn) {
    return (fn.endsWith(".jpg") || fn.endsWith(".png"));
}

// Ask the server to extract the metadata for this track
// If we get it, update the window title so things like lock screen
//  hold something helpful.
function paint_metadata(s) {
    let req = new XMLHttpRequest();
    req.open("GET", s + "?metadata");
    req.onreadystatechange = function() {
	if (req.readyState == 4) {
	    if (req.status == 200) {
		let meta = JSON.parse(this.responseText);
		window.document.title =
		    (meta.artist || "") + " - " +
		    (meta.title || "");
	    } else {
		// No metadata available this time
		window.document.title = "WWW Player";
	    }
	}
    }
    req.send();
}

// End of current track, try to advance
function playNext() {
    lovebtn.style.background = "";
    while (playlist.length > 0) {
	var s = playlist.shift();

................................................................................
	}

	// Play it
	player.src = s;

	// For good measure
	player.play();
	playing = true;

	// Update UI
	nowplaying.textContent = do_trim(unescape(s));
	paintQueue();

	paint_metadata(s);

	return;
    }

    // Nothing to play
    nowplaying.textContent = '';
    playing = false;
................................................................................

    // Play or queue a track
    if (!playing) {
	player.src = fname;
	nowplaying.textContent = do_trim(unescape(fname));
	player.play();
	playing = true;
	paint_metadata(fname);
    } else {
	playlist.push(fname);
	paintQueue();
    }
    return false;
}