diff --git a/README.md b/README.md index 360759de..bcd9a8b7 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ turn almost any device into a file server with resumable uploads/downloads using * [batch rename](#batch-rename) - select some files and press `F2` to bring up the rename UI * [media player](#media-player) - plays almost every audio format there is * [audio equalizer](#audio-equalizer) - bass boosted + * [unreliable playback on android](#unreliable-playback-on-android) - due to phone / app settings * [markdown viewer](#markdown-viewer) - and there are *two* editors * [other tricks](#other-tricks) * [searching](#searching) - search by size, date, path/name, mp3-tags, ... @@ -275,6 +276,8 @@ server notes: * [Firefox issue 1790500](https://bugzilla.mozilla.org/show_bug.cgi?id=1790500) -- entire browser can crash after uploading ~4000 small files +* Android: music playback randomly stops due to [battery usage settings](#unreliable-playback-on-android) + * iPhones: the volume control doesn't work because [apple doesn't want it to](https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW11) * *future workaround:* enable the equalizer, make it all-zero, and set a negative boost to reduce the volume * "future" because `AudioContext` can't maintain a stable playback speed in the current iOS version (15.7), maybe one day... @@ -701,6 +704,11 @@ can also boost the volume in general, or increase/decrease stereo width (like [c has the convenient side-effect of reducing the pause between songs, so gapless albums play better with the eq enabled (just make it flat) +### unreliable playback on android + +due to phone / app settings, android phones may randomly stop playing music when the power saver kicks in, especially at the end of an album -- you can fix it by [disabling power saving](https://user-images.githubusercontent.com/241032/235262123-c328cca9-3930-4948-bd18-3949b9fd3fcf.png) in the [app settings](https://user-images.githubusercontent.com/241032/235262121-2ffc51ae-7821-4310-a322-c3b7a507890c.png) of the browser you use for music streaming (preferably a dedicated one) + + ## markdown viewer and there are *two* editors diff --git a/copyparty/web/browser.js b/copyparty/web/browser.js index 994c1f97..dfacd9d8 100644 --- a/copyparty/web/browser.js +++ b/copyparty/web/browser.js @@ -261,6 +261,7 @@ var Ls = { "mm_e403": "Could not play audio; error 403: Access denied.\n\nTry pressing F5 to reload, maybe you got logged out", "mm_e5xx": "Could not play audio; server error ", "mm_nof": "not finding any more audio files nearby", + "mm_pwrsv": "
it looks like playback is being interrupted by your phone's power-saving settings!
" + 'please go to the app settings of your browser and then allow unrestricted battery usage to fix it.
(probably a good idea to use a separate browser dedicated for just music streaming...)
', "mm_hnf": "that song no longer exists", "im_hnf": "that image no longer exists", @@ -721,6 +722,7 @@ var Ls = { "mm_e403": "Avspilling feilet: Tilgang nektet.\n\nKanskje du ble logget ut?\nPrøv å trykk F5 for å laste siden på nytt.", "mm_e5xx": "Avspilling feilet: ", "mm_nof": "finner ikke flere sanger i nærheten", + "mm_pwrsv": "det ser ut som musikken ble avbrutt av telefonen sine strømsparings-innstillinger!
" + 'ta en tur innom app-innstillingene til nettleseren din og så tillat ubegrenset batteriforbruk
(sikkert smart å ha en egen nettleser kun for musikkspilling...)
', "mm_hnf": "sangen finnes ikke lenger", "im_hnf": "bildet finnes ikke lenger", @@ -1483,7 +1485,8 @@ var mpl = (function () { ebi('np_title').textContent = np.title || ''; ebi('np_dur').textContent = np['.dur'] || ''; ebi('np_url').textContent = get_vpath() + np.file.split('?')[0]; - ebi('np_img').setAttribute('src', cover || ''); // dont give last.fm the pwd + if (!MOBILE) + ebi('np_img').setAttribute('src', cover || ''); // dont give last.fm the pwd navigator.mediaSession.metadata = new MediaMetadata(tags); navigator.mediaSession.setActionHandler('play', mplay); @@ -1541,6 +1544,7 @@ var re_au_native = can_ogg ? /\.(aac|flac|m4a|mp3|ogg|opus|wav)$/i : // extract songs + add play column var mpo = { "au": null, "au2": null, "acs": null }; +var t_fchg = 0; function MPlayer() { var r = this; r.id = Date.now(); @@ -2162,17 +2166,30 @@ function song_skip(n) { else play(mp.order[n == -1 ? mp.order.length - 1 : 0]); } +function next_song_sig(e) { + t_fchg = document.hasFocus() ? 0 : Date.now(); + return next_song_cmn(e); +} function next_song(e) { + t_fchg = 0; + return next_song_cmn(e); +} +function next_song_cmn(e) { ev(e); if (mp.order.length) { mpl.traversals = 0; return song_skip(1); } if (mpl.traversals++ < 5) { - treectl.ls_cb = next_song; + if (MOBILE && t_fchg && Date.now() - t_fchg > 30 * 1000) + modal.alert(L.mm_pwrsv); + + t_fchg = document.hasFocus() ? 0 : Date.now(); + treectl.ls_cb = next_song_cmn; return tree_neigh(1); } toast.inf(10, L.mm_nof); + t_fchg = 0; } function prev_song(e) { ev(e); @@ -2288,6 +2305,10 @@ var mpui = (function () { return; } + var pos = mp.au.currentTime; + if (!isNum(pos)) + pos = 0; + // indicate playback state in ui widget.paused(mp.au.paused); @@ -2310,10 +2331,18 @@ var mpui = (function () { pbar.drawbuf(); } + if (pos > 0.3 && t_fchg) { + // cannot check document.hasFocus to avoid false positives; + // it continues on power-on, doesn't need to be in-browser + if (MOBILE && Date.now() - t_fchg > 30 * 1000) + modal.alert(L.mm_pwrsv); + + t_fchg = 0; + } + // preload next song if (mpl.preload && preloaded != mp.au.rsrc) { - var pos = mp.au.currentTime, - len = mp.au.duration, + var len = mp.au.duration, rem = pos > 1 ? len - pos : 999, full = null; @@ -2706,6 +2735,7 @@ function play(tid, is_ev, seek) { tn = 0; } else if (mpl.pb_mode == 'next') { + t_fchg = document.hasFocus() ? 0 : Date.now(); treectl.ls_cb = next_song; return tree_neigh(1); } @@ -2735,7 +2765,7 @@ function play(tid, is_ev, seek) { mp.au.onerror = evau_error; mp.au.onprogress = pbar.drawpos; mp.au.onplaying = mpui.progress_updater; - mp.au.onended = next_song; + mp.au.onended = next_song_sig; widget.open(); } @@ -2752,7 +2782,7 @@ function play(tid, is_ev, seek) { mp.au.onerror = evau_error; mp.au.onprogress = pbar.drawpos; mp.au.onplaying = mpui.progress_updater; - mp.au.onended = next_song; + mp.au.onended = next_song_sig; t = mp.au.currentTime; if (isNum(t) && t > 0.1) mp.au.currentTime = 0; @@ -2812,7 +2842,7 @@ function play(tid, is_ev, seek) { toast.err(0, esc(L.mm_playerr + basenames(ex))); } clmod(ebi(oid), 'act'); - setTimeout(next_song, 5000); + setTimeout(next_song_sig, 5000); } @@ -7326,9 +7356,6 @@ ebi('files').onclick = ebi('docul').onclick = function (e) { function reload_mp() { if (mp && mp.au) { - if (afilt) - afilt.stop(); - mpo.au = mp.au; mpo.au2 = mp.au2; mpo.acs = mp.acs; diff --git a/docs/notes.sh b/docs/notes.sh index db301102..3c83b6fc 100644 --- a/docs/notes.sh +++ b/docs/notes.sh @@ -194,6 +194,9 @@ sqlite3 .hist/up2k.db 'select * from mt where k="fgsfds" or k="t:mtp"' | tee /de for ((f=420;f<1200;f++)); do sz=$(ffmpeg -y -f lavfi -i sine=frequency=$f:duration=2 -vf volume=0.1 -ac 1 -ar 44100 -f s16le /dev/shm/a.wav 2>/dev/null; base64 -w0