Compare commits

...

7 Commits

Author SHA1 Message Date
ed
54013d861b v0.11.23 2021-06-21 21:15:56 +02:00
ed
ec100210dc support showing album-cover on windows lockscreen 2021-06-21 19:15:22 +00:00
ed
3ab1acf32c v0.11.22 2021-06-21 20:30:29 +02:00
ed
8c28266418 subscribe to media-keys globally as a media player 2021-06-21 20:26:11 +02:00
ed
7f8b8dcb92 scandir is not withable before py3.6 2021-06-21 20:23:35 +02:00
ed
6dd39811d4 disable u2idx if sqlite3 is unavailable 2021-06-21 20:22:54 +02:00
ed
35e2138e3e doc: macos support 2021-06-21 18:42:15 +02:00
8 changed files with 136 additions and 27 deletions

View File

@@ -111,7 +111,7 @@ summary: all planned features work! now please enjoy the bloatening
* ☑ FUSE client (read-only) * ☑ FUSE client (read-only)
* browser * browser
* ☑ tree-view * ☑ tree-view
* ☑ audio player * ☑ audio player (with OS media controls)
* ☑ thumbnails * ☑ thumbnails
* ☑ images using Pillow * ☑ images using Pillow
* ☑ videos using FFmpeg * ☑ videos using FFmpeg

View File

@@ -410,7 +410,7 @@ def main(argv=None):
+ " (if you crash with codec errors then that is why)" + " (if you crash with codec errors then that is why)"
) )
if WINDOWS and sys.version_info < (3, 6): if sys.version_info < (3, 6):
al.no_scandir = True al.no_scandir = True
# signal.signal(signal.SIGINT, sighandler) # signal.signal(signal.SIGINT, sighandler)

View File

@@ -1,8 +1,8 @@
# coding: utf-8 # coding: utf-8
VERSION = (0, 11, 21) VERSION = (0, 11, 23)
CODENAME = "the grid" CODENAME = "the grid"
BUILD_DT = (2021, 6, 20) BUILD_DT = (2021, 6, 21)
S_VERSION = ".".join(map(str, VERSION)) S_VERSION = ".".join(map(str, VERSION))
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT) S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)

View File

@@ -26,7 +26,7 @@ class U2idx(object):
self.timeout = self.args.srch_time self.timeout = self.args.srch_time
if not HAVE_SQLITE3: if not HAVE_SQLITE3:
self.log("could not load sqlite3; searchign wqill be disabled") self.log("your python does not have sqlite3; searching will be disabled")
return return
self.cur = {} self.cur = {}
@@ -57,6 +57,9 @@ class U2idx(object):
raise Pebkac(500, min_ex()) raise Pebkac(500, min_ex())
def get_cur(self, ptop): def get_cur(self, ptop):
if not HAVE_SQLITE3:
return None
cur = self.cur.get(ptop) cur = self.cur.get(ptop)
if cur: if cur:
return cur return cur

View File

@@ -811,10 +811,12 @@ input.eq_gain {
padding: 0; padding: 0;
border-bottom: 1px solid #555; border-bottom: 1px solid #555;
} }
#thumbs { #thumbs,
#au_osd_cv {
opacity: .3; opacity: .3;
} }
#griden.on+#thumbs { #griden.on+#thumbs,
#au_os_ctl.on+#au_osd_cv {
opacity: 1; opacity: 1;
} }
#ghead { #ghead {

View File

@@ -222,10 +222,14 @@ var have_webp = null;
var mpl = (function () { var mpl = (function () {
var have_mctl = 'mediaSession' in navigator && window.MediaMetadata;
ebi('op_player').innerHTML = ( ebi('op_player').innerHTML = (
'<div><h3>switches</h3><div>' + '<div><h3>switches</h3><div>' +
'<a href="#" class="tgl btn" id="au_preload" tt="start loading the next song near the end for gapless playback">preload</a>' + '<a href="#" class="tgl btn" id="au_preload" tt="start loading the next song near the end for gapless playback">preload</a>' +
'<a href="#" class="tgl btn" id="au_npclip" tt="show buttons for clipboarding the currently playing song">/np clip</a>' + '<a href="#" class="tgl btn" id="au_npclip" tt="show buttons for clipboarding the currently playing song">/np clip</a>' +
'<a href="#" class="tgl btn" id="au_os_ctl" tt="os integration (media hotkeys / osd)">os-ctl</a>' +
'<a href="#" class="tgl btn" id="au_osd_cv" tt="show album cover in osd">osd-cv</a>' +
'</div></div>' + '</div></div>' +
'<div><h3>playback mode</h3><div id="pb_mode">' + '<div><h3>playback mode</h3><div id="pb_mode">' +
@@ -238,7 +242,9 @@ var mpl = (function () {
var r = { var r = {
"pb_mode": sread('pb_mode') || 'loop-folder', "pb_mode": sread('pb_mode') || 'loop-folder',
"preload": bcfg_get('au_preload', true), "preload": bcfg_get('au_preload', true),
"clip": bcfg_get('au_npclip', false) "clip": bcfg_get('au_npclip', false),
"os_ctl": bcfg_get('au_os_ctl', false) && have_mctl,
"osd_cv": bcfg_get('au_osd_cv', true),
}; };
ebi('au_preload').onclick = function (e) { ebi('au_preload').onclick = function (e) {
@@ -254,6 +260,20 @@ var mpl = (function () {
clmod(ebi('wtoggle'), 'np', r.clip && mp.au); clmod(ebi('wtoggle'), 'np', r.clip && mp.au);
}; };
ebi('au_os_ctl').onclick = function (e) {
ev(e);
r.os_ctl = !r.os_ctl && have_mctl;
bcfg_set('au_os_ctl', r.os_ctl);
if (!have_mctl)
alert('need firefox 82+ or chrome 73+');
};
ebi('au_osd_cv').onclick = function (e) {
ev(e);
r.osd_cv = !r.osd_cv;
bcfg_set('au_osd_cv', r.osd_cv);
};
function draw_pb_mode() { function draw_pb_mode() {
var btns = QSA('#pb_mode>a'); var btns = QSA('#pb_mode>a');
for (var a = 0, aa = btns.length; a < aa; a++) { for (var a = 0, aa = btns.length; a < aa; a++) {
@@ -270,6 +290,55 @@ var mpl = (function () {
draw_pb_mode(); draw_pb_mode();
} }
r.announce = function () {
if (!r.os_ctl)
return;
var np = get_np()[0],
fns = np.file.split(' - '),
artist = (np.circle ? np.circle + ' // ' : '') + (np.artist || (fns.length > 1 ? fns[0] : '')),
tags = {
title: np.title || fns.slice(-1)[0]
};
if (artist)
tags.artist = artist;
if (np.album)
tags.album = np.album;
if (r.osd_cv) {
var files = QSA("#files tr>td:nth-child(2)>a[id]"),
cover = null;
for (var a = 0, aa = files.length; a < aa; a++) {
if (/^(cover|folder)\.(jpe?g|png|gif)$/.test(files[a].textContent)) {
cover = files[a].getAttribute('href');
break;
}
}
if (cover) {
cover += (cover.indexOf('?') === -1 ? '?' : '&') + 'th=j';
var pwd = get_pwd();
if (pwd)
cover += '&pw=' + uricom_enc(pwd);
tags.artwork = [{ "src": cover, type: "image/jpeg" }];
}
}
navigator.mediaSession.metadata = new MediaMetadata(tags);
navigator.mediaSession.playbackState = mp.au.paused ? "paused" : "playing";
navigator.mediaSession.setActionHandler('play', playpause);
navigator.mediaSession.setActionHandler('pause', playpause);
navigator.mediaSession.setActionHandler('seekbackward', function () { seek_au_rel(-10); });
navigator.mediaSession.setActionHandler('seekforward', function () { seek_au_rel(10); });
navigator.mediaSession.setActionHandler('previoustrack', prev_song);
navigator.mediaSession.setActionHandler('nexttrack', next_song);
};
return r; return r;
})(); })();
@@ -365,6 +434,28 @@ var mp = new MPlayer();
makeSortable(ebi('files'), mp.read_order.bind(mp)); makeSortable(ebi('files'), mp.read_order.bind(mp));
function get_np() {
var th = ebi('files').tHead.rows[0].cells,
tr = QS('#files tr.play').cells,
rv = [],
ra = [],
rt = {};
for (var a = 1, aa = th.length; a < aa; a++) {
var tv = tr[a].textContent,
tk = a == 1 ? 'file' : th[a].getAttribute('name').split('/').slice(-1)[0],
vis = th[a].className.indexOf('min') === -1;
if (!tv)
continue;
(vis ? rv : ra).push(tk);
rt[tk] = tv;
}
return [rt, rv, ra];
};
// toggle player widget // toggle player widget
var widget = (function () { var widget = (function () {
var ret = {}, var ret = {},
@@ -411,22 +502,16 @@ var widget = (function () {
}; };
npirc.onclick = nptxt.onclick = function (e) { npirc.onclick = nptxt.onclick = function (e) {
ev(e); ev(e);
var th = ebi('files').tHead.rows[0].cells, var irc = this.getAttribute('id') == 'npirc',
tr = QS('#files tr.play').cells,
irc = this.getAttribute('id') == 'npirc',
ck = irc ? '06' : '', ck = irc ? '06' : '',
cv = irc ? '07' : '', cv = irc ? '07' : '',
m = ck + 'np: '; m = ck + 'np: ',
npr = get_np(),
npk = npr[1],
np = npr[0];
for (var a = 1, aa = th.length; a < aa; a++) { for (var a = 0; a < npk.length; a++)
if (th[a].className.indexOf('min') !== -1) m += (npk[a] == 'file' ? '' : npk[a]) + '(' + cv + np[npk[a]] + ck + ') // ';
continue;
var tv = tr[a].textContent,
tk = a == 1 ? '' : th[a].getAttribute('name').split('/').slice(-1)[0];
m += tk + '(' + cv + tv + ck + ') // ';
}
m += '[' + cv + s2ms(mp.au.currentTime) + ck + '/' + cv + s2ms(mp.au.duration) + ck + ']'; m += '[' + cv + s2ms(mp.au.currentTime) + ck + '/' + cv + s2ms(mp.au.duration) + ck + ']';
@@ -635,6 +720,11 @@ function seek_au_mul(mul) {
seek_au_sec(mp.au.duration * mul); seek_au_sec(mp.au.duration * mul);
} }
function seek_au_rel(sec) {
if (mp.au)
seek_au_sec(mp.au.currentTime + sec);
}
function seek_au_sec(seek) { function seek_au_sec(seek) {
if (!mp.au) if (!mp.au)
return; return;
@@ -685,6 +775,9 @@ function playpause(e) {
} }
else else
play(0); play(0);
if (navigator.mediaSession)
navigator.mediaSession.playbackState = mp.au.paused ? "paused" : "playing";
}; };
@@ -1124,6 +1217,7 @@ function play(tid, seek, call_depth) {
mpui.progress_updater(); mpui.progress_updater();
pbar.drawbuf(); pbar.drawbuf();
mpl.announce();
return true; return true;
} }
catch (ex) { catch (ex) {
@@ -1206,6 +1300,8 @@ function autoplay_blocked(seek) {
seek_au_sec(seek); seek_au_sec(seek);
else else
mpui.progress_updater(); mpui.progress_updater();
mpl.announce();
}; };
na.onclick = unblocked; na.onclick = unblocked;
} }
@@ -1515,18 +1611,18 @@ document.onkeydown = function (e) {
pos = parseInt(k.slice(-1)) * 0.1; pos = parseInt(k.slice(-1)) * 0.1;
if (pos !== -1) if (pos !== -1)
return seek_au_mul(pos); return seek_au_mul(pos) || true;
var n = k == 'KeyJ' ? -1 : k == 'KeyL' ? 1 : 0; var n = k == 'KeyJ' ? -1 : k == 'KeyL' ? 1 : 0;
if (n !== 0) if (n !== 0)
return song_skip(n); return song_skip(n) || true;
if (k == 'KeyP') if (k == 'KeyP')
return playpause(); return playpause() || true;
n = k == 'KeyU' ? -10 : k == 'KeyO' ? 10 : 0; n = k == 'KeyU' ? -10 : k == 'KeyO' ? 10 : 0;
if (n !== 0) if (n !== 0)
return mp.au ? seek_au_sec(mp.au.currentTime + n) : true; return seek_au_rel(n) || true;
n = k == 'KeyI' ? -1 : k == 'KeyK' ? 1 : 0; n = k == 'KeyI' ? -1 : k == 'KeyK' ? 1 : 0;
if (n !== 0) if (n !== 0)
@@ -1536,7 +1632,6 @@ document.onkeydown = function (e) {
return tree_up(); return tree_up();
if (k == 'KeyB') if (k == 'KeyB')
//return treectl.hidden ? treectl.show() : treectl.hide();
return treectl.hidden ? treectl.entree() : treectl.detree(); return treectl.hidden ? treectl.entree() : treectl.detree();
if (k == 'KeyG') if (k == 'KeyG')

View File

@@ -359,6 +359,15 @@ function get_vpath() {
} }
function get_pwd() {
var pwd = ('; ' + document.cookie).split('; cppwd=');
if (pwd.length < 2)
return null;
return pwd[1].split(';')[0];
}
function unix2iso(ts) { function unix2iso(ts) {
return new Date(ts * 1000).toISOString().replace("T", " ").slice(0, -5); return new Date(ts * 1000).toISOString().replace("T", " ").slice(0, -5);
} }

View File

@@ -157,7 +157,7 @@ dbg.asyncStore.pendingBreakpoints = {}
about:config >> devtools.debugger.prefs-schema-version = -1 about:config >> devtools.debugger.prefs-schema-version = -1
# determine server version # determine server version
git reset --hard origin/HEAD && git log --format=format:"%H %ai %d" --decorate=full > /dev/shm/revs && cat /dev/shm/revs | while read -r rev extra; do (git reset --hard $rev >/dev/null 2>/dev/null && dsz=$(cat copyparty/web/{util,browser,up2k}.js 2>/dev/null | diff -wNarU0 - <(cat /mnt/Users/ed/Downloads/ref/{util,browser,up2k}.js) | wc -c) && printf '%s %6s %s\n' "$rev" $dsz "$extra") </dev/null; done git pull; git reset --hard origin/HEAD && git log --format=format:"%H %ai %d" --decorate=full > ../revs && cat ../{util,browser}.js >../vr && cat ../revs | while read -r rev extra; do (git reset --hard $rev >/dev/null 2>/dev/null && dsz=$(cat copyparty/web/{util,browser}.js >../vg 2>/dev/null && diff -wNarU0 ../{vg,vr} | wc -c) && printf '%s %6s %s\n' "$rev" $dsz "$extra") </dev/null; done
## ##