diff --git a/install.sh b/install.sh index 657748b15..b2f4f9c60 100644 --- a/install.sh +++ b/install.sh @@ -14,6 +14,9 @@ dirshm=$dirdata/shm dirsystem=$dirdata/system dirwebradio=/srv/http/data/webradio +# 20221218 +[[ -L $dirdata/playlists ]] && chown -h mpd:audio $dirdata/playlists + # 20221208 if [[ -e /srv/http/assets/css/desktop.css ]]; then rm -f /srv/http/main.php @@ -22,7 +25,7 @@ if [[ -e /srv/http/assets/css/desktop.css ]]; then rm -f /srv/http/assets/js/plugin/{jquery.selectric,simple-}* fi -readarray -t bookmarks <<< $( ls -1 /srv/http/data/bookmarks/* ) +readarray -t bookmarks <<< $( ls -1 /srv/http/data/bookmarks/* 2> /dev/null ) if [[ $bookmarks ]]; then for file in "${bookmarks[@]}"; do if [[ $( sed -n 2p "$file" ) ]]; then @@ -102,6 +105,8 @@ fi #------------------------------------------------------------------------------- installstart "$1" +rm -rf /srv/http/assets/{css,js} + getinstallzip chmod +x $dirsettings/system.sh diff --git a/srv/http/assets/css/common.css b/srv/http/assets/css/common.css index 28f8dabb2..718cce6ca 100644 --- a/srv/http/assets/css/common.css +++ b/srv/http/assets/css/common.css @@ -1,6 +1,6 @@ @font-face { font-family : rern; - src : url( '/assets/fonts/rern.woff2?v.2022121800' ) format( 'woff2' ); + src : url( '/assets/fonts/rern.woff2?v.2022121600' ) format( 'woff2' ); font-display : block; font-style : normal; font-weight : normal; diff --git a/srv/http/assets/css/main.css b/srv/http/assets/css/main.css index c1292b999..c0f257b2c 100644 --- a/srv/http/assets/css/main.css +++ b/srv/http/assets/css/main.css @@ -1047,11 +1047,18 @@ i.map.disabled, .map.disabled i { #biocontent .close-root, #biocontent .bioback { float: right; - margin-top: 0; + width: 40px; + line-height: 40px; + margin-top: 5px; + margin-right: -8px; font-size: 24px; + text-align: center; color: var( --cm ) !important; z-index: 5; } +#biocontent .bioback { + margin-top: -10px; +} #biocontent .genre { text-transform: capitalize; } @@ -1315,6 +1322,7 @@ i.map.disabled, .map.disabled i { } .coveredit { position: absolute; + right: 0; bottom: 0; width: 34px; height: 34px; @@ -1324,20 +1332,17 @@ i.map.disabled, .map.disabled i { left: 0; } .coveredit.cover-save i { - width: 30px; + width: 30px !important; height: 30px; margin-left: 2px; font-size: 24px; - line-height: 30px; + line-height: 30px !important; text-align: center; - color: #000000; + color: var( --cgd ) !important; background: var( --cw ); border-radius: 50%; box-shadow: -1px 1px 2px #000000; } -.coveredit.cover { - right: 0; -} #bannerIcon .iconcover { margin: 3px; } @@ -1346,6 +1351,7 @@ i.map.disabled, .map.disabled i { width: 28px !important; } .infoimgname { + line-height: 25px; clear: both; margin: 0; } diff --git a/srv/http/assets/css/settings.css b/srv/http/assets/css/settings.css index 529b7d035..81f6e5b36 100644 --- a/srv/http/assets/css/settings.css +++ b/srv/http/assets/css/settings.css @@ -189,7 +189,7 @@ heading i.fa-status { heading.status i.fa-status { display: inline-block; } -heading i.fa-help { +heading i.help { float: right; width: 40px; font-size: 22px; @@ -507,7 +507,7 @@ input.disabled + .switchlabel:after { text-align: center; } .col-r { - width: calc( 100% - 170px ); + width: calc( 100% - 165px ); padding-right: 0; padding-left: 0 !important; font-weight: normal; @@ -560,6 +560,9 @@ input.disabled + .switchlabel:after { .head { padding-right: 0 !important; } + heading i.help { + margin-right: -10px; + } wide { display: none; } diff --git a/srv/http/assets/fonts/rern.woff2 b/srv/http/assets/fonts/rern.woff2 index 2385544c9..6bf27a455 100644 Binary files a/srv/http/assets/fonts/rern.woff2 and b/srv/http/assets/fonts/rern.woff2 differ diff --git a/srv/http/assets/js/common.js b/srv/http/assets/js/common.js index 67239339a..b73653496 100644 --- a/srv/http/assets/js/common.js +++ b/srv/http/assets/js/common.js @@ -4,13 +4,12 @@ info(), infoPower(), infoPowerCommand(), infoPowerNfs(), loader(), local(), $.fn.press(), pushstream, selectSet() */ -G = {} var page = location.search.replace( '?p=', '' ); var iconwarning = ' '; // ---------------------------------------------------------------------- function banner( icon, title, message, delay ) { - clearTimeout( G.timeoutbanner ); + clearTimeout( I.timeoutbanner ); var iconhtml = icon && icon.slice( 0, 1 ) === '<' ? icon : icon ? '' : ''; @@ -19,19 +18,11 @@ function banner( icon, title, message, delay ) {
${ title }
${ message }
` ).removeClass( 'hide' ); - if ( delay !== -1 ) G.timeoutbanner = setTimeout( bannerHide, delay || 3000 ); + if ( delay !== -1 ) I.timeoutbanner = setTimeout( bannerHide, delay || 3000 ); } function bannerHide() { if ( $( '#banner' ).hasClass( 'hide' ) ) return - if ( G.bannerhold ) { - setTimeout( () => { - G.bannerhold = 0; - bannerHide(); - }, G.bannerhold ); - return - } - clearTimeout( G.timeoutbanner ); $( '#banner' ) .addClass( 'hide' ) .empty(); @@ -611,8 +602,8 @@ function infoCheckSet() { } function infoFileImage() { delete I.infofilegif; - G.timeoutfile = setTimeout( () => banner( 'refresh blink', 'Change Image', 'Load ...', -1 ), 1000 ); - G.rotate = 0; + I.timeoutfile = setTimeout( () => banner( 'refresh blink', 'Change Image', 'Load ...', -1 ), 1000 ); + I.rotate = 0; $( '.infoimgname' ).addClass( 'hide' ); $( '.infoimgnew, .infoimgwh' ).remove(); if ( I.infofile.name.slice( -3 ) !== 'gif' ) { @@ -633,7 +624,7 @@ function infoFileImage() { var imgH = img.height; var resize = infoFileImageResize( 'gif', imgW, imgH ); infoFileImageRender( img.src, imgW +' x '+ imgH, resize ? resize.wxh : '' ); - clearTimeout( G.timeoutfile ); + clearTimeout( I.timeoutfile ); bannerHide(); } } else { @@ -643,7 +634,7 @@ function infoFileImage() { } } function infoFileImageReader() { - var maxsize = ( G.library && ! G.librarylist ) ? 200 : 1000; + var maxsize = ( V.library && ! V.librarylist ) ? 200 : 1000; var reader = new FileReader(); reader.onload = function( e ) { var img = new Image(); @@ -667,7 +658,7 @@ function infoFileImageReader() { } else { infoFileImageRender( filecanvas.toDataURL( 'image/jpeg' ), imgW +' x '+ imgH ); } - clearTimeout( G.timeoutfile ); + clearTimeout( I.timeoutfile ); bannerHide(); } } @@ -677,8 +668,8 @@ function infoFileImageReader() { .on( 'click', '.infoimgnew', function() { if ( ! $( '.infomessage .rotate' ).length ) return - G.rotate += 90; - if ( G.rotate === 360 ) G.rotate = 0; + I.rotate += 90; + if ( I.rotate === 360 ) I.rotate = 0; var canvas = document.createElement( 'canvas' ); var ctx = canvas.getContext( '2d' ); var image = $( this )[ 0 ]; @@ -713,7 +704,7 @@ function infoFileImageRender( src, original, resize ) { ); } function infoFileImageResize( ext, imgW, imgH ) { - var maxsize = ( G.library && ! G.librarylist ) ? 200 : ( ext === 'gif' ? 600 : 1000 ); + var maxsize = ( V.library && ! V.librarylist ) ? 200 : ( ext === 'gif' ? 600 : 1000 ); if ( imgW > maxsize || imgH > maxsize ) { var w = imgW > imgH ? maxsize : Math.round( imgW / imgH * maxsize ); var h = imgW > imgH ? Math.round( imgH / imgW * maxsize ) : maxsize; @@ -877,8 +868,8 @@ function loaderHide() { // ---------------------------------------------------------------------- function local( delay ) { - G.local = 1; - setTimeout( () => G.local = 0, delay || 300 ); + V.local = 1; + setTimeout( () => V.local = 0, delay || 300 ); } // ---------------------------------------------------------------------- @@ -905,12 +896,12 @@ $.fn.press = function( arg1, arg2 ) { } this.on( 'touchstart mousedown', delegate, function( e ) { timeout = setTimeout( () => { - G.press = 1; + V.press = 1; callback( e ); }, 1000 ); } ).on( 'touchend mouseup mouseleave', delegate, function( e ) { clearTimeout( timeout ); - setTimeout( () => G.press = 0, 300 ); // needed for mouse events + setTimeout( () => V.press = 0, 300 ); // needed for mouse events } ); return this // allow chain } @@ -927,36 +918,25 @@ if ( ! [ 'addons', 'addons-progress', 'guide' ].includes( page ) ) { } function pushstreamPower( message ) { var type = message.split( ' ' )[ 0 ].toLowerCase(); - G[ type ] = 1; - var ready = type === 'ready'; - if ( G.display.logout ) { - if ( ready ) location.reload(); - - $( 'body > div, pre' ).not( '#banner, #loader' ).remove(); - loader(); - } else { - if ( ready ) { - if ( page === 'system' ) getStatus(); - loaderHide(); - } else { - loader(); - } - } + V[ type ] = 1; + loader(); } pushstream.onstatuschange = status => { // 0 - disconnected; 1 - reconnect; 2 - connected if ( status === 2 ) { // connected - if ( G.reboot ) { - delete G.reboot; - banner( 'raudio', 'rAudio', 'Ready', 6000 ); + if ( V.reboot ) { + if ( S.login ) { + location.href = '/'; + return + } + + delete V.reboot; loaderHide(); - page === 'system' ? refreshData() : bash( [ 'autoplaystatus' ] ); - } else { - refreshData(); - bannerHide(); } + refreshData(); + bannerHide(); } else if ( status === 0 ) { // disconnected pushstreamDisconnect(); - if ( G.off ) { + if ( V.off ) { pushstream.disconnect(); $( '#loader' ).css( 'background', '#000000' ); setTimeout( () => { @@ -971,7 +951,7 @@ if ( ! [ 'addons', 'addons-progress', 'guide' ].includes( page ) ) { var active = 1; // fix: multiple firings var select2 = 0; // fix: closing > blur > disconnect function connect() { - if ( active || G.off ) return + if ( active || V.off ) return active = 1; pushstream.connect(); @@ -981,7 +961,6 @@ if ( ! [ 'addons', 'addons-progress', 'guide' ].includes( page ) ) { active = 0; pushstream.disconnect(); - console.log('disconnect') } document.onvisibilitychange = () => document.hidden ? disconnect() : connect(); window.onpagehide = disconnect; diff --git a/srv/http/assets/js/context.js b/srv/http/assets/js/context.js index 185a0a7d5..a18767ba1 100644 --- a/srv/http/assets/js/context.js +++ b/srv/http/assets/js/context.js @@ -1,17 +1,15 @@ function addReplace( cmd, command, title, msg ) { var play = cmd === 'addplay' || cmd === 'replaceplay'; if ( play || cmd === 'replace' ) $( '#stop' ).click(); - bash( command, () => { - if ( G.display.playbackswitch && play ) $( '#playback' ).click(); - } ); + bash( command ); banner( 'playlist', title, msg ); } function addSimilar() { banner( 'lastfm blink', 'Playlist - Add Similar', 'Fetch similar list ...', -1 ); var url = 'http://ws.audioscrobbler.com/2.0/?method=track.getsimilar' - +'&artist='+ encodeURI( G.list.artist ) - +'&track='+ encodeURI( G.list.name ) - +'&api_key='+ G.apikeylastfm + +'&artist='+ encodeURI( V.list.artist ) + +'&track='+ encodeURI( V.list.name ) + +'&api_key='+ V.apikeylastfm +'&format=json' +'&autocorrect=1'; $.post( url, function( data ) { @@ -38,18 +36,18 @@ function bookmarkNew() { // #1 - track list - show image from licover // #2 - dir list - show image from path + coverart.jpg // #3 - no cover - icon + directory name - if ( [ 'http', 'rtsp' ].includes( G.list.path.slice( 0, 4 ) ) ) { - var $img = G.list.li.find( '.iconthumb' ); + if ( [ 'http', 'rtsp' ].includes( V.list.path.slice( 0, 4 ) ) ) { + var $img = V.list.li.find( '.iconthumb' ); var src = $img.length ? $img.attr( 'src' ).replace( /-thumb.jpg\?v=.*$/, '.jpg' ) : ''; - var path = G.list.path; - var name = G.list.name; + var path = V.list.path; + var name = V.list.name; var msgpath = name; } else { - if ( G.mode.slice( -5 ) === 'radio' ) { - var path = G.mode +'/'+ G.list.path; + if ( V.mode.slice( -5 ) === 'radio' ) { + var path = V.mode +'/'+ V.list.path; var src = '/data/'+ path +'/coverart.jpg'; } else { - var path = G.list.path.slice( -4 ) === '.cue' ? dirName( path ) : G.list.path; + var path = V.list.path.slice( -4 ) === '.cue' ? dirName( path ) : V.list.path; var src = '/mnt/MPD/'+ path +'/coverart.jpg'; } var msgpath = path; @@ -100,14 +98,14 @@ function playlistDelete() { icon : 'file-playlist' , title : 'Delete Playlist' , message : 'Delete?' - +'
'+ G.list.name +'' + +'
'+ V.list.name +'' , oklabel : 'Delete' , okcolor : red - , ok : () => bash( [ 'savedpldelete', G.list.name ] ) + , ok : () => bash( [ 'savedpldelete', V.list.name ] ) } ); } function playlistLoad( path, play, replace ) { - G.local = 1; + V.local = 1; banner( 'file-playlist blink', 'Saved Playlist', 'Load ...', -1 ); list( { cmd : 'load' @@ -115,8 +113,8 @@ function playlistLoad( path, play, replace ) { , play : play , replace : replace }, function( data ) { - G.local = 0; - G.status.pllength = +data; + V.local = 0; + S.pllength = +data; banner( 'playlist', replace ? 'Playlist Replaced' : 'Playlist Added', 'Done' ); } ); } @@ -133,7 +131,7 @@ function playlistNew( name ) { } ); } function playlistRename() { - var name = G.list.name; + var name = V.list.name; info( { icon : 'file-playlist' , title : 'Rename Playlist' @@ -179,37 +177,38 @@ function playlistSaveExist( type, name, oldname ) { function tagEditor() { var name = [ 'Album', 'AlbumArtist', 'Artist', 'Composer', 'Conductor', 'Genre', 'Date', 'Title', 'Track' ]; var format = name.map( el => el.toLowerCase() ); - var file = G.list.path; + var file = V.list.path; + var dir = dirName( file ); var cue = file.slice( -4 ) === '.cue'; - if ( !G.playlist && G.list.licover ) format = format.slice( 0, -2 ); + if ( !V.playlist && V.list.licover ) format = format.slice( 0, -2 ); var query = { query : 'track' - , file : G.list.path + , file : V.list.path , format : format } list( query, function( values ) { name[ 1 ] = 'Album Artist'; var label = []; format.forEach( ( el, i ) => { - if ( G.playlist && ! values[ i ] ) { + if ( V.playlist && ! values[ i ] ) { delete values[ i ]; return } label.push( ''+ name[ i ] +' ' ); } ); - if ( G.library ) { - var $img = $( '.licover' ).length ? $( '.licoverimg img' ) : G.list.li.find( 'img' ); - var src = $img.length ? $img.attr( 'src' ) : G.coverdefault; + if ( V.library ) { + var $img = $( '.licover' ).length ? $( '.licoverimg img' ) : V.list.li.find( 'img' ); + var src = $img.length ? $img.attr( 'src' ) : V.coverdefault; } else { - var $img = G.list.li.find( 'img' ); - var src = $img.length ? $img.attr( 'src' ).replace( '/thumb.', '/coverart.' ) : G.coverdefault; + var $img = V.list.li.find( 'img' ); + var src = $img.length ? $img.attr( 'src' ).replace( '/thumb.', '/coverart.' ) : V.coverdefault; values = values.filter( val => val ); // reindex after deleting blank elements } var fileicon = cue ? 'file-music' : 'file-playlist'; var message = ''+ file +'' +'
'; - if ( G.list.licover ) { + if ( V.list.licover ) { message += ''+ file; } else { message += ''+ file +'
'+ file.split( '/' ).pop(); @@ -217,10 +216,10 @@ function tagEditor() { message += '
'; var footer = ''; footer += '
 Label
'; - if ( G.list.licover ) footer += '
*  Various values in tracks
'; + if ( V.list.licover ) footer += '
*  Various values in tracks
'; info( { - icon : G.playlist ? 'info-circle' : 'tag' - , title : G.playlist ? 'Track Info' : 'Tag Editor' + icon : V.playlist ? 'info-circle' : 'tag' + , title : V.playlist ? 'Track Info' : 'Tag Editor' , width : 500 , message : message , messagealign : 'left' @@ -234,7 +233,7 @@ function tagEditor() { $( '#infoContent .infomessage' ).addClass( 'tagmessage' ); $( '#infoContent .infofooter' ).addClass( 'tagfooter' ); $( '#infoContent td i' ).css( 'cursor', 'pointer' ); - if ( G.playlist ) $( '#infoContent input' ).prop( 'disabled', 1 ); + if ( V.playlist ) $( '#infoContent input' ).prop( 'disabled', 1 ); var tableW = $( '#infoContent table' ).width(); $( '#infoContent' ).on( 'click', '#taglabel', function() { if ( $( '.taglabel' ).hasClass( 'hide' ) ) { @@ -263,38 +262,39 @@ function tagEditor() { , modetitle : string , path : string } - G.mode = mode; + V.mode = mode; renderLibraryList( data ); query.gmode = mode; query.modetitle = string; tagModeSwitch(); - G.query.push( query ); + V.query.push( query ); } ); } ); $( '.infomessage' ).click( function() { - if ( G.library ) return + if ( V.library ) return var query = { query : 'ls' - , string : file + , string : V.library ? file : dir , format : [ 'file' ] } - if ( cue ) file = dirName( file ); + if ( cue ) file = dir; list( query, function( html ) { var data = { html : html , modetitle : file , path : file } - G.mode = file.split( '/' )[ 0 ].toLowerCase(); + V.mode = file.split( '/' )[ 0 ].toLowerCase(); tagModeSwitch(); renderLibraryList( data ); + switchPage( 'library' ); } ); } ); } - , okno : G.playlist - , ok : G.playlist ? '' : () => { - var tag = [ 'cmd-tageditor.sh', file, G.list.licover, cue ]; + , okno : V.playlist + , ok : V.playlist ? '' : () => { + var tag = [ 'cmd-tageditor.sh', file, V.list.licover, cue ]; var newvalues = infoVal(); var val; newvalues.forEach( ( v, i ) => { @@ -304,15 +304,15 @@ function tagEditor() { banner( 'tag blink', 'Tag Editor', 'Change tags ...', -1 ); setTimeout( () => banner( 'tag blink', 'Tag Editor', 'Update Library ...' ), 3000 ); $.post( 'cmd.php', { cmd: 'sh', sh: tag } ); - if ( G.list.licover ) { + if ( V.list.licover ) { var tags = [ 'album', 'albumartist', 'artist', 'composer', 'conductor', 'genre', 'date' ]; for ( i = 0; i < 7; i++ ) { var v = newvalues[ i ]; if ( v !== '*' ) $( '.li'+ tags[ i ] ).text( v ); } } else { - G.list.li.find( '.li1' ).text( newvalues[ 7 ] ); - G.list.li.find( '.track' ).text( newvalues[ 8 ] ); + V.list.li.find( '.li1' ).text( newvalues[ 7 ] ); + V.list.li.find( '.track' ).text( newvalues[ 8 ] ); } } } ); @@ -320,27 +320,27 @@ function tagEditor() { } function tagModeSwitch() { $( '#infoX' ).click(); - if ( G.playlist ) { + if ( V.playlist ) { $( '#page-playlist' ).addClass( 'hide' ); $( '#page-library' ).removeClass( 'hide' ); - G.playlist = 0; - G.library = 1; - G.page = 'library'; + V.playlist = 0; + V.library = 1; + V.page = 'library'; } } function webRadioCoverart() { - if ( G.playback ) { - var coverart = G.status.stationcover || G.coverdefault; - var type = G.status.icon === 'dabradio' ? 'dabradio' : 'webradio'; - var url = G.status.file; - var name = G.status.station; + if ( V.playback ) { + var coverart = S.stationcover || V.coverdefault; + var type = S.icon === 'dabradio' ? 'dabradio' : 'webradio'; + var url = S.file; + var name = S.station; } else { - var coverart = G.coverdefault; - var src = G.list.li.find( '.lib-icon' ).attr( 'src' ); - var type = G.mode; - var pathsplit = G.list.li.find( '.lipath' ).text().split( '//' ); + var coverart = V.coverdefault; + var src = V.list.li.find( '.lib-icon' ).attr( 'src' ); + var type = V.mode; + var pathsplit = V.list.li.find( '.lipath' ).text().split( '//' ); var url = pathsplit[ 0 ].replace( /.*\//, '' ) +'//'+ pathsplit[ 1 ]; - var name = G.list.name; + var name = V.list.name; } var imagefilenoext = '/srv/http/data/'+ type +'/img/'+ url.replace( /\//g, '|' ); $( '#coverart' ).removeAttr( 'style' ); @@ -354,7 +354,7 @@ function webRadioCoverart() { , fileoklabel : 'Replace' , filetype : 'image/*' , beforeshow : () => { - $( '.extrabtn' ).toggleClass( 'hide', coverart === G.coverdefault ); + $( '.extrabtn' ).toggleClass( 'hide', coverart === V.coverdefault ); if ( src ) { bash( [ 'coverartget', imagefilenoext, 'radio' ], coverart => { if ( coverart ) { @@ -371,12 +371,12 @@ function webRadioCoverart() { } ); } function webRadioDelete() { - var name = G.list.name; - var img = G.list.li.find( 'img' ).attr( 'src' ) || G.coverdefault; - var url = G.list.li.find( '.li2' ).text(); + var name = V.list.name; + var img = V.list.li.find( 'img' ).attr( 'src' ) || V.coverdefault; + var url = V.list.li.find( '.li2' ).text(); info( { - icon : G.mode - , title : 'Delete '+ ( G.mode === 'webradio' ? 'Web Radio' : 'DAB Radio' ) + icon : V.mode + , title : 'Delete '+ ( V.mode === 'webradio' ? 'Web Radio' : 'DAB Radio' ) , width : 500 , message : '
' +'
'+ name +'' @@ -384,9 +384,9 @@ function webRadioDelete() { , oklabel : 'Delete' , okcolor : red , ok : () => { - G.list.li.remove(); + V.list.li.remove(); var dir = $( '#lib-path .lipath' ).text(); - bash( ['webradiodelete', dir, url, G.mode ] ); + bash( ['webradiodelete', dir, url, V.mode ] ); } } ); } @@ -403,11 +403,11 @@ var htmlwebradio = `\ `; function webRadioEdit() { - var name = G.list.name; - var img = G.list.li.find( 'img' ).attr( 'src' ) || G.coverdefault; - var pathsplit = G.list.path.split( '//' ); + var name = V.list.name; + var img = V.list.li.find( 'img' ).attr( 'src' ) || V.coverdefault; + var pathsplit = V.list.path.split( '//' ); var url = pathsplit[ 0 ].replace( /.*\//, '' ) +'//'+ pathsplit[ 1 ]; - var charset = G.list.li.data( 'charset' ); + var charset = V.list.li.data( 'charset' ); info( { icon : 'webradio' , title : 'Edit Web Radio' @@ -484,7 +484,7 @@ function webRadioNew( name, url, charset ) { } ); } function webRadioSave( name ) { - var url = G.list.li.find( '.lipath' ).text(); + var url = V.list.li.find( '.lipath' ).text(); info( { icon : 'webradio' , title : 'Save Web Radio' @@ -494,7 +494,7 @@ function webRadioSave( name ) { , focus : 0 , checkblank : 1 , ok : () => { - G.local = 1; + V.local = 1; var newname = infoVal().toString().replace( /\/\s*$/, '' ); // omit trailling / and space bash( [ 'webradioadd', '', newname, url ], error => { if ( error ) { @@ -509,11 +509,11 @@ function webRadioSave( name ) { return } - G.list.li.find( '.liname, .radioname' ).text( newname ); - G.list.li.find( '.li2 .radioname' ).append( ' • ' ); - G.list.li.find( '.savewr' ).remove(); - G.list.li.removeClass( 'notsaved' ); - G.local = 0; + V.list.li.find( '.liname, .radioname' ).text( newname ); + V.list.li.find( '.li2 .radioname' ).append( ' • ' ); + V.list.li.find( '.savewr' ).remove(); + V.list.li.removeClass( 'notsaved' ); + V.local = 0; } ); } } ); @@ -527,11 +527,11 @@ $( '.contextmenu a, .contextmenu .submenu' ).click( function() { // playback ////////////////////////////////////////////////////////////// if ( [ 'play', 'pause', 'stop' ].includes( cmd ) ) { if ( cmd === 'play' ) { - if ( G.status.player !== 'mpd' ) { + if ( S.player !== 'mpd' ) { $( '#stop' ).click(); - G.status.player = 'mpd'; + S.player = 'mpd'; } - $( '#pl-list li' ).eq( G.list.li.index() ).click(); + $( '#pl-list li' ).eq( V.list.li.index() ).click(); } else { $( '#'+ cmd ).click(); } @@ -540,28 +540,28 @@ $( '.contextmenu a, .contextmenu .submenu' ).click( function() { switch ( cmd ) { case 'current': - bash( [ 'mpcsetcurrent', G.list.index + 1 ] ); + bash( [ 'mpcsetcurrent', V.list.index + 1 ] ); return case 'directory': - if ( G.mode === 'latest' ) { - var path = dirName( G.list.path ); + if ( V.mode === 'latest' ) { + var path = dirName( V.list.path ); var query = { query : 'ls' , string : path , format : [ 'file' ] } var modetitle = path; - query.gmode = G.mode; + query.gmode = V.mode; list( query, function( data ) { - G.mode = path.split( '/' )[ 0 ].toLowerCase(); - G.gmode = 'latest'; + V.mode = path.split( '/' )[ 0 ].toLowerCase(); + V.gmode = 'latest'; data.path = path; data.modetitle = modetitle; renderLibraryList( data ); }, 'json' ); query.path = path; query.modetitle = modetitle; - G.query.push( query ); + V.query.push( query ); } else { $( '#lib-list .liinfopath' ).click(); } @@ -571,36 +571,36 @@ $( '.contextmenu a, .contextmenu .submenu' ).click( function() { icon : 'folder-forbid' , title : 'Exclude Directory' , message : 'Exclude from Library:' - +'
'+ G.list.path +'' + +'
'+ V.list.path +'' , ok : () => { - bash( [ 'ignoredir', G.list.path ], () => G.list.li.remove() ); - var dir = G.list.path.split( '/' ).pop(); + bash( [ 'ignoredir', V.list.path ], () => V.list.li.remove() ); + var dir = V.list.path.split( '/' ).pop(); } } ); return case 'remove': - G.contextmenu = 1; - setTimeout( () => G.contextmenu = 0, 500 ); - playlistRemove( G.list.li ); + V.contextmenu = 1; + setTimeout( () => V.contextmenu = 0, 500 ); + playlistRemove( V.list.li ); return case 'savedpladd': - if ( G.playlist ) { - var album = G.list.li.find( '.album' ).text(); - var file = G.list.path; + if ( V.playlist ) { + var album = V.list.li.find( '.album' ).text(); + var file = V.list.path; } else { var album = $( '.licover .lialbum' ).text(); - var file = G.list.li.find( '.lipath' ).text(); + var file = V.list.li.find( '.lipath' ).text(); } - saveToPlaylist( G.list.name, album, file ); + saveToPlaylist( V.list.name, album, file ); return case 'savedplremove': local(); var plname = $( '#pl-path .lipath' ).text(); - bash( [ 'savedpledit', plname, 'remove', G.list.li.index() + 1 ] ); - G.list.li.remove(); + bash( [ 'savedpledit', plname, 'remove', V.list.li.index() + 1 ] ); + V.list.li.remove(); return case 'similar': - if ( G.display.plsimilar ) { + if ( D.plsimilar ) { info( { icon : 'lastfm' , title : 'Add Similar' @@ -619,25 +619,25 @@ $( '.contextmenu a, .contextmenu .submenu' ).click( function() { icon : iconcover , title : 'Album Thumbnails' , message : 'Update album thumbnails in:' - +'
'+ G.list.path +'' - , ok : () => thumbUpdate( G.list.path ) + +'
'+ V.list.path +'' + , ok : () => thumbUpdate( V.list.path ) } ); return case 'update': - if ( G.list.path.slice( -3 ) === 'cue' ) G.list.path = dirName( G.list.path ); - infoUpdate( G.list.path ); + if ( V.list.path.slice( -3 ) === 'cue' ) V.list.path = dirName( V.list.path ); + infoUpdate( V.list.path ); return case 'wrdirdelete': - var path = G.list.li.find( '.lipath' ).text(); + var path = V.list.li.find( '.lipath' ).text(); info( { - icon : G.mode + icon : V.mode , title : 'Delete Folder' , message : 'Folder:' +'
'+ path +'' , oklabel : 'Delete' , okcolor : red , ok : () => { - bash( [ 'wrdirdelete', path, G.mode ], std => { + bash( [ 'wrdirdelete', path, V.mode ], std => { if ( std == -1 ) { info( { icon : 'webradio' @@ -647,7 +647,7 @@ $( '.contextmenu a, .contextmenu .submenu' ).click( function() { +'
Confirm delete?' , oklabel : 'Delete' , okcolor : red - , ok : () => bash( [ 'wrdirdelete', path, G.mode, 'noconfirm' ] ) + , ok : () => bash( [ 'wrdirdelete', path, V.mode, 'noconfirm' ] ) } ); } } ); @@ -655,11 +655,11 @@ $( '.contextmenu a, .contextmenu .submenu' ).click( function() { } ); return case 'wrdirrename': - var path = G.list.li.find( '.lipath' ).text().split( '/' ); + var path = V.list.li.find( '.lipath' ).text().split( '/' ); var name = path.pop(); var path = path.join( '/' ); info( { - icon : G.mode + icon : V.mode , title : 'Rename Folder' , textlabel : 'Name' , focus : 0 @@ -667,7 +667,7 @@ $( '.contextmenu a, .contextmenu .submenu' ).click( function() { , checkblank : 1 , checkchange : 1 , oklabel : 'Rename' - , ok : () => bash( [ 'wrdirrename', path, name, infoVal(), G.mode ] ) + , ok : () => bash( [ 'wrdirrename', path, name, infoVal(), V.mode ] ) } ); return case 'wrsave': @@ -690,8 +690,8 @@ $( '.contextmenu a, .contextmenu .submenu' ).click( function() { } // replaceplay|replace|addplay|add ////////////////////////////////////////// - var path = G.list.path; - if ( G.mode.slice( -5 ) === 'radio' ) { + var path = V.list.path; + if ( V.mode.slice( -5 ) === 'radio' ) { var pathsplit = path.split( '//' ); path = pathsplit[ 0 ].replace( /.*\//, '' ) +'//'+ pathsplit[ 1 ]; } @@ -700,22 +700,22 @@ $( '.contextmenu a, .contextmenu .submenu' ).click( function() { var mode = cmd.replace( /replaceplay|replace|addplay|add/, '' ); switch ( mode ) { case '': - if ( G.list.singletrack || G.mode.slice( -5 ) === 'radio' ) { // single track + if ( V.list.singletrack || V.mode.slice( -5 ) === 'radio' ) { // single track mpccmd = [ 'mpcadd', path ]; } else if ( $( '.licover' ).length && ! $( '.licover .lipath' ).length ) { - mpccmd = [ 'mpcfindadd', 'multi', G.mode, path, 'album', G.list.album ]; + mpccmd = [ 'mpcfindadd', 'multi', V.mode, path, 'album', V.list.album ]; } else { // directory or album mpccmd = [ 'mpcls', path ]; } break; case 'pl': cmd = cmd.slice( 2 ); - if ( G.library ) { + if ( V.library ) { mpccmd = [ 'mpcload', path ]; } else { // saved playlist var play = cmd.slice( -1 ) === 'y' ? 1 : 0; var replace = cmd.slice( 0, 1 ) === 'r' ? 1 : 0; - if ( replace && G.display.plclear && G.status.pllength ) { + if ( replace && D.plclear && S.pllength ) { infoReplace( () => playlistLoad( path, play, replace ) ); } else { playlistLoad( path, play, replace ); @@ -728,21 +728,21 @@ $( '.contextmenu a, .contextmenu .submenu' ).click( function() { break case 'wr': cmd = cmd.slice( 2 ); - var charset = G.list.li.data( 'charset' ); + var charset = V.list.li.data( 'charset' ); if ( charset ) path += '#charset='+ charset mpccmd = [ 'mpcadd', path ]; break; default: - if ( ! G.list.name ) { + if ( ! V.list.name ) { mpccmd = [ 'mpcfindadd', mode, path ]; - if ( G.list.artist ) mpccmd.push( 'artist', G.list.artist ); + if ( V.list.artist ) mpccmd.push( 'artist', V.list.artist ); } else { - mpccmd = [ 'mpcfindadd', 'multi', G.mode, $( '#mode-title' ).text(), 'album', G.list.name ]; + mpccmd = [ 'mpcfindadd', 'multi', V.mode, $( '#mode-title' ).text(), 'album', V.list.name ]; } } if ( ! mpccmd ) mpccmd = []; - var sleep = G.mode.slice( -5 ) === 'radio' ? 1 : 0.2; - if ( G.status.state === 'play' && G.status.webradio ) sleep += 1; + var sleep = V.mode.slice( -5 ) === 'radio' ? 1 : 0.2; + if ( S.state === 'play' && S.webradio ) sleep += 1; var contextCommand = { add : mpccmd , playnext : mpccmd @@ -759,19 +759,19 @@ $( '.contextmenu a, .contextmenu .submenu' ).click( function() { } else if ( cmd === 'playnext' ) { var title = 'Add to Playlist to play next'; } else { - var title = 'Replace playlist'+ ( cmd === 'replace' ? '' : ' and play' ); + var title = 'Replace Playlist'+ ( cmd === 'replace' ? '' : ' and play' ); } - if ( G.list.li.hasClass( 'licover' ) ) { - var msg = G.list.li.find( '.lialbum' ).text() - +''+ G.list.li.find( '.liartist' ).text() +''; - } else if ( G.list.li.find( '.li1' ).length ) { - var msg = G.list.li.find( '.li1' )[ 0 ].outerHTML - + G.list.li.find( '.li2' )[ 0 ].outerHTML; + if ( V.list.li.hasClass( 'licover' ) ) { + var msg = V.list.li.find( '.lialbum' ).text() + +''+ V.list.li.find( '.liartist' ).text() +''; + } else if ( V.list.li.find( '.li1' ).length ) { + var msg = V.list.li.find( '.li1' )[ 0 ].outerHTML + + V.list.li.find( '.li2' )[ 0 ].outerHTML; msg = msg.replace( '', '' ).replace( '', '' ); } else { - var msg = G.list.li.find( '.lipath' ).text() || G.list.li.find( '.liname' ).text(); + var msg = V.list.li.find( '.lipath' ).text() || V.list.li.find( '.liname' ).text(); } - if ( G.display.plclear && ( cmd === 'replace' || cmd === 'replaceplay' ) ) { + if ( D.plclear && ( cmd === 'replace' || cmd === 'replaceplay' ) ) { infoReplace( () => addReplace( cmd, command, title, msg ) ); } else { addReplace( cmd, command, title, msg ); diff --git a/srv/http/assets/js/equalizer.js b/srv/http/assets/js/equalizer.js index ab2eb4217..07e9eafbb 100644 --- a/srv/http/assets/js/equalizer.js +++ b/srv/http/assets/js/equalizer.js @@ -1,3 +1,4 @@ +E = {} var freq = [ 31, 63, 125, 250, 500, 1, 2, 4, 8, 16 ]; var timeout; var band = []; @@ -21,14 +22,14 @@ var content = ` `; function equalizer() { bash( [ 'equalizerget' ], data => { - G.eq = data; + E = data; infoEqualizer(); }, 'json' ); } function infoEqualizer( update ) { - var values = [ '', G.eq.current, ...G.eq.values ]; // [ #eqname, #eqpreset, ... ] + var values = [ '', E.current, ...E.values ]; // [ #eqname, #eqpreset, ... ] var optpreset = ''; - G.eq.presets.forEach( name => optpreset += '' ); + E.presets.forEach( name => optpreset += '' ); info( { icon : 'equalizer' , title : 'Equalizer' @@ -70,9 +71,9 @@ function infoEqualizer( update ) { $( '#eqname' ).on( 'keyup paste cut', function( e ) { var val = $( this ).val().trim(); var blank = val === ''; - var exists = G.eq.presets.includes( val ); + var exists = E.presets.includes( val ); if ( $( '#eqrename' ).hasClass( 'hide' ) ) { - var changed = ! blank && ! exists && val !== G.eq.current; + var changed = ! blank && ! exists && val !== E.current; } else { // new var changed = ! blank && ! exists; } @@ -80,19 +81,19 @@ function infoEqualizer( update ) { $( '#eqsave' ).toggleClass( 'disabled', ! changed ); } ); $( '#eqdelete' ).click( function() { - bash( [ 'equalizer', 'delete', G.eq.current ] ); + bash( [ 'equalizer', 'delete', E.current ] ); $( '#eqcancel' ).click(); } ); $( '#eqrename' ).click( function() { $( '#eqrename, #eqdelete' ).toggleClass( 'hide' ); - $( '#eqname' ).val( G.eq.current ); + $( '#eqname' ).val( E.current ); $( '#eqnew' ).click(); } ); $( '#eqsave' ).click( function() { if ( $( '#eqrename' ).hasClass( 'hide' ) ) { - bash( [ 'equalizer', 'rename', G.eq.current, $( '#eqname' ).val() ] ); + bash( [ 'equalizer', 'rename', E.current, $( '#eqname' ).val() ] ); } else { - var name = $( '#eqname' ).hasClass( 'hide' ) ? G.eq.current : $( '#eqname' ).val(); + var name = $( '#eqname' ).hasClass( 'hide' ) ? E.current : $( '#eqname' ).val(); bash( [ 'equalizer', 'save', name ] ); } $( '#eqcancel' ).click(); @@ -105,7 +106,7 @@ function infoEqualizer( update ) { $( '#eqname' ).css( 'display', 'inline-block' ); $( '#eqrename' ).addClass( 'disabled' ); $( '#eqsave' ).addClass( 'disabled' ); - if ( G.eq.current !== 'Flat' && G.eq.current !== '(unnamed)' ) $( '#eqname' ).val( G.eq.current ) + if ( E.current !== 'Flat' && E.current !== '(unnamed)' ) $( '#eqname' ).val( E.current ) } ); $( '#eqcancel' ).click( function() { $( '#eqrename, #eqnew, #eq .select2-container' ).removeClass( 'hide' ); @@ -114,19 +115,19 @@ function infoEqualizer( update ) { eqButtonSet(); } ); $( '#equndo' ).click( function() { - bash( [ 'equalizer', 'preset', G.eq.current ] ); + bash( [ 'equalizer', 'preset', E.current ] ); } ); } , okno : 1 } ); } function eqButtonSet() { - var flat = G.eq.current === 'Flat'; - var unnamed = G.eq.current === '(unnamed)'; + var flat = E.current === 'Flat'; + var unnamed = E.current === '(unnamed)'; if ( flat || unnamed ) { var changed = false; } else { - var val = G.eq.nameval[ G.eq.current ].split( ' ' ) + var val = E.nameval[ E.current ].split( ' ' ) var vnew = infoVal().slice( 2 ); var changed = vnew.some( ( v, i ) => Math.abs( v - val[ i ] ) > 1 ); // fix: resolution not precise } diff --git a/srv/http/assets/js/features.js b/srv/http/assets/js/features.js index df3056f47..a44866fce 100644 --- a/srv/http/assets/js/features.js +++ b/srv/http/assets/js/features.js @@ -6,10 +6,10 @@ $( '#setting-spotifyd' ).click( function() { var icon = 'spotify'; var title = 'Spotify Client'; - if ( ! G.spotifyd && G.spotifytoken ) { + if ( ! S.spotifyd && S.spotifytoken ) { bash( [ 'spotifyd', true ] ); notify( icon, title, 'Enable ...' ); - } else if ( G.spotifytoken ) { + } else if ( S.spotifytoken ) { info( { icon : icon , title : title @@ -53,7 +53,7 @@ $( '#setting-spotifyd' ).click( function() { response_type : 'code' , client_id : id , scope : 'user-read-currently-playing user-read-playback-position' - , redirect_uri : G.spotifyredirect + , redirect_uri : S.spotifyredirect , state : window.location.hostname } window.location = 'https://accounts.spotify.com/authorize?'+ $.param( data ); @@ -79,9 +79,9 @@ $( '#setting-snapclient' ).click( function() { , textlabel : 'Latency (ms)' , focus : 0 , checkblank : 1 - , values : G.snapcastconf + , values : S.snapcastconf , boxwidth : 100 - , checkchanged : G.snapclient + , checkchanged : S.snapclient , beforeshow : () => { $( '#infoContent input' ).eq( 0 ).on( 'keyup paste cut', function() { $( this ).val( $( this ).val().replace( /[^0-9]/, '' ) ); @@ -90,7 +90,7 @@ $( '#setting-snapclient' ).click( function() { , cancel : () => cancelSwitch( 'snapclient' ) , ok : () => { bash( [ 'snapclient', true, infoVal() ] ); - notify( icon, title, G.snapclient ? 'Change ...' : 'Enable ...' ); + notify( icon, title, S.snapclient ? 'Change ...' : 'Enable ...' ); } } ); } ); @@ -101,12 +101,12 @@ $( '#setting-upmpdcli' ).click( function() { icon : icon , title : title , checkbox : [ 'Clear Playlist on start' ] - , values : [ G.upmpdcliownqueue ] - , checkchanged : G.upmpdcli + , values : [ S.upmpdcliownqueue ] + , checkchanged : S.upmpdcli , cancel : () => cancelSwitch( 'upmpdcli' ) , ok : () => { bash( [ 'upmpdcli', true, infoVal() ] ); - notify( icon, title, G.upmpdcli ? 'Change ...' : 'Enable ...' ); + notify( icon, title, S.upmpdcli ? 'Change ...' : 'Enable ...' ); } } ); } ); @@ -120,12 +120,12 @@ $( '#setting-camilladsp' ).click( function() { , focus : 0 , checkblank : 1 , boxwidth : 100 - , values : G.camillarefresh - , checkchanged : G.camilladsp + , values : S.camillarefresh + , checkchanged : S.camilladsp , cancel : () => cancelSwitch( 'camilladsp' ) , ok : () => { bash( [ 'camilladsp', true, infoVal() ] ); - notify( icon, title, G.camilladsp ? 'Change ...' : 'Enable ...' ); + notify( icon, title, S.camilladsp ? 'Change ...' : 'Enable ...' ); } } ); } ); @@ -137,8 +137,8 @@ $( '#setting-hostapd' ).click( function() { , title : title , footer : '(8 characters or more)' , textlabel : [ 'IP', 'Password' ] - , values : G.hostapdconf - , checkchanged : G.hostapd + , values : S.hostapdconf + , checkchanged : S.hostapd , checkblank : 1 , checklength : { 1: [ 8, 'min' ] } , cancel : () => cancelSwitch( 'hostapd' ) @@ -151,31 +151,31 @@ $( '#setting-hostapd' ).click( function() { var ip012 = ips.join( '.' ); var iprange = ip012 +'.'+ ( +ip3 + 1 ) +','+ ip012 +'.254,24h'; bash( [ 'hostapd', true, iprange, ip, pwd ] ); - notify( icon, title, G.hostapd ? 'Change ...' : 'Enable ...' ); + notify( icon, title, S.hostapd ? 'Change ...' : 'Enable ...' ); } } ); } ); $( '#setting-autoplay' ).click( function() { - var val = G.autoplayconf[ 0 ] || G.autoplayconf[ 1 ] || G.autoplayconf[ 2 ]; + var val = S.autoplayconf[ 0 ] || S.autoplayconf[ 1 ] || S.autoplayconf[ 2 ]; var icon = 'play'; var title = 'AutoPlay'; info( { icon : icon , title : title , checkbox : [ 'Bluetooth connected', 'Audio CD inserted', 'Power on / Reboot' ] - , values : val ? G.autoplayconf : [ false, false, true ] - , checkchanged : G.autoplay + , values : val ? S.autoplayconf : [ false, false, true ] + , checkchanged : S.autoplay , cancel : () => cancelSwitch( 'autoplay' ) , ok : () => { bash( [ 'autoplay', true, ...infoVal() ] ); - notify( icon, title, G.autoplay ? 'Change ...' : 'Enable ...' ); + notify( icon, title, S.autoplay ? 'Change ...' : 'Enable ...' ); } } ); } ); $( '#setting-localbrowser' ).click( function() { - var v = G.localbrowserconf; - var brightness = v.brightness ? '
Brightness

' : ''; - var content = ` + var val = S.localbrowserconf; + var htmlbrightness = val.brightness ? '
Brightness

' : ''; + var content = `
Rotation
-${ brightness } +${ htmlbrightness }
 Reload On/Off @@ -217,11 +217,11 @@ ${ brightness } , title : title , content : content , boxwidth : 110 - , values : [ v.rotate, v.zoom, v.cursor, v.screenoff, v.onwhileplay, v.brightness ] - , checkchanged : G.localbrowser + , values : [ val.rotate, val.zoom, val.cursor, val.screenoff, val.onwhileplay, val.brightness ] + , checkchanged : S.localbrowser , beforeshow : () => { - $( '#onwhileplay' ).prop( 'disabled', v.screenoff === 0 ); - $( '.btnbottom' ).toggleClass( 'hide', ! G.localbrowser ); + $( '#onwhileplay' ).prop( 'disabled', val.screenoff === 0 ); + $( '.btnbottom' ).toggleClass( 'hide', ! S.localbrowser ); $( '#infoContent' ).on( 'click', '.up, .dn', function() { var up = $( this ).hasClass( 'up' ); var zoom = +$( '#zoom' ).val(); @@ -243,7 +243,7 @@ ${ brightness } $( '.screenoff' ).click( function() { bash( [ 'screenofftoggle' ] ); } ); - if ( v.brightness ) { + if ( val.brightness ) { $( '#infoRange input' ).on( 'click input keyup', function() { bash( 'echo '+ $( this ).val() +' > /sys/class/backlight/rpi_backlight/brightness' ); } ).on( 'touchend mouseup keyup', function() { @@ -254,7 +254,7 @@ ${ brightness } , cancel : () => cancelSwitch( 'localbrowser' ) , ok : () => { bash( [ 'localbrowser', true, ...infoVal() ] ); - notify( icon, title, G.localbrowser ? 'Change ...' : 'Enable ...', ); + notify( icon, title, S.localbrowser ? 'Change ...' : 'Enable ...', ); } } ); } ); @@ -266,12 +266,12 @@ $( '#setting-smb' ).click( function() { , title : title , message : 'Write permission:' , checkbox : [ '/mnt/MPD/SD', '/mnt/MPD/USB' ] - , values : G.smbconf - , checkchanged : G.smb + , values : S.smbconf + , checkchanged : S.smb , cancel : () => cancelSwitch( 'smb' ) , ok : () => { bash( [ 'smb', true, ...infoVal() ] ); - notify( icon, title, G.smb ? 'Change ...' : 'Enable ...' ); + notify( icon, title, S.smb ? 'Change ...' : 'Enable ...' ); } } ); } ); @@ -285,12 +285,12 @@ $( '#setting-multiraudio' ).click( function() { +' '; var content = ' Name IP / URL ' + trhtml.replace( 'NUM', 1 ); - var dataL = G.multiraudioconf.length; + var dataL = S.multiraudioconf.length; if ( dataL ) { var iL = dataL / 2 - 1; for ( i = 0; i < iL; i++ ) content += trhtml; } else { - G.multiraudioconf = [ "rAudio", location.host ]; + S.multiraudioconf = [ "rAudio", location.host ]; } var icon = 'raudiobox'; var title = 'Multiple rAudios'; @@ -298,8 +298,8 @@ $( '#setting-multiraudio' ).click( function() { icon : icon , title : title , content : ''+ content +'
' - , values : G.multiraudioconf - , checkchanged : G.multiraudio + , values : S.multiraudioconf + , checkchanged : S.multiraudio , beforeshow : () => { if ( $( '#infoContent input' ).length === 2 ) { setTimeout( () => { @@ -320,7 +320,7 @@ $( '#setting-multiraudio' ).click( function() { I.inputs = $( '#infoContent input' ); var values = infoVal(); if ( typeof values === 'string' ) values = [ values ]; - $( '#infoOk' ).toggleClass( 'disabled', values.join( ',' ) === G.multiraudioconf.join( ',' ) ); + $( '#infoOk' ).toggleClass( 'disabled', values.join( ',' ) === S.multiraudioconf.join( ',' ) ); $( '.ipremove' ).toggleClass( 'hide', I.inputs.length === 2 ); } ); } @@ -328,7 +328,7 @@ $( '#setting-multiraudio' ).click( function() { , ok : () => { I.inputs = $( '#infoContent input' ); bash( [ 'multiraudio', true, ...infoVal() ] ); - notify( icon, title, G.multiraudio ? 'Change ...' : 'Enable ...' ); + notify( icon, title, S.multiraudio ? 'Change ...' : 'Enable ...' ); } } ); } ); @@ -365,18 +365,18 @@ $( '#setting-login' ).click( function() { info( { icon : icon , title : title - , message : ( G.login ? 'Change password:' : 'New setup:' ) - , passwordlabel : ( G.login ? [ 'Existing', 'New' ] : 'Password' ) + , message : ( S.login ? 'Change password:' : 'New setup:' ) + , passwordlabel : ( S.login ? [ 'Existing', 'New' ] : 'Password' ) , focus : 0 , checkblank : 1 , cancel : () => cancelSwitch( 'login' ) , ok : () => { var values = infoVal(); - notify( icon, title, G.login ? 'Change ...' : 'Enable...' ); + notify( icon, title, S.login ? 'Change ...' : 'Enable...' ); $.post( 'cmd.php', { cmd : 'login' , password : values[ 0 ] - , pwdnew : G.login ? values[ 1 ] : values + , pwdnew : S.login ? values[ 1 ] : values }, function( verified ) { if ( verified == -1 ) passwordWrong(); }, 'json' ); @@ -401,15 +401,15 @@ $( '#setting-scrobble' ).click( function() { , title : title , content : content , boxwidth : 170 - , values : G.scrobbleconf - , checkblank : G.scrobblekey ? '' : [ 0, 1 ] - , checkchanged : G.scrobble + , values : S.scrobbleconf + , checkblank : S.scrobblekey ? '' : [ 0, 1 ] + , checkchanged : S.scrobble , beforeshow : () => { var $user = $( '#infoContent input[type=text]' ); var $pwd = $( '#infoContent input[type=password]' ).parents( 'tr' ) - $user.prop( 'disabled', G.scrobblekey ); - $pwd.toggleClass( 'hide', G.scrobblekey ); - $( '.scrobbleuser' ).toggleClass( 'hide', ! G.scrobblekey ) + $user.prop( 'disabled', S.scrobblekey ); + $pwd.toggleClass( 'hide', S.scrobblekey ); + $( '.scrobbleuser' ).toggleClass( 'hide', ! S.scrobblekey ) $( '.scrobbleuser' ).click( function() { $( this ).remove(); $user.prop( 'disabled', false ); @@ -432,7 +432,7 @@ $( '#setting-scrobble' ).click( function() { $( '#scrobble' ).prop( 'checked', 0 ); } }, 'json' ); - notify( icon, title, G.scrobble ? 'Change ...' : 'Enable ...' ); + notify( icon, title, S.scrobble ? 'Change ...' : 'Enable ...' ); } } ); } ); @@ -446,7 +446,7 @@ $( '#nfsserver' ).click( function() { , title : title , message : $this.prev().html() } ); - $this.prop( 'checked', G.nfsserver ); + $this.prop( 'checked', S.nfsserver ); return } @@ -454,14 +454,14 @@ $( '#nfsserver' ).click( function() { info( { icon : icon , title : title - , message : ( G.nfsserver ? 'Shared directories:' : 'Directories to share:' ) + , message : ( S.nfsserver ? 'Shared directories:' : 'Directories to share:' ) +'

'+ list +'

' - + ( G.nfsserver ? 'Disable all shares?' : 'Continue?' ) + + ( S.nfsserver ? 'Disable all shares?' : 'Continue?' ) , cancel : () => cancelSwitch( 'nfsserver' ) - , okcolor : G.nfsserver ? orange : '' + , okcolor : S.nfsserver ? orange : '' , ok : () => { - bash( [ 'nfsserver', ! G.nfsserver ] ); - notify( icon, title, G.nfsserver ? 'Disable ...' : 'Enable ...' ); + bash( [ 'nfsserver', ! S.nfsserver ] ); + notify( icon, title, S.nfsserver ? 'Disable ...' : 'Enable ...' ); } } ); } ); @@ -474,11 +474,11 @@ $( '#setting-stoptimer' ).click( function() { , title : title , radio : { Disable: 'false', '15 minutes': 15, '30 minutes': 30, '60 minutes': 60 } , checkbox : [ 'Power off on stop' ] - , values : G.stoptimerconf || [ false, false ] - , checkchanged : G.stoptimer + , values : S.stoptimerconf || [ false, false ] + , checkchanged : S.stoptimer , beforeshow : () => { var $poweroff = $( '#infoContent input:checkbox' ); - $poweroff.prop( 'disabled', ! G.stoptimerconf[ 1 ] ); + $poweroff.prop( 'disabled', ! S.stoptimerconf[ 1 ] ); $( '#infoContent tr:last' ).css( 'height', '60px' ); $( '#infoContent input:radio' ).change( function() { var valfalse = $( this ).val() === 'false'; @@ -489,7 +489,7 @@ $( '#setting-stoptimer' ).click( function() { , cancel : () => cancelSwitch( 'stoptimer' ) , ok : () => { bash( [ 'stoptimer', true, ...infoVal() ] ); - notify( icon, title, G.stoptimer ? 'Change ...' : 'Enable ...' ); + notify( icon, title, S.stoptimer ? 'Change ...' : 'Enable ...' ); } } ); } ); @@ -503,27 +503,27 @@ function passwordWrong() { , title : 'Password Login' , message : 'Wrong existing password.' } ); - $( '#login' ).prop( 'checked', G.login ); + $( '#login' ).prop( 'checked', S.login ); } function renderPage() { - $( '#shairport-sync' ).toggleClass( 'disabled', G.shairportactive ); - $( '#dabradio' ).toggleClass( 'disabled', ! G.dabdevice ); - $( '#snapclient' ).parent().prev().toggleClass( 'single', ! G.snapclientactive ); - $( '#snapclient' ).toggleClass( 'disabled', G.snapclientactive ); - $( '#snapserver' ).toggleClass( 'disabled', G.snapserveractive ); - $( '#spotifyd' ).toggleClass( 'disabled', G.spotifydactive ); - $( '#redirecturi' ).text( G.spotifyredirect ); - $( '#upmpdcli' ).toggleClass( 'disabled', G.upmpdcliactive ); - $( '#hostapd' ).toggleClass( 'disabled', G.wlanconnected ); - $( '#smb' ).toggleClass( 'disabled', G.nfsserver ); - $( '#nfsserver' ).toggleClass( 'disabled', G.smb || G.shareddata || G.nfsconnected ); - $( '#stoptimer' ).toggleClass( 'disabled', G.state !== 'play' ); - if ( G.nosound ) { + $( '#shairport-sync' ).toggleClass( 'disabled', S.shairportactive ); + $( '#dabradio' ).toggleClass( 'disabled', ! S.dabdevice ); + $( '#snapclient' ).parent().prev().toggleClass( 'single', ! S.snapclientactive ); + $( '#snapclient' ).toggleClass( 'disabled', S.snapclientactive ); + $( '#snapserver' ).toggleClass( 'disabled', S.snapserveractive ); + $( '#spotifyd' ).toggleClass( 'disabled', S.spotifydactive ); + $( '#redirecturi' ).text( S.spotifyredirect ); + $( '#upmpdcli' ).toggleClass( 'disabled', S.upmpdcliactive ); + $( '#hostapd' ).toggleClass( 'disabled', S.wlanconnected ); + $( '#smb' ).toggleClass( 'disabled', S.nfsserver ); + $( '#nfsserver' ).toggleClass( 'disabled', S.smb || S.shareddata || S.nfsconnected ); + $( '#stoptimer' ).toggleClass( 'disabled', S.state !== 'play' ); + if ( S.nosound ) { $( '#divdsp' ).addClass( 'hide' ); } else { $( '#divdsp' ).removeClass( 'hide' ); - $( '#camilladsp' ).toggleClass( 'disabled', G.bluetoothsink || G.equalizer ); - $( '#equalizer' ).toggleClass( 'disabled', G.camilladsp ); + $( '#camilladsp' ).toggleClass( 'disabled', S.bluetoothsink || S.equalizer ); + $( '#equalizer' ).toggleClass( 'disabled', S.camilladsp ); } if ( ! /code|error/.test( window.location.href ) ) { showContent(); diff --git a/srv/http/assets/js/function.js b/srv/http/assets/js/function.js index fb689befd..f523f1fc4 100644 --- a/srv/http/assets/js/function.js +++ b/srv/http/assets/js/function.js @@ -22,13 +22,13 @@ function list( args, callback, json ) { //---------------------------------------------------------------------- function blinkDot() { - if ( ! G.localhost ) return + if ( ! V.localhost ) return $( '.dot' ).css( 'animation', 'none' ); var $d1 = $( '.dot1' ); var $d2 = $( '.dot2' ); var $d3 = $( '.dot3' ); - G.intBlinkDot = setInterval( () => { + V.intBlinkDot = setInterval( () => { $d1.css( 'opacity', 1 ); $d2.css( 'opacity', 0.1 ); $d3.css( 'opacity', 0.50 ); @@ -47,11 +47,21 @@ function blinkDot() { function blinkUpdate() { var $icons = $( '#library, #button-library, #i-libupdate, #ti-libupdate' ); $icons.removeClass( 'blink' ); - G.intBlinkUpdate = setInterval( () => { + V.intBlinkUpdate = setInterval( () => { $icons.addClass( 'clear' ); setTimeout( () => $icons.removeClass( 'clear' ), 1500 ); }, 2500 ); } +function bookmarkRadioAddPlaylist( action, path, name ) { + var delay = 1; + if ( action === 'add' ) { + addReplace( action, [ 'mpcadd', path ], 'Add to Playlist', name ) + } else if ( action === 'addplay' ) { + addReplace( action, [ 'mpcadd', path, action, delay ], 'Add to Playlist and play', name ); + } else if ( action === 'replaceplay' ) { + addReplace( action, [ 'mpcadd', path, action, delay ], 'Replace Playlist and play', name ); + } +} function changeIP() { // for android app info( { icon : 'networks' @@ -86,19 +96,19 @@ function changeIP() { // for android app function clearIntervalAll() { // .btn-cmd[play], #time[start change], #time-band[touchstart mousedown], #pl-list li, // psNotify, pushstream[disconnect], renderPlayback, setProgressElapsed, setPlaylistScroll, switchPage - [ G.intBlinkDot, G.intBlinkUpdate, G.intElapsedPl, G.intElapsed, G.intRelaysTimer, G.intVu ].forEach( el => clearInterval( el ) ); - if ( G.status.state === 'play' && ! G.status.stream ) setProgress(); // stop progress animation + [ V.intBlinkDot, V.intBlinkUpdate, V.intElapsedPl, V.intElapsed, V.intRelaysTimer, V.intVu ].forEach( el => clearInterval( el ) ); + if ( S.state === 'play' && ! S.stream ) setProgress(); // stop progress animation $( '#vuneedle' ).css( 'transform', '' ); } function colorSet() { - G.color = 0; + V.color = 0; var rgb0 = $( '#colorcancel' ).css( 'color' ).replace( /rgb\(|,|\)/g, '' ); // rgb(aaa, bb, cc) > aaa bb cc $( '#lib-list .lib-icon' ).eq( 0 ).click(); - $( '.licover' ).toggleClass( 'hide', G.wH < 590 ); + $( '.licover' ).toggleClass( 'hide', V.wH < 590 ); $( '#colorreset' ) - .toggleClass( 'hide', G.display.color === '' ) + .toggleClass( 'hide', D.color === '' ) .before( '' ); - G.colorpicker = new KellyColorPicker( { + V.colorpicker = new KellyColorPicker( { place : 'canvascolor' , size : 230 , color : $( '#button-library' ).css( 'background-color' ) @@ -131,47 +141,47 @@ function colorSet() { function contextmenuLibrary( $li, $target ) { menuHide(); var $menu = $( $li.find( '.lib-icon' ).data( 'target' ) ); - G.list = {}; - G.list.li = $li; // for contextmenu - G.list.licover = $li.hasClass( 'licover' ); - G.list.singletrack = ! G.list.licover && $li.find( '.lib-icon' ).hasClass( 'fa-music' ); + V.list = {}; + V.list.li = $li; // for contextmenu + V.list.licover = $li.hasClass( 'licover' ); + V.list.singletrack = ! V.list.licover && $li.find( '.lib-icon' ).hasClass( 'fa-music' ); // file modes - path > path ... > tracks // album mode - path > tracks // other modes - name > name-album > filtered tracks - G.list.path = $li.find( '.lipath' ).text() || $( '#mode-title' ).text(); - if ( G.playlist ) { - G.list.name = $li.find( '.liname' ).text() || ''; - G.list.artist = $li.find( '.liartist' ).text() || ''; + V.list.path = $li.find( '.lipath' ).text() || $( '#mode-title' ).text(); + if ( V.playlist ) { + V.list.name = $li.find( '.liname' ).text() || ''; + V.list.artist = $li.find( '.liartist' ).text() || ''; } else if ( $( '.licover' ).length && ! $li.hasClass( 'licover' ) ) { - G.list.name = $li.find( '.li1' ).html().replace( / 767 ) && G.display.fixedcover ? true : false; + var fixedmenu = V.library && ( V.list.licover && V.wH > 767 ) && D.fixedcover ? true : false; $menu .css( 'top', menutop ) .toggleClass( 'fixed', fixedmenu ) @@ -187,14 +197,14 @@ function contextmenuScroll( $menu, menutop ) { var targetB = $menu.offset().top + $menu.height(); var topH = $bartop.is( ':visible' ) ? 80 : 40; var wT = $( window ).scrollTop(); - if ( targetB > ( G.wH - topH + wT ) ) $( 'html, body' ).animate( { scrollTop: targetB - G.wH + 42 } ); + if ( targetB > ( V.wH - topH + wT ) ) $( 'html, body' ).animate( { scrollTop: targetB - V.wH + 42 } ); } function coverartChange() { - if ( G.playback ) { + if ( V.playback ) { var src = $( '#coverart' ).attr( 'src' ); - var path = dirName( G.status.file ); - var album = G.status.Album; - var artist = G.status.Artist; + var path = dirName( S.file ); + var album = S.Album; + var artist = S.Artist; } else { var src = $( '#liimg' ).attr( 'src' ); var path = $( '.licover .lipath' ).text(); @@ -202,24 +212,24 @@ function coverartChange() { var album = $( '.licover .lialbum' ).text(); var artist = $( '.licover .liartist' ).text(); } - if ( 'discid' in G.status ) { - var imagefilenoext = '/srv/http/data/audiocd/'+ G.status.discid; + if ( 'discid' in S ) { + var imagefilenoext = '/srv/http/data/audiocd/'+ S.discid; var type = 'audiocd'; } else { var imagefilenoext = '/mnt/MPD/'+ path +'/cover'; var type = 'coverart'; } - if ( G.playback ) { + if ( V.playback ) { var pbonlinefetched = $( '#divcover .cover-save' ).length; - var pbcoverdefault = $( '#coverart' ).attr( 'src' ) === G.coverdefault; + var pbcoverdefault = $( '#coverart' ).attr( 'src' ) === V.coverdefault; var embedded = $( '#coverart' ).attr( 'src' ).split( '/' )[ 3 ] === 'embedded' ? '(Embedded)' : ''; } else { var lionlinefetched = $( '.licover .cover-save' ).length; - var licoverdefault = $( '.licoverimg img' ).attr( 'src' ) === G.coverdefault; + var licoverdefault = $( '.licoverimg img' ).attr( 'src' ) === V.coverdefault; var embedded = $( '.licoverimg img' ).attr( 'src' ).split( '/' )[ 3 ] === 'embedded' ? '(Embedded)' : ''; } - var coverartlocal = ( G.playback && ! embedded && ! pbonlinefetched && ! pbcoverdefault ) - || ( G.library && ! embedded && ! lionlinefetched && ! licoverdefault ) + var coverartlocal = ( V.playback && ! embedded && ! pbonlinefetched && ! pbcoverdefault ) + || ( V.library && ! embedded && ! lionlinefetched && ! licoverdefault ) && $( '#liimg' ).attr( 'src' ).slice( 0, 7 ) !== '/assets'; $( '#coverart, #liimg' ).removeAttr( 'style' ); $( '.coveredit' ).remove(); @@ -249,19 +259,19 @@ function coverartChange() { } ); } function coverartDefault() { - if ( G.display.vumeter ) return + if ( D.vumeter ) return var hash = versionHash(); - if ( ! G.display.covervu ) { + if ( ! D.covervu ) { $( '#coverart' ) - .attr( 'src', G.coverdefault + hash ) - .css( 'border', G.coverdefault === G.coverart ? 'none' : '' ) + .attr( 'src', V.coverdefault + hash ) + .css( 'border', V.coverdefault === V.coverart ? 'none' : '' ) .removeClass( 'hide' ); $( '#vu' ).addClass( 'hide' ); } else { $( '#coverart' ) .addClass( 'hide' ) - .attr( 'src', G.coverdefault + hash ); + .attr( 'src', V.coverdefault + hash ); $( '#vu' ).removeClass( 'hide' ); vu(); } @@ -269,12 +279,12 @@ function coverartDefault() { $( '#coverart' ).css( 'opacity', '' ); } function coverartSave() { - if ( G.playback ) { + if ( V.playback ) { var src = $( '#coverart' ).attr( 'src' ); - var file = G.status.file; + var file = S.file; var path = '/mnt/MPD/'+ dirName( file ); - var artist = G.status.Artist; - var album = G.status.Album; + var artist = S.Artist; + var album = S.Album; } else { var src = $( '.licover img' ).attr( 'src' ); var path = '/mnt/MPD/'+ $( '.licover .lipath' ).text(); @@ -333,9 +343,9 @@ function dirName( path ) { function displayBars() { if ( ! $( '#bio' ).hasClass( 'hide' ) ) return - var smallscreen = G.wH < 590 || G.wW < 500; - var lcd = ( G.wH <= 320 && G.wW <= 480 ) || ( G.wH <= 480 && G.wW <= 320 ); - if ( ! G.display.bars || ( smallscreen && ! G.display.barsalways ) || lcd ) { + var smallscreen = V.wH < 590 || V.wW < 500; + var lcd = ( V.wH <= 320 && V.wW <= 480 ) || ( V.wH <= 480 && V.wW <= 320 ); + if ( ! D.bars || ( smallscreen && ! D.barsalways ) || lcd ) { $( '#bar-top' ).addClass( 'hide' ); $( '#bar-bottom' ).addClass( 'transparent' ); $( '.page' ).addClass ( 'barshidden' ); @@ -349,7 +359,7 @@ function displayBars() { $( '.page' ).removeClass ( 'barshidden' ); $( '#page-playback, .emptyadd' ).addClass( 'barsalways' ); $( '.list, #lib-index, #pl-index' ).removeClass( 'bars-off' ); - $( '.content-top' ).css( 'top', G.display.bars || G.display.barsalways ? '' : 0 ); + $( '.content-top' ).css( 'top', D.bars || D.barsalways ? '' : 0 ); $( '.emptyadd' ).css( 'top', '' ); } displayBottom(); @@ -357,19 +367,19 @@ function displayBars() { function displayBottom() { $( '#playback' ) .removeAttr( 'class' ) - .addClass( 'fa fa-'+ G.status.player ); + .addClass( 'fa fa-'+ S.player ); $( '#bar-bottom i' ).removeClass( 'active' ); - $( '#'+ G.page ).addClass( 'active' ); + $( '#'+ V.page ).addClass( 'active' ); } function displayPlayback() { var $cover = $( '#coverart-block' ); - $time.toggleClass( 'hide', ! G.display.time ); - $volume.toggleClass( 'hide', ! G.display.volume || G.display.volumenone ); + $time.toggleClass( 'hide', ! D.time ); + $volume.toggleClass( 'hide', ! D.volume || D.volumenone ); var time = $time.is( ':visible' ); - var cover = G.display.cover; + var cover = D.cover; var volume = $volume.is( ':visible' ); $cover.toggleClass( 'hide', ! cover ); - if ( ( ! time || ! volume ) && G.wW > 500 ) { + if ( ( ! time || ! volume ) && V.wW > 500 ) { $( '#time-knob, #volume-knob' ).css( 'width', '38%' ); if ( ! time && ! volume ) { $cover.css( { width: '100%', 'max-width': '100%' } ); @@ -380,38 +390,36 @@ function displayPlayback() { $( '#time-knob, #volume-knob' ).css( 'width', '' ); $cover.css( { width: '', 'max-width': '' } ); } - if ( time ) $( '#time' ).roundSlider( G.status.stream || G.status.player !== 'mpd' || ! G.status.pllength ? 'disable' : 'enable' ); + if ( time ) $( '#time' ).roundSlider( S.stream || S.player !== 'mpd' || ! S.pllength ? 'disable' : 'enable' ); $( '#progress, #time-bar, #time-band' ).toggleClass( 'hide', time ); - $( '#time-band' ).toggleClass( 'disabled', ! G.status.pllength || G.status.player !== 'mpd' || G.status.stream ); - $( '#time-knob, #coverBL, #coverBR' ).toggleClass( 'disabled', G.status.stream || ! [ 'mpd', 'upnp' ].includes( G.status.player ) ); - $( '.volumeband' ).toggleClass( 'hide', G.display.volumenone || volume ); - $( '#timemap' ).toggleClass( 'hide', G.display.cover ); - $( '#play-group, #vol-group' ).toggleClass( 'hide', ! G.display.buttons ); + $( '#time-band' ).toggleClass( 'disabled', ! S.pllength || S.player !== 'mpd' || S.stream ); + $( '#time-knob, #coverBL, #coverBR' ).toggleClass( 'disabled', S.stream || ! [ 'mpd', 'upnp' ].includes( S.player ) ); + $( '.volumeband' ).toggleClass( 'hide', D.volumenone || volume ); + $( '#timemap' ).toggleClass( 'hide', D.cover ); + $( '#play-group, #vol-group' ).toggleClass( 'hide', ! D.buttons ); } function displaySave( keys ) { var values = infoVal(); - var display = JSON.parse( JSON.stringify( G.display ) ); + var display = JSON.parse( JSON.stringify( D ) ); keys.forEach( ( k, i ) => display[ k ] = values[ i ] ); - [ 'audiocd', 'color', 'equalizer', 'logout', 'order', - 'relays', 'screenoff', 'snapclient', 'volumenone' ].forEach( item => delete display[ item ] ); + [ 'audiocd', 'color', 'equalizer', 'logout', 'order', 'relays', 'screenoff', 'snapclient', 'volumenone' ].forEach( item => delete display[ item ] ); bash( [ 'displaysave', JSON.stringify( display ) ] ); } function displaySubMenu() { - if ( G.display.equalizer && typeof infoEqualizer !== 'function' ) { + if ( D.equalizer && typeof infoEqualizer !== 'function' ) { location.reload(); return } $( '#dsp' ) - .toggleClass( 'fa-camilladsp', G.display.camilladsp ) - .toggleClass( 'fa-equalizer', G.display.equalizer ); - G.display.dsp = G.display.camilladsp || G.display.equalizer; - var submenu = [ 'dsp', 'logout', 'relays', 'snapclient', 'multiraudio' ]; - submenu.forEach( el => $( '#'+ el ).prev().toggleClass( 'sub', G.display[ el ] ) ); // submenu toggled by css .settings + .submenu - if ( G.localhost ) $( '#power' ).addClass( 'sub' ); + .toggleClass( 'fa-camilladsp', D.camilladsp ) + .toggleClass( 'fa-equalizer', D.equalizer ); + D.dsp = D.camilladsp || D.equalizer; + [ 'dsp', 'logout', 'relays', 'snapclient', 'multiraudio' ].forEach( el => $( '#'+ el ).prev().toggleClass( 'sub', D[ el ] ) ); // submenu toggled by css .settings + .submenu + if ( V.localhost ) $( '#power' ).addClass( 'sub' ); } function getBio( artist, getsimilar ) { - G.bioartist.push( artist ); + V.bioartist.push( artist ); if ( artist === $( '#biocontent .name' ).text() ) { $( '#bio' ).removeClass( 'hide' ); return @@ -422,7 +430,7 @@ function getBio( artist, getsimilar ) { +'?autocorrect=1' +'&format=json' +'&method=artist.getinfo' - +'&api_key='+ G.apikeylastfm + +'&api_key='+ V.apikeylastfm +'&artist='+ encodeURI( artist.replace( '&', 'and' ) ); $.post( url, function( data ) { if ( 'error' in data || ( ! data.artist.bio.content ) ) { @@ -464,7 +472,7 @@ function getBio( artist, getsimilar ) {
`; $( '#bio' ).html( biohtml ).promise().done( () => { $( '#bio' ).removeClass( 'hide' ); - $.get( 'https://webservice.fanart.tv/v3/music/'+ data.mbid +'?api_key='+ G.apikeyfanart ).done( data => { + $.get( 'https://webservice.fanart.tv/v3/music/'+ data.mbid +'?api_key='+ V.apikeyfanart ).done( data => { if ( 'error message' in data ) { loaderHide(); return @@ -532,17 +540,18 @@ function getPlaybackStatus( withdisplay ) { return false } - G.counts = status.counts; + C = status.counts; delete status.counts; if ( 'display' in status ) { - G.display = status.display; - G.coverdefault = ! G.display.covervu && ! G.display.vumeter ? G.coverart : G.covervu; + D = status.display; + D.logout = status.login; + V.coverdefault = ! D.covervu && ! D.vumeter ? V.coverart : V.covervu; delete status.display; - delete G.coverTL; + delete V.coverTL; displaySubMenu(); bannerHide(); } - $.each( status, ( k, v ) => { G.status[ k ] = v } ); // need braces + $.each( status, ( k, v ) => { S[ k ] = v } ); // need braces var dataerror = $( '#data .copy' ).length; if ( $( '#data' ).hasClass( 'hide' ) || dataerror ) { if ( dataerror ) { @@ -555,7 +564,7 @@ function getPlaybackStatus( withdisplay ) { setButtonControl(); setButtonUpdating(); } else { - $( '#data' ).html( highlightJSON( G.status ) ) + $( '#data' ).html( highlightJSON( S ) ) $( '#button-data, #data' ).removeClass( 'hide' ); } } ); @@ -564,10 +573,10 @@ function getPlaylist() { list( { cmd: 'current' }, ( data ) => renderPlaylist( data ), 'json' ); } function hideGuide() { - if ( G.guide ) { - G.guide = 0; + if ( V.guide ) { + V.guide = 0; var barvisible = $bartop.is( ':visible' ); - $( '#coverTR' ).toggleClass( 'empty', ! G.status.pllength && ! barvisible && G.status.player === 'mpd' ); + $( '#coverTR' ).toggleClass( 'empty', ! S.pllength && ! barvisible && S.player === 'mpd' ); $( '.map' ).removeClass( 'mapshow' ); $( '#bar-bottom' ).removeClass( 'translucent' ); if ( ! barvisible ) $( '#bar-bottom' ).addClass( 'transparent' ); @@ -587,7 +596,7 @@ function imageLoad( list ) { if ( ! $lazyload.length ) return if ( list === 'lib-list' ) { - if ( G.mode === 'album' || G.mode === 'latest' ) { + if ( V.mode === 'album' || V.mode === 'latest' ) { $lazyload.off( 'error' ).on( 'error', function() { imageOnError( this ); } ); @@ -595,16 +604,16 @@ function imageLoad( list ) { $lazyload.off( 'error' ).on( 'error', function() { var $this = $( this ); var src = $this.attr( 'src' ); - if ( G.mode.slice( -5 ) === 'radio' ) { + if ( V.mode.slice( -5 ) === 'radio' ) { if ( $this.parent().hasClass( 'dir' ) ) { var icon = 'folder'; var menu = 'wrdir'; } else { - var icon = G.mode; + var icon = V.mode; var menu = 'webradio'; } } else { - var icon = $this.parent().data( 'index' ) !== 'undefined' ? 'folder' : G.mode; + var icon = $this.parent().data( 'index' ) !== 'undefined' ? 'folder' : V.mode; var menu = 'folder'; } $this.replaceWith( '' ); @@ -623,7 +632,7 @@ function imageOnError( el, bookmark ) { if ( src.slice( -16, -13 ) === 'jpg' ) { $this.attr( 'src', src.replace( 'jpg?v=', 'gif?v=' ) ); } else if ( ! bookmark ) { - $this.attr( 'src', G.coverart ); + $this.attr( 'src', V.coverart ); } else { // bookmark var icon = ''; if ( I.infohide ) icon += '
'+ bookmark +''; @@ -684,7 +693,7 @@ function infoLibrary( page ) { var keys = Object.keys( page2 ? chklibrary2 : chklibrary ); keys = keys.filter( k => k !== '-' ); var values = []; - keys.forEach( k => values.push( G.display[ k ] ) ); + keys.forEach( k => values.push( D[ k ] ) ); info( { icon : 'library' , title : 'Library' @@ -716,16 +725,16 @@ function infoLibrary( page ) { .prop( 'checked', 0 ) .parent().toggleClass( 'gr', ! enable ); } ); - $el.fixedcover.prop( 'disabled', G.display.hidecover ); + $el.fixedcover.prop( 'disabled', D.hidecover ); } else { - $el.sd.add( $el.usb ).prop( 'disabled', G.status.shareddata ); + $el.sd.add( $el.usb ).prop( 'disabled', S.shareddata ); } } , ok : () => displaySave( keys ) } ); } function infoUpdate( path ) { - if ( G.status.updating_db ) { + if ( S.updating_db ) { info( { icon : 'refresh-library' , title : 'Library Database' @@ -740,7 +749,7 @@ function infoUpdate( path ) { , message : path ? ' '+ path +'' : '' , radio : path ? '' : { 'Only changed files' : '', 'Rebuild entire database': 'rescan' } , beforeshow : () => { - if ( ! G.counts ) { + if ( ! C ) { $( '#infoContent input' ).eq( 0 ).prop( 'disabled', 1 ); $( '#infoContent input' ).eq( 1 ).prop( 'checked', 1 ); } @@ -750,37 +759,37 @@ function infoUpdate( path ) { } function libraryHome() { $.post( 'mpdlibrary.php', { query: 'home' }, function( data ) { - G.counts = data.counts; - G.display.order = data.order; + C = data.counts; + O = data.order; var html = data.html - if ( html !== G.libraryhtml ) { - G.libraryhtml = html; + if ( html !== V.libraryhtml ) { + V.libraryhtml = html; var hash = versionHash(); var html = html.replaceAll( '^^^', hash ); $( '#lib-mode-list' ).html( html ); } if ( ! $( '#lib-search-input' ).val() ) $( '#lib-search-close' ).empty(); - if ( G.library ) { - if ( G.librarylist ) G.scrolltop[ $( '#lib-path .lipath' ).text() ] = $( window ).scrollTop(); + if ( V.library ) { + if ( V.librarylist ) V.scrolltop[ $( '#lib-path .lipath' ).text() ] = $( window ).scrollTop(); renderLibrary(); } else { switchPage( 'library' ); - if ( G.status.updating_db ) banner( 'refresh-library blink', 'Library Database', 'Update ...' ); + if ( S.updating_db ) banner( 'refresh-library blink', 'Library Database', 'Update ...' ); } $( '#lib-mode-list .bkcoverart' ).off( 'error' ).on( 'error', function() { imageOnError( this, $( this ).prev().text() ); } ); $( '#lib-path span' ).removeClass( 'hide' ); - if ( G.color ) $( '#mode-webradio' ).click(); + if ( V.color ) $( '#mode-webradio' ).click(); }, 'json' ); } function lyricsShow( data ) { if ( data !== 'current' ) { - G.lyrics = data; + V.lyrics = data; var lyricshtml = data ? data.replace( /\n/g, '
' ) +'


· · ·' : '(Lyrics not available.)'; - if ( G.lyricsCover ) $( '#divlyricstitle img' ).attr( 'src', G.lyricsCover ); - $( '#lyricstitle' ).text( G.lyricsTitle ); - $( '#lyricsartist' ).text( G.lyricsArtist ); + if ( V.lyricsCover ) $( '#divlyricstitle img' ).attr( 'src', V.lyricsCover ); + $( '#lyricstitle' ).text( V.lyricsTitle ); + $( '#lyricsartist' ).text( V.lyricsArtist ); $( '#lyricstext' ).html( lyricshtml ); } if ( $bartop.is( ':visible' ) ) { @@ -794,10 +803,10 @@ function lyricsShow( data ) { bannerHide(); } function lyricsHide() { - if ( $( '#artist' ).text() !== G.lyricsArtist || $( '#title' ).text() !== G.lyricsTitle ) { - G.lyrics = ''; - G.lyricsArtist = ''; - G.lyricsTitle = ''; + if ( $( '#artist' ).text() !== V.lyricsArtist || $( '#title' ).text() !== V.lyricsTitle ) { + V.lyrics = ''; + V.lyricsArtist = ''; + V.lyricsTitle = ''; $( '#lyricstext' ).empty(); $( '#lyricstextarea' ).val( '' ); } @@ -814,20 +823,20 @@ function menuHide() { $( '#pl-list li' ).removeClass( 'updn' ); } function mpcSeek( elapsed ) { - G.status.elapsed = elapsed; + S.elapsed = elapsed; local(); setProgress(); - if ( G.status.state === 'play' ) setTimeout( setProgressAnimate, 0 ); + if ( S.state === 'play' ) setTimeout( setProgressAnimate, 0 ); $( '#elapsed, #total' ).removeClass( 'gr' ); - if ( G.status.state !== 'play' ) $( '#elapsed' ).addClass( 'bl' ); + if ( S.state !== 'play' ) $( '#elapsed' ).addClass( 'bl' ); $( '#elapsed' ).text( second2HMS( elapsed ) ); - $( '#total' ).text( second2HMS( G.status.Time ) ); - if ( G.status.state === 'stop' && $bartop.is( ':visible' ) ) { + $( '#total' ).text( second2HMS( S.Time ) ); + if ( S.state === 'stop' && $bartop.is( ':visible' ) ) { $( '#playback-controls i' ).removeClass( 'active' ); $( '#pause' ).addClass( 'active' ); $( '#title' ).addClass( 'gr' ); } - bash( [ 'mpcseek', elapsed, G.status.state ] ); + bash( [ 'mpcseek', elapsed, S.state ] ); } function mpcSeekBar( pageX ) { var $timeband = $( '#time-band' ); @@ -835,18 +844,18 @@ function mpcSeekBar( pageX ) { var bandW = $timeband.width(); posX = posX < 0 ? 0 : ( posX > bandW ? bandW : posX ); var pos = posX / bandW; - var elapsed = Math.round( pos * G.status.Time ); + var elapsed = Math.round( pos * S.Time ); var elapsedhms = second2HMS( elapsed ); - if ( G.status.elapsed ) { + if ( S.elapsed ) { $( '#progress span' ).html( elapsedhms ); } else { - $( '#progress' ).html( ''+ elapsedhms +' / '+ second2HMS( G.status.Time ) ); + $( '#progress' ).html( ''+ elapsedhms +' / '+ second2HMS( S.Time ) ); } $( '#time-bar' ).css( 'width', ( pos * 100 ) +'%' ); - if ( ! G.drag ) mpcSeek( elapsed ); + if ( ! V.drag ) mpcSeek( elapsed ); } function orderLibrary() { - G.display.order.forEach( name => { + O.forEach( name => { var $libmode = $( '.lib-mode' ).filter( ( i, el ) => $( el ).find( '.lipath' ).text() === name ); $libmode.detach(); $( '#lib-mode-list' ).append( $libmode ); @@ -854,19 +863,19 @@ function orderLibrary() { } function playlistInsert( indextarget ) { var plname = $( '#pl-path .lipath' ).text(); - bash( [ 'savedpledit', plname, 'add', indextarget, G.pladd.file ], () => { + bash( [ 'savedpledit', plname, 'add', indextarget, V.pladd.file ], () => { renderSavedPlaylist( plname ); if ( indextarget === 'last' ) { setTimeout( () => $( 'html, body' ).animate( { scrollTop: ( $( '#pl-savedlist li' ).length - 3 ) * 49 } ), 300 ); } - G.pladd = {} + V.pladd = {} } ); } function playlistInsertSelect( $this ) { var track = ''+ ( $this.index() + 1 ) +' - '+ $this.find( '.name' ).text(); var content = `\ -${ G.pladd.title } -
${ G.pladd.album } +${ V.pladd.title } +
${ V.pladd.album }

Before
@@ -881,7 +890,7 @@ ${ track } , values : [ 1 ] , buttonlabel : 'Select' , button : playlistInsertTarget - , cancel : () => G.pladd = {} + , cancel : () => V.pladd = {} , ok : () => playlistInsert( +infoVal() + $this.index() ) } ); bannerHide(); @@ -890,8 +899,8 @@ function playlistInsertTarget() { info( { icon : 'file-playlist' , title : 'Add to a playlist' - , message : ''+ G.pladd.title +'' - +'
'+ G.pladd.album + , message : ''+ V.pladd.title +'' + +'
'+ V.pladd.album +'
' +'Select where to add:' , radio : { First : 'first', Select: 'select', Last: 'last' } @@ -903,7 +912,7 @@ function playlistInsertTarget() { } ); } , cancel : () => { - if ( ! G.local ) G.pladd = {} + if ( ! V.local ) V.pladd = {} } , ok : () => playlistInsert( infoVal() ) } ); @@ -979,20 +988,20 @@ function playlistRemove( $li ) { } } function refreshData( resetdata ) { - if ( G.library ) { + if ( V.library ) { if ( $( '#lib-search-input' ).val() ) return - if ( ! G.librarylist ) { // home - if ( resetdata ) G.libraryhtml = ''; + if ( ! V.librarylist ) { // home + if ( resetdata ) V.libraryhtml = ''; libraryHome(); } else { - if ( resetdata ) G.librarylisthtml = ''; - if ( [ 'sd', 'nas', 'usb' ].includes( G.mode ) ) { + if ( resetdata ) V.librarylisthtml = ''; + if ( [ 'sd', 'nas', 'usb' ].includes( V.mode ) ) { $( '#lib-breadcrumbs .lidir' ).last().click(); - } else if ( G.mode === 'album' && $( '#lib-list .coverart' ).length ) { + } else if ( V.mode === 'album' && $( '#lib-list .coverart' ).length ) { $( '#mode-album' ).click(); - } else if ( G.query.length ) { - var query = G.query[ G.query.length - 1 ]; + } else if ( V.query.length ) { + var query = V.query[ V.query.length - 1 ]; list( query, function( html ) { var data = { html : html @@ -1002,19 +1011,16 @@ function refreshData( resetdata ) { renderLibraryList( data ); } ); } else { - $( '#mode-'+ G.mode ).click(); + $( '#mode-'+ V.mode ).click(); } } - } else if ( G.playback ) { + } else if ( V.playback ) { getPlaybackStatus( 'withdisplay' ); - if ( $( '#data' ).hasClass( 'hide' ) || $( '#data .copy' ).length ) { - - } } else { if ( ! $( '#pl-list' ).hasClass( 'hide' ) ) { - if ( resetdata ) G.playlisthtml = ''; + if ( resetdata ) V.playlisthtml = ''; getPlaylist(); - } else if ( ! G.savedplaylist ) { + } else if ( ! V.savedplaylist ) { $( '#button-pl-playlists' ).click(); } else { renderSavedPlaylist( $( '#pl-path .lipath' ).text() ) @@ -1022,9 +1028,9 @@ function refreshData( resetdata ) { } } function renderLibrary() { // home - G.mode = ''; - G.librarylist = 0; - G.query = []; + V.mode = ''; + V.librarylist = 0; + V.query = []; $( '#lib-path' ).css( 'max-width', '' ); $( '#lib-title, #lib-path>i, #button-lib-search' ).removeClass( 'hide' ); $( '#lib-path .lipath' ).empty() @@ -1035,9 +1041,9 @@ function renderLibrary() { // home $( '#page-library .content-top, #lib-mode-list' ).removeClass( 'hide' ); $( '.mode:not( .mode-bookmark )' ).each( ( i, el ) => { var name = el.id.replace( 'mode-', '' ); - $( el ).parent().toggleClass( 'hide', ! G.display[ name ] ); + $( el ).parent().toggleClass( 'hide', ! D[ name ] ); } ); - if ( G.display.label ) { + if ( D.label ) { $( '#lib-mode-list a.label' ).show(); $( '.mode' ).removeClass( 'nolabel' ); } else { @@ -1048,50 +1054,50 @@ function renderLibrary() { // home $( '#lib-mode-list' ) .css( 'padding-top', $bartop.is( ':visible' ) ? '' : 50 ) .removeClass( 'hide' ); - if ( G.display.order ) orderLibrary(); - $( 'html, body' ).scrollTop( G.modescrolltop ); + if ( O ) orderLibrary(); + $( 'html, body' ).scrollTop( V.modescrolltop ); $( '.bkedit' ).remove(); $( '.mode-bookmark' ).children().addBack().removeAttr( 'style' ); renderLibraryCounts(); } function renderLibraryCounts() { - $( '.mode gr' ).toggleClass( 'hide', ! G.display.count ); - var songs = G.counts.song ? G.counts.song.toLocaleString() +'' : ''; + $( '.mode gr' ).toggleClass( 'hide', ! D.count ); + var songs = C.song ? C.song.toLocaleString() +'' : ''; $( '#li-count' ).html( songs ); - $.each( G.counts, ( k, v ) => $( '#mode-'+ k ).find( 'gr' ).text( v ? v.toLocaleString() : '' ) ); + $.each( C, ( k, v ) => $( '#mode-'+ k ).find( 'gr' ).text( v ? v.toLocaleString() : '' ) ); } function renderLibraryList( data ) { - if ( G.librarylist && data.html === G.librarylisthtml ) { - if ( G.color ) colorSet() + if ( V.librarylist && data.html === V.librarylisthtml ) { + if ( V.color ) colorSet() return } - G.librarylist = 1; + V.librarylist = 1; $( '#lib-title, #lib-mode-list, .menu' ).addClass( 'hide' ); $( '#button-lib-back' ) - .toggleClass( 'back-left', G.display.backonleft ) + .toggleClass( 'back-left', D.backonleft ) .toggleClass( 'hide', data.modetitle === 'search' ); $( '#lib-path .lipath' ).text( data.path ); - var root = data.modetitle.toLowerCase() === G.mode; + var root = data.modetitle.toLowerCase() === V.mode; var modetitle = ! root ? data.modetitle : data.modetitle .replace( 'MARTIST', 'M ARTIST' ) .replace( 'BRADIO', 'B RADIO' ); - var htmlmodetitle = ' '+ modetitle +''; - if ( 'count' in data && G.mode !== 'latest' ) { + var htmlmodetitle = ' '+ modetitle +''; + if ( 'count' in data && V.mode !== 'latest' ) { $( '#lib-path' ).css( 'max-width', 40 ); $( '#lib-list' ).css( 'width', '100%' ); var htmlpath = ''; } else if ( [ 'DABRADIO', 'WEBRADIO' ].includes( data.path ) ) { var htmlpath = htmlmodetitle; $( '#lib-path .lipath' ).empty(); - } else if ( ! [ 'sd', 'nas', 'usb', 'dabradio', 'webradio' ].includes( G.mode ) ) { + } else if ( ! [ 'sd', 'nas', 'usb', 'dabradio', 'webradio' ].includes( V.mode ) ) { var htmlpath = htmlmodetitle; $( '#button-lib-search' ).addClass( 'hide' ); } else if ( data.path ) { // dir breadcrumbs var dir = data.path.split( '/' ); var dir0 = dir[ 0 ]; - var htmlpath = ''; - if ( G.mode.slice( -5 ) === 'radio' ) htmlpath += ''+ G.mode +'/'; + var htmlpath = ''; + if ( V.mode.slice( -5 ) === 'radio' ) htmlpath += ''+ V.mode +'/'; htmlpath += ''+ dir0 +'/'+ dir0 +''; var lidir = dir0; var iL = dir.length; @@ -1100,17 +1106,17 @@ function renderLibraryList( data ) { htmlpath += ''+ dir[ i ] +'/'+ lidir +''; } } - if ( G.mode === 'webradio' ) { + if ( V.mode === 'webradio' ) { htmlpath += ''; - } else if ( G.mode === 'latest' ) { + } else if ( V.mode === 'latest' ) { htmlpath += ''; - } else if ( G.mode === 'dabradio' ) { + } else if ( V.mode === 'dabradio' ) { htmlpath += root ? '' : ''; } $( '#lib-breadcrumbs' ) .html( htmlpath ) .removeClass( 'hide' ); - G.librarylisthtml = data.html; + V.librarylisthtml = data.html; $( '#lib-list, #lib-index, #lib-index1' ).remove(); if ( ! data.html ) return // empty radio @@ -1118,45 +1124,45 @@ function renderLibraryList( data ) { var html = data.html.replaceAll( '^^^', hash ); $( '#lib-mode-list' ).after( html ).promise().done( () => { if ( $( '.licover' ).length ) { - if ( $( '#liimg' ).attr( 'src' ).slice( 0, 5 ) === '/data' ) $( '.licoverimg ' ).append( icoversave ); + if ( $( '#liimg' ).attr( 'src' ).slice( 0, 16 ) === '/data/shm/online' ) $( '.licoverimg ' ).append( icoversave ); } else { imageLoad( 'lib-list' ); } - $( '.liinfopath' ).toggleClass( 'hide', [ 'sd', 'nas', 'usb', 'webradio' ].includes( G.mode ) ); - if ( G.mode === 'album' && $( '#lib-list .coverart' ).length ) { - G.albumlist = 1; + $( '.liinfopath' ).toggleClass( 'hide', [ 'sd', 'nas', 'usb', 'webradio' ].includes( V.mode ) ); + if ( V.mode === 'album' && $( '#lib-list .coverart' ).length ) { + V.albumlist = 1; $( '#lib-list img' ).eq( 0 ).on( 'load', function() { $( '#lib-breadcrumbs' ).append( '' ); } ); - if ( G.iactive ) $( '#lib-list .coverart' ).eq( G.iactive ).addClass( 'active' ); + if ( V.iactive ) $( '#lib-list .coverart' ).eq( V.iactive ).addClass( 'active' ); $( '#lib-list' ).removeClass( 'hide' ); } else { - G.albumlist = 0; + V.albumlist = 0; $( '#lib-list p' ) - .toggleClass( 'fixedcover', G.display.fixedcover ) + .toggleClass( 'fixedcover', D.fixedcover ) .toggleClass( 'bars-on', $bartop.is( ':visible' ) ); $( '#lib-list' ).removeClass( 'hide' ); - G.color ? colorSet() : setTrackCoverart(); + V.color ? colorSet() : setTrackCoverart(); } $( '#lib-list' ).css( 'width', $( '#lib-index' ).length ? '' : '100%' ); - var pH = G.wH - 80; - pH -= G.albumlist ? $( '.coverart' ).height() : 49; + var pH = V.wH - 80; + pH -= V.albumlist ? $( '.coverart' ).height() : 49; if ( $bartop.is( ':hidden' ) ) pH += 40; $( '#lib-list p' ) .removeClass( 'bars-on' ) - .toggleClass( 'fixedcover', G.display.fixedcover && $( '.licover' ).length === 1 ) + .toggleClass( 'fixedcover', D.fixedcover && $( '.licover' ).length === 1 ) .css( 'height', pH ); - $( 'html, body' ).scrollTop( G.scrolltop[ data.path ] || 0 ); + $( 'html, body' ).scrollTop( V.scrolltop[ data.path ] || 0 ); } ); } function renderPlayback() { - if ( ! G.status.state ) return // suppress on reboot + if ( ! S.state ) return // suppress on reboot local(); - if ( G.status.state === 'stop' ) setProgress( 0 ); + if ( S.state === 'stop' ) setProgress( 0 ); setVolume(); - clearInterval( G.intBlinkDot ); - if ( ! G.status.pllength && G.status.player === 'mpd' && G.status.state === 'stop' ) { // empty queue + clearInterval( V.intBlinkDot ); + if ( ! S.pllength && S.player === 'mpd' && S.state === 'stop' ) { // empty queue setPlaybackBlank(); return } @@ -1168,17 +1174,17 @@ function renderPlayback() { $( '#qrwebui, #qrip' ).empty(); setInfo(); setCoverart(); - var istate = ''; - if ( G.status.elapsed === false || G.status.webradio ) { + var istate = ''; + if ( S.elapsed === false || S.webradio ) { setBlinkDot(); return } - var time = 'Time' in G.status ? G.status.Time : ''; + var time = 'Time' in S ? S.Time : ''; var timehms = time ? second2HMS( time ) : ''; $( '#total' ).text( timehms ); $timeRS.option( 'max', time || 100 ); - if ( G.status.state === 'stop' ) { + if ( S.state === 'stop' ) { $( '#elapsed, #total, #progress' ).empty(); $( '#title' ).removeClass( 'gr' ); if ( timehms ) { @@ -1191,21 +1197,21 @@ function renderPlayback() { } $( '#elapsed, #total' ).removeClass( 'bl gr wh' ); - if ( G.status.elapsed === false || G.status.Time === false || ! ( 'elapsed' in G.status ) || G.status.elapsed > time ) { - $( '#elapsed' ).html( G.status.state === 'play' ? blinkdot : '' ); + if ( S.elapsed === false || S.Time === false || ! ( 'elapsed' in S ) || S.elapsed > time ) { + $( '#elapsed' ).html( S.state === 'play' ? blinkdot : '' ); blinkDot(); return } - if ( G.status.elapsed ) { - var elapsedhms = second2HMS( G.status.elapsed ); + if ( S.elapsed ) { + var elapsedhms = second2HMS( S.elapsed ); $( '#progress' ).html( istate +''+ elapsedhms +' / '+ timehms ); } else { $( '#progress' ).html( istate +''+ timehms ); setTimeout( () => $( '#progress span' ).after( ' / ' ), 1000 ); } setProgress(); - if ( G.status.state === 'pause' ) { + if ( S.state === 'pause' ) { $( '#elapsed' ).text( elapsedhms ).addClass( 'bl' ); $( '#total' ).addClass( 'wh' ); } else { //play @@ -1213,15 +1219,14 @@ function renderPlayback() { } } function renderPlaylist( data ) { // current playlist - G.savedlist = 0; - G.savedplaylist = 0; - G.status.elapsed = data.elapsed; - G.status.song = data.song; + V.savedlist = 0; + V.savedplaylist = 0; + S.elapsed = data.elapsed; $( '#pl-search-close' ).click(); $( '#button-pl-back, #pl-savedlist, #pl-index' ).addClass( 'hide' ); - $( '#button-pl-playlists' ).toggleClass( 'disabled', G.counts.playlists === 0 ); - if ( ! G.status.pllength || data == -1 ) { - G.playlisthtml = ''; + $( '#button-pl-playlists' ).toggleClass( 'disabled', C.playlists === 0 ); + if ( ! S.pllength || data == -1 ) { + V.playlisthtml = ''; $( '#playback-controls' ).addClass( 'hide' ); $( '#pl-path' ).html( 'PLAYLIST' ); $( '.pllength' ).addClass( 'disabled' ); @@ -1237,13 +1242,13 @@ function renderPlaylist( data ) { // current playlist $( '.emptyadd' ).addClass( 'hide' ); $( '#pl-path' ).html( 'PLAYLIST '+ data.counthtml ); $( '#button-pl-save, #button-pl-clear, #button-pl-search' ).removeClass( 'disabled' ); - $( '#button-pl-shuffle' ).toggleClass( 'disabled', G.status.pllength < 2 ); - $( '#button-pl-consume' ).toggleClass( 'bl', G.status.consume ); + $( '#button-pl-shuffle' ).toggleClass( 'disabled', S.pllength < 2 ); + $( '#button-pl-consume' ).toggleClass( 'bl', S.consume ); $( '#button-pl-librandom' ) - .toggleClass( 'bl', G.status.librandom ) - .toggleClass( 'disabled', G.counts.song === 0 ); - if ( data.html !== G.playlisthtml ) { - G.playlisthtml = data.html; + .toggleClass( 'bl', S.librandom ) + .toggleClass( 'disabled', C.song === 0 ); + if ( data.html !== V.playlisthtml ) { + V.playlisthtml = data.html; var hash = versionHash(); var html = data.html.replaceAll( '^^^', hash ) +'

'; $( '#pl-list' ).html( html ).promise().done( () => { @@ -1262,10 +1267,10 @@ function renderPlaylistList( data ) { // list of saved playlists $( '#pl-path' ).html( data.counthtml ); $( '#button-pl-back, #pl-savedlist, #pl-index' ).removeClass( 'hide' ); $( '.emptyadd' ).addClass( 'hide' ); - $( '#button-pl-back' ).toggleClass( 'back-left', G.display.backonleft ); + $( '#button-pl-back' ).toggleClass( 'back-left', D.backonleft ); var barvisible = $bartop.is( ':visible' ); - if ( data.html !== G.playlisthtml ) { - G.playlistlisthtml = data.html; + if ( data.html !== V.playlisthtml ) { + V.playlistlisthtml = data.html; var hash = versionHash(); var html = data.html.replaceAll( '^^^', hash ) +'

'; $( '#pl-savedlist' ).html( html ).promise().done( () => { @@ -1283,7 +1288,7 @@ function renderSavedPlaylist( name ) { // tracks in a playlist menuHide(); list( { cmd: 'get', name: name }, function( data ) { $( '#pl-path' ).html( data.counthtml ); - $( '#button-pl-back' ).toggleClass( 'back-left', G.display.backonleft ); + $( '#button-pl-back' ).toggleClass( 'back-left', D.backonleft ); $( '#button-pl-back, #pl-savedlist' ).removeClass( 'hide' ); var hash = versionHash(); var html = data.html.replaceAll( '^^^', hash ) +'

'; @@ -1297,12 +1302,12 @@ function renderSavedPlaylist( name ) { // tracks in a playlist }, 'json' ); } function saveToPlaylist( title, album, file ) { - G.pladd.title = title; - G.pladd.album = album; - G.pladd.file = file; + V.pladd.title = title; + V.pladd.album = album; + V.pladd.file = file; local(); $( '#button-pl-playlists' ).click(); - if ( ! G.playlist ) $( '#button-playlist' ).click(); + if ( ! V.playlist ) $( '#button-playlist' ).click(); banner( 'file-playlist blink', 'Add to a playlist', 'Select target playlist', 5000 ); } function second2HMS( second ) { @@ -1321,14 +1326,14 @@ function second2HMS( second ) { return hh +':'+ mm +':'+ ss; } function setBlinkDot() { - [ G.intBlinkDot, G.intElapsedPl, G.intElapsed, G.intVu ].forEach( el => clearInterval( el ) ); + [ V.intBlinkDot, V.intElapsedPl, V.intElapsed, V.intVu ].forEach( el => clearInterval( el ) ); $( '#vuneedle' ).css( 'transform', '' ); $( '#elapsed, #total, #progress' ).empty(); - if ( G.status.state === 'play' ) { - $( '#elapsed' ).html( G.status.state === 'play' ? blinkdot : '' ); + if ( S.state === 'play' ) { + $( '#elapsed' ).html( S.state === 'play' ? blinkdot : '' ); blinkDot(); - if ( G.display.radioelapsed ) { - $( '#progress' ).html( '' ); + if ( D.radioelapsed ) { + $( '#progress' ).html( '' ); setProgressElapsed(); } } @@ -1340,7 +1345,7 @@ function setBookmarkEdit() { return } - G.bklabel = $( this ).find( '.label' ); + V.bklabel = $( this ).find( '.label' ); $( '.mode-bookmark' ).each( ( i, el ) => { var $this = $( el ); var path = $this.find( '.lipath' ).text(); @@ -1355,62 +1360,62 @@ function setBookmarkEdit() { .css( 'opacity', 0.33 ); } function setButtonControl() { - if ( ! G.status.state ) return // suppress on reboot + if ( ! S.state ) return // suppress on reboot if ( $bartop.is( ':visible' ) ) { - var mpd_upnp = [ 'mpd', 'upnp' ].includes( G.status.player ); - var noprevnext = G.status.pllength < 2 || ! mpd_upnp; - $( '#playback-controls' ).toggleClass( 'hide', G.status.pllength === 0 && mpd_upnp ); + var mpd_upnp = [ 'mpd', 'upnp' ].includes( S.player ); + var noprevnext = S.pllength < 2 || ! mpd_upnp; + $( '#playback-controls' ).toggleClass( 'hide', S.pllength === 0 && mpd_upnp ); $( '#previous, #next' ).toggleClass( 'hide', noprevnext ); $( '#coverL, #coverR' ).toggleClass( 'disabled', noprevnext ); $( '#play, #pause, #coverM' ).toggleClass( 'disabled', ! mpd_upnp ); - $( '#pause' ).toggleClass( 'hide', G.status.stream && G.status.player !== 'upnp' ); + $( '#pause' ).toggleClass( 'hide', S.stream && S.player !== 'upnp' ); $( '#playback-controls i' ).removeClass( 'active' ); - $( '#'+ G.status.state ).addClass( 'active' ); // suppress on reboot + $( '#'+ S.state ).addClass( 'active' ); // suppress on reboot } - if ( G.playback ) setTimeout( setButtonOptions, 0 ); + if ( V.playback ) setTimeout( setButtonOptions, 0 ); } function setButtonOptions() { - $( '#dsp' ).toggleClass( 'disabled', [ 'airplay', 'spotify' ].includes( G.status.player ) ); - $( '#relays' ).toggleClass( 'on', G.status.relayson ); - $( '#snapclient' ).toggleClass( 'on', G.status.player === 'snapcast' ); + $( '#dsp' ).toggleClass( 'disabled', [ 'airplay', 'spotify' ].includes( S.player ) ); + $( '#relays' ).toggleClass( 'on', S.relayson ); + $( '#snapclient' ).toggleClass( 'on', S.player === 'snapcast' ); $( '#modeicon i, #timeicon i' ).addClass( 'hide' ); var timevisible = $time.is( ':visible' ); var prefix = timevisible ? 'ti' : 'i'; - $( '#'+ prefix +'-btsender' ).toggleClass( 'hide', ! G.status.btreceiver ); - $( '#'+ prefix +'-relays' ).toggleClass( 'hide', ! G.status.relayson ); - $( '#'+ prefix +'-stoptimer' ).toggleClass( 'hide', ! G.status.stoptimer ); - $( '#'+ prefix +'-snapclient' ).toggleClass( 'hide', ! G.status.snapclient ); - if ( ! G.status.stream && G.status.player === 'mpd' ) { + $( '#'+ prefix +'-btsender' ).toggleClass( 'hide', ! S.btreceiver ); + $( '#'+ prefix +'-relays' ).toggleClass( 'hide', ! S.relayson ); + $( '#'+ prefix +'-stoptimer' ).toggleClass( 'hide', ! S.stoptimer ); + $( '#'+ prefix +'-snapclient' ).toggleClass( 'hide', ! S.snapclient ); + if ( ! S.stream && S.player === 'mpd' ) { if ( $( '#play-group' ).is( ':visible' ) ) { - $( '#random' ).toggleClass( 'active', G.status.random ); - $( '#repeat' ).toggleClass( 'active', G.status.repeat ); - $( '#single' ).toggleClass( 'active', G.status.single ); + $( '#random' ).toggleClass( 'active', S.random ); + $( '#repeat' ).toggleClass( 'active', S.repeat ); + $( '#single' ).toggleClass( 'active', S.single ); } else { - $( '#'+ prefix +'-random' ).toggleClass( 'hide', ! G.status.random ); - $( '#'+ prefix +'-repeat' ).toggleClass( 'hide', ! G.status.repeat || G.status.single ); - $( '#'+ prefix +'-repeat1' ).toggleClass( 'hide', ! ( G.status.repeat && G.status.single ) ); - $( '#'+ prefix +'-single' ).toggleClass( 'hide', ! G.status.single || ( G.status.repeat && G.status.single ) ); + $( '#'+ prefix +'-random' ).toggleClass( 'hide', ! S.random ); + $( '#'+ prefix +'-repeat' ).toggleClass( 'hide', ! S.repeat || S.single ); + $( '#'+ prefix +'-repeat1' ).toggleClass( 'hide', ! ( S.repeat && S.single ) ); + $( '#'+ prefix +'-single' ).toggleClass( 'hide', ! S.single || ( S.repeat && S.single ) ); } [ 'consume', 'librandom' ].forEach( option => { if ( timevisible ) { $( '#i-'+ option ).addClass( 'hide' ); - $( '#ti-'+ option ).toggleClass( 'hide', ! G.status[ option ] ); + $( '#ti-'+ option ).toggleClass( 'hide', ! S[ option ] ); } else { $( '#ti-'+ option ).addClass( 'hide' ); - $( '#i-'+ option ).toggleClass( 'hide', ! G.status[ option ] ); + $( '#i-'+ option ).toggleClass( 'hide', ! S[ option ] ); } - $( '#button-pl-'+ option ).toggleClass( 'bl', G.status[ option ] ); + $( '#button-pl-'+ option ).toggleClass( 'bl', S[ option ] ); } ); } setButtonUpdateAddons(); setButtonUpdating(); - if ( $volume.is( ':hidden' ) && G.status.volumemute ) $( '#'+ prefix +'-mute' ).removeClass( 'hide' ); + if ( $volume.is( ':hidden' ) && S.volumemute ) $( '#'+ prefix +'-mute' ).removeClass( 'hide' ); } function setButtonUpdateAddons() { - if ( G.status.updateaddons ) { + if ( S.updateaddons ) { $( '#button-settings, #addons i' ).addClass( 'bl' ); - if ( ! G.display.bars ) { + if ( ! D.bars ) { var prefix = $time.is( ':visible' ) ? 'ti' : 'i'; $( '#'+ prefix +'-addons' ).addClass( 'hide' ); $( '#'+ prefix +'-addons' ).removeClass( 'hide' ); @@ -1421,37 +1426,37 @@ function setButtonUpdateAddons() { } } function setButtonUpdating() { - clearInterval( G.intBlinkUpdate ); - if ( G.status.updating_db ) { + clearInterval( V.intBlinkUpdate ); + if ( S.updating_db ) { if ( $( '#bar-bottom' ).is( ':hidden' ) || $( '#bar-bottom' ).hasClass( 'transparent' ) ) { var prefix = $time.is( ':visible' ) ? 'ti' : 'i'; $( '#'+ prefix +'-libupdate' ).removeClass( 'hide' ); } else { $( '#library, #button-library' ).addClass( 'blink' ); } - if ( G.localhost ) blinkUpdate(); + if ( V.localhost ) blinkUpdate(); $( '#update' ).addClass( 'on' ); } else { $( '#library, #button-library' ).removeClass( 'blink' ); $( '#i-libupdate, #ti-libupdate' ).addClass( 'hide' ); $( '#update' ).removeClass( 'on' ); } - $( '#i-dabupdate' ).toggleClass( 'hide', ! G.status.updatingdab ); + $( '#i-dabupdate' ).toggleClass( 'hide', ! S.updatingdab ); } function setCoverart() { - if ( ! G.display.cover ) { + if ( ! D.cover ) { loaderHide(); return } - if ( G.display.vumeter ) { + if ( D.vumeter ) { $( '#coverart' ) .addClass( 'hide' ) .attr( 'src', '' ); $( '#vu' ).removeClass( 'hide' ); loaderHide(); } else { - var coverart = G.status.stream ? ( G.status.coverart || G.status.stationcover ) : G.status.coverart; + var coverart = S.stream ? ( S.coverart || S.stationcover ) : S.coverart; if ( coverart ) { $( '#vu' ).addClass( 'hide' ); $( '#coverart' ) @@ -1463,52 +1468,52 @@ function setCoverart() { } } function setInfo() { - G.prevartist = $( '#artist' ).text(); - G.prevtitle = $( '#title' ).text(); - G.prevalbum = $( '#album' ).text(); - if ( ! G.status.stream || G.status.player === 'upnp' ) { - $( '#artist' ).text( G.status.Artist ); + V.prevartist = $( '#artist' ).text(); + V.prevtitle = $( '#title' ).text(); + V.prevalbum = $( '#album' ).text(); + if ( ! S.stream || S.player === 'upnp' ) { + $( '#artist' ).text( S.Artist ); $( '#title' ) - .text( G.status.Title ) - .toggleClass( 'gr', G.status.state === 'pause' ); - $( '#album' ).text( G.status.Album || G.status.file ); + .text( S.Title ) + .toggleClass( 'gr', S.state === 'pause' ); + $( '#album' ).text( S.Album || S.file ); } else { // webradio - var url = G.status.file.replace( /#charset=.*/, '' ); - if ( G.status.state !== 'play' ) { - $( '#artist' ).text( G.status.station ); + var url = S.file.replace( /#charset=.*/, '' ); + if ( S.state !== 'play' ) { + $( '#artist' ).text( S.station ); $( '#title' ).html( '· · ·' ); $( '#album' ).text( url ); } else { - $( '#artist' ).text( G.status.Artist || ( ! G.status.Artist && ! G.status.Title ? G.status.station : '' ) ); - $( '#title' ).html( G.status.Title || blinkdot ); + $( '#artist' ).text( S.Artist || ( ! S.Artist && ! S.Title ? S.station : '' ) ); + $( '#title' ).html( S.Title || blinkdot ); blinkDot(); - $( '#album' ).text( G.status.Album || url ); + $( '#album' ).text( S.Album || url ); } } - $( '#artist' ).toggleClass( 'disabled', G.status.Artist === '' ); - $( '#title' ).toggleClass( 'disabled', G.status.Title === '' ); - $( '#album' ).toggleClass( 'disabled', G.status.Album === '' ); + $( '#artist' ).toggleClass( 'disabled', S.Artist === '' ); + $( '#title' ).toggleClass( 'disabled', S.Title === '' ); + $( '#album' ).toggleClass( 'disabled', S.Album === '' ); setInfoScroll(); - var sampling = G.status.sampling; - if ( G.status.stream ) { - if ( G.status.icon === 'dabradio' ) { + var sampling = S.sampling; + if ( S.stream ) { + if ( S.icon === 'dabradio' ) { sampling += ' • DAB'; - } else if ( G.status.Album && G.status.station ) { - var station = [ 'radiofrance', 'radioparadise' ].includes( G.status.icon ) ? G.status.station.split( ' - ' ).pop() : G.status.station; + } else if ( S.Album && S.station ) { + var station = [ 'radiofrance', 'radioparadise' ].includes( S.icon ) ? S.station.split( ' - ' ).pop() : S.station; sampling += ' • '+ station; } else { - sampling += ' • '+ G.status.ext; + sampling += ' • '+ S.ext; } } $( '#sampling' ).html( sampling ); - if ( G.status.icon !== $( '#playericon' ).prop( 'class' ).replace( 'fa fa-', '' ) ) { + if ( S.icon !== $( '#playericon' ).prop( 'class' ).replace( 'fa fa-', '' ) ) { $( '#playericon' ).removeAttr( 'class' ); - if ( G.status.icon ) $( '#playericon' ).addClass( 'fa fa-'+ G.status.icon ); + if ( S.icon ) $( '#playericon' ).addClass( 'fa fa-'+ S.icon ); } if ( $time.is( ':hidden' ) ) setProgressElapsed(); } function setInfoScroll() { - if ( $( '#artist' ).text() + $( '#title' ).text() + $( '#album' ).text() === G.prevartist + G.prevtitle + G.prevalbum ) return // skip if same data + if ( $( '#artist' ).text() + $( '#title' ).text() + $( '#album' ).text() === V.prevartist + V.prevtitle + V.prevalbum ) return // skip if same data var tWmax = 0; var $el = $( '#artist, #title, #album' ); @@ -1517,7 +1522,7 @@ function setInfoScroll() { .removeAttr( 'style' ); $el.each( ( i, el ) => { var tW = Math.ceil( el.getBoundingClientRect().width ); - if ( tW > G.wW - 20 ) { + if ( tW > V.wW - 20 ) { if ( tW > tWmax ) tWmax = tW; // same width > scroll together (same speed) $( el ).addClass( 'scrollleft' ); } @@ -1526,9 +1531,9 @@ function setInfoScroll() { $( '.scrollleft' ).css( { // same width and speed width : tWmax - , animation : ( G.wW + tWmax ) / G.scrollspeed +'s infinite linear scrollleft' + , animation : ( V.wW + tWmax ) / V.scrollspeed +'s infinite linear scrollleft' } ); - if ( G.localhost ) { + if ( V.localhost ) { $( '.scrollleft' ) .css( 'animation-iteration-count', 1 ) .on( 'animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd', function() { @@ -1540,19 +1545,19 @@ function setInfoScroll() { } } function setPlaybackBlank() { - $( '#page-playback .emptyadd' ).toggleClass( 'hide', G.status.player !== 'mpd' ); + $( '#page-playback .emptyadd' ).toggleClass( 'hide', S.player !== 'mpd' ); $( '#playback-controls, #infoicon i, #vu' ).addClass( 'hide' ); $( '#divartist, #divtitle, #divalbum' ).removeClass( 'scroll-left' ); $( '#artist, #title, #album, #progress, #elapsed, #total' ).empty(); setProgress( 0 ); $( '#divcover .coveredit' ).remove(); $( '#coverart' ) - .attr( 'src', G.coverdefault ) + .attr( 'src', V.coverdefault ) .css( 'opacity', '' ); - if ( G.status.ip ) { - $( '#qrip' ).html( 'http://'+ G.status.ip +'
http://'+ G.status.hostname ); + if ( S.ip ) { + $( '#qrip' ).html( 'http://'+ S.ip +'
http://'+ S.hostname ); var qr = new QRCode( { - msg : 'http://'+ G.status.ip + msg : 'http://'+ S.ip , dim : 230 , pad : 11 } ); @@ -1586,8 +1591,8 @@ function setPlaylistInfoWidth() { function setPlaylistScroll() { clearIntervalAll(); switchPage( 'playlist' ); - if ( G.sortable - || ( G.display.audiocd && $( '#pl-list li' ).length < G.status.song + 1 ) // on eject cd G.status.song not yet refreshed + if ( V.sortable + || ( D.audiocd && $( '#pl-list li' ).length < S.song + 1 ) // on eject cd S.song not yet refreshed ) { $( '#page-playlist' ).css( 'visibility', '' ); return @@ -1596,7 +1601,7 @@ function setPlaylistScroll() { var litop = $bartop.is( ':visible' ) ? 80 : 40; $( '#menu-plaction' ).addClass( 'hide' ); $( '#pl-list li' ).removeClass( 'active updn' ); - $liactive = $( '#pl-list li' ).eq( G.status.song || 0 ); + $liactive = $( '#pl-list li' ).eq( S.song ); $liactive.addClass( 'active' ); if ( ! $( '.pl-remove' ).length && I.infohide ) { if ( $( '#pl-list li' ).length < 5 ) { @@ -1608,41 +1613,41 @@ function setPlaylistScroll() { } $( '#page-playlist' ).css( 'visibility', '' ); $( '#pl-list .elapsed' ).empty(); - var $this = $( '#pl-list li' ).eq( G.status.song ); + var $this = $( '#pl-list li' ).eq( S.song ); var $elapsed = $this.find( '.elapsed' ); var $name = $this.find( '.name' ); var $stationname = $this.find( '.li2 .stationname' ); $stationname.addClass( 'hide' ); - if ( G.status.state === 'stop' ) { - if ( G.status.webradio ) $name.text( $this.find( '.liname' ).text() ); + if ( S.state === 'stop' ) { + if ( S.webradio ) $name.text( $this.find( '.liname' ).text() ); $stationname.addClass( 'hide' ); } else { - if ( G.status.elapsed === false ) return + if ( S.elapsed === false ) return - var slash = G.status.Time ? ' /' : ''; - if ( G.status.player === 'upnp' ) $this.find( '.time' ).text( second2HMS( G.status.Time ) ); - if ( G.status.state === 'pause' ) { - elapsedtxt = second2HMS( G.status.elapsed ); + var slash = S.Time ? ' /' : ''; + if ( S.player === 'upnp' ) $this.find( '.time' ).text( second2HMS( S.Time ) ); + if ( S.state === 'pause' ) { + elapsedtxt = second2HMS( S.elapsed ); $elapsed.html( ''+ elapsedtxt + slash ); setPlaylistInfoWidth(); - } else if ( G.status.state === 'play' ) { + } else if ( S.state === 'play' ) { $stationname.removeClass( 'hide' ); - if ( G.status.webradio ) { + if ( S.webradio ) { $stationname.removeClass( 'hide' ); - $name.html( G.status.Title || '· · ·' ); + $name.html( S.Title || '· · ·' ); } var elapsedL0 = 0; var elapsedL = 0; - if ( G.status.elapsed ) $elapsed.html( ''+ second2HMS( G.status.elapsed ) + slash ); - G.intElapsedPl = setInterval( () => { - G.status.elapsed++; - if ( G.status.elapsed === G.status.Time ) { + if ( S.elapsed ) $elapsed.html( ''+ second2HMS( S.elapsed ) + slash ); + V.intElapsedPl = setInterval( () => { + S.elapsed++; + if ( S.elapsed === S.Time ) { clearIntervalAll(); - G.status.elapsed = 0; + S.elapsed = 0; $elapsed.empty(); setPlaylistScroll(); } else { - elapsedtxt = second2HMS( G.status.elapsed ); + elapsedtxt = second2HMS( S.elapsed ); $elapsed.html( ''+ elapsedtxt + slash ); elapsedL = elapsedtxt.length; if ( elapsedL > elapsedL0 ) { @@ -1655,95 +1660,95 @@ function setPlaylistScroll() { } } function setProgress( position ) { - if ( G.status.state !== 'play' || G.status.elapsed === 0 ) clearInterval( G.intElapsed ); - if ( position !== 0 ) position = G.status.elapsed; + if ( S.state !== 'play' || S.elapsed === 0 ) clearInterval( V.intElapsed ); + if ( position !== 0 ) position = S.elapsed; $timeprogress.css( 'transition-duration', '0s' ); $timeRS.setValue( position ); - var w = position && G.status.Time ? position / G.status.Time * 100 : 0; + var w = position && S.Time ? position / S.Time * 100 : 0; $( '#time-bar' ).css( 'width', w +'%' ); } function setProgressAnimate() { - if ( ! G.display.time && ! G.display.cover ) return + if ( ! D.time && ! D.cover ) return - $timeprogress.css( 'transition-duration', G.status.Time - G.status.elapsed +'s' ); - $timeRS.setValue( G.status.Time ); + $timeprogress.css( 'transition-duration', S.Time - S.elapsed +'s' ); + $timeRS.setValue( S.Time ); $( '#time-bar' ).css( 'width', '100%' ); } function setProgressElapsed() { - clearInterval( G.intElapsed ); - if ( G.status.elapsed === false || G.status.state !== 'play' || 'autoplaycd' in G ) return // wait for cd cache on start + clearInterval( V.intElapsed ); + if ( S.elapsed === false || S.state !== 'play' || 'autoplaycd' in V ) return // wait for cd cache on start var elapsedhms; - var $elapsed = G.status.elapsed === false ? $( '#total, #progress span' ) : $( '#elapsed, #progress span' ); - if ( G.status.elapsed ) $elapsed.text( second2HMS( G.status.elapsed ) ); - if ( G.status.Time ) { - var time = G.status.Time; + var $elapsed = S.elapsed === false ? $( '#total, #progress span' ) : $( '#elapsed, #progress span' ); + if ( S.elapsed ) $elapsed.text( second2HMS( S.elapsed ) ); + if ( S.Time ) { + var time = S.Time; $timeRS.option( 'max', time ); setProgress(); - if ( ! G.localhost ) { + if ( ! V.localhost ) { setTimeout( setProgressAnimate, 0 ); // delay to after setvalue on load } else { $timeprogress.css( 'transition-duration', '0s' ); } - G.intElapsed = setInterval( () => { - G.status.elapsed++; - if ( G.status.elapsed < time ) { - if ( G.localhost ) { - $timeRS.setValue( G.status.elapsed ); - $( '#time-bar' ).css( 'width', G.status.elapsed / time * 100 +'%' ); + V.intElapsed = setInterval( () => { + S.elapsed++; + if ( S.elapsed < time ) { + if ( V.localhost ) { + $timeRS.setValue( S.elapsed ); + $( '#time-bar' ).css( 'width', S.elapsed / time * 100 +'%' ); } - elapsedhms = second2HMS( G.status.elapsed ); + elapsedhms = second2HMS( S.elapsed ); $elapsed.text( elapsedhms ); - if ( G.status.state !== 'play' ) clearInterval( G.intElapsed ); + if ( S.state !== 'play' ) clearInterval( V.intElapsed ); } else { - G.status.elapsed = 0; + S.elapsed = 0; clearIntervalAll(); $elapsed.empty(); setProgress( 0 ); } }, 1000 ); - } else if ( G.display.radioelapsed ) { + } else if ( D.radioelapsed ) { $( '#elapsed' ).html( blinkdot ); $elapsed = $( '#total, #progress span' ); - $elapsed.text( second2HMS( G.status.elapsed ) ); - G.intElapsed = setInterval( () => { - G.status.elapsed++; - elapsedhms = second2HMS( G.status.elapsed ); + $elapsed.text( second2HMS( S.elapsed ) ); + V.intElapsed = setInterval( () => { + S.elapsed++; + elapsedhms = second2HMS( S.elapsed ); $elapsed.text( elapsedhms ); - if ( G.status.state !== 'play' ) clearInterval( G.intElapsed ); + if ( S.state !== 'play' ) clearInterval( V.intElapsed ); }, 1000 ); } } function setTrackCoverart() { - if ( G.display.hidecover || ! $( '#liimg' ).length ) return + if ( D.hidecover || ! $( '#liimg' ).length ) return $( '#liimg' ).off( 'load' ).on( 'load', function() { // not exist on initial page load $( 'html, body' ).scrollTop( 0 ); } ).off( 'error' ).on( 'error', function() { - $( this ).attr( 'src', G.coverdefault ); + $( this ).attr( 'src', V.coverdefault ); } ); - if ( G.mode === 'album' ) { + if ( V.mode === 'album' ) { $( '#mode-title' ).html( $( '.liinfo .lialbum' ).text() ); $( '.liinfo .lialbum' ).addClass( 'hide' ); } else { $( '.liinfo .lialbum' ).removeClass( 'hide' ); } - if ( ! G.display.fixedcover ) { + if ( ! D.fixedcover ) { $( '.licover' ).addClass( 'nofixed' ); $( '#lib-list li' ).eq( 1 ).removeClass( 'track1' ); } } function setVolume() { - var mute = G.status.volumemute !== 0; - $volumeRS.setValue( G.status.volume ); - if ( G.status.volume === 0 ) $volumehandle.rsRotate( -310 ); - mute ? volumeColorMute( G.status.volumemute ) : volumeColorUnmute(); - $( '#voldn' ).toggleClass( 'disabled', G.status.volume === 0 ); - $( '#volmute' ).toggleClass( 'disabled', G.status.volume === 0 && ! mute ); - $( '#volup' ).toggleClass( 'disabled', G.status.volume === 100 ); - $( '#volume-bar' ).css( 'width', G.status.volume +'%' ); + var mute = S.volumemute !== 0; + $volumeRS.setValue( S.volume ); + if ( S.volume === 0 ) $volumehandle.rsRotate( -310 ); + mute ? volumeColorMute( S.volumemute ) : volumeColorUnmute(); + $( '#voldn' ).toggleClass( 'disabled', S.volume === 0 ); + $( '#volmute' ).toggleClass( 'disabled', S.volume === 0 && ! mute ); + $( '#volup' ).toggleClass( 'disabled', S.volume === 100 ); + $( '#volume-bar' ).css( 'width', S.volume +'%' ); $( '#volume-text' ) - .text( G.status.volumemute || G.status.volume ) + .text( S.volumemute || S.volume ) .toggleClass( 'bl', mute ); if ( $volume.is( ':hidden' ) ) { var prefix = $time.is( ':visible' ) ? 'ti' : 'i'; @@ -1751,8 +1756,8 @@ function setVolume() { } } function sortPlaylist( pl, iold, inew ) { - G.sortable = 1; - setTimeout( () => G.sortable = 0, 500 ); + V.sortable = 1; + setTimeout( () => V.sortable = 0, 500 ); if ( pl === 'pl-list' ) { bash( [ 'mpcmove', iold + 1, inew + 1 ] ); } else { @@ -1777,29 +1782,29 @@ function stopAirplay() { function switchPage( page ) { clearIntervalAll(); // get scroll position before changed - if ( G.library ) { - if ( G.librarylist ) { - G.liscrolltop = $( window ).scrollTop(); + if ( V.library ) { + if ( V.librarylist ) { + V.liscrolltop = $( window ).scrollTop(); } else { - G.modescrolltop = $( window ).scrollTop(); + V.modescrolltop = $( window ).scrollTop(); } - if ( G.color ) $( '#colorcancel' ).click(); - } else if ( G.playlist ) { - var savedlist = G.savedlist || G.savedplaylist; - if ( savedlist ) G.plscrolltop = $( window ).scrollTop(); - } - G.library = G.playback = G.playlist = 0; - G[ page ] = 1; - G.page = page; + if ( V.color ) $( '#colorcancel' ).click(); + } else if ( V.playlist ) { + var savedlist = V.savedlist || V.savedplaylist; + if ( savedlist ) V.plscrolltop = $( window ).scrollTop(); + } + V.library = V.playback = V.playlist = 0; + V[ page ] = 1; + V.page = page; displayBottom(); // restore page scroll - if ( G.playback ) { + if ( V.playback ) { $( 'html, body' ).scrollTop( 0 ); vu(); - } else if ( G.library ) { - G.librarylist ? $( 'html, body' ).scrollTop( G.liscrolltop ) : renderLibrary(); + } else if ( V.library ) { + V.librarylist ? $( 'html, body' ).scrollTop( V.liscrolltop ) : renderLibrary(); } else { - if ( savedlist ) $( 'html, body' ).scrollTop( G.plscrolltop ); + if ( savedlist ) $( 'html, body' ).scrollTop( V.plscrolltop ); } $( '.page, .menu' ).addClass( 'hide' ); $( '#page-'+ page ).removeClass( 'hide' ); @@ -1839,53 +1844,53 @@ function volumeBarHide() { $( '.volumeband' ).addClass( 'transparent' ); } function volumeBarSet( pageX ) { - clearTimeout( G.volumebar ); + clearTimeout( V.volumebar ); if ( pageX === 'toggle' ) { - var vol = G.status.volumemute || 0; + var vol = S.volumemute || 0; var cmd = [ 'volume' ]; } else { var posX = pageX - $( '#volume-band' ).offset().left; var bandW = $( '#volume-band' ).width(); posX = posX < 0 ? 0 : ( posX > bandW ? bandW : posX ); var vol = Math.round( posX / bandW * 100 ); - var cmd = [ 'volume', G.status.volume, vol, G.status.card, G.status.control ] + var cmd = [ 'volume', S.volume, vol, S.card, S.control ] } - if ( G.drag ) { + if ( V.drag ) { $( '#volume-bar' ).css( 'width', vol +'%' ); - bash( [ 'volume', 'drag', vol, G.status.card, G.status.control ] ); + bash( [ 'volume', 'drag', vol, S.card, S.control ] ); } else { - var ms = Math.ceil( Math.abs( vol - G.status.volume ) / 5 ) * 0.2 * 1000; + var ms = Math.ceil( Math.abs( vol - S.volume ) / 5 ) * 0.2 * 1000; $( '#volume-bar' ).animate( { width: vol +'%' } , { duration : ms , easing : 'linear' - , complete : () => G.volumebar = setTimeout( volumeBarHide, 3000 ) + , complete : () => V.volumebar = setTimeout( volumeBarHide, 3000 ) } ); $( '.volumeband' ).addClass( 'disabled' ); bash( cmd, () => $( '.volumeband' ).removeClass( 'disabled' ) ); } - $( '#volume-text' ).text( G.status.volumemute || vol ); + $( '#volume-text' ).text( S.volumemute || vol ); $( '#i-mute, #ti-mute' ).addClass( 'hide' ); - G.status.volume = vol; - $volumeRS.setValue( G.status.volume ); + S.volume = vol; + $volumeRS.setValue( S.volume ); } function volumeBarShow() { - if ( G.status.volumenone || ! $( '#volume-bar' ).hasClass( 'hide' ) ) return + if ( S.volumenone || ! $( '#volume-bar' ).hasClass( 'hide' ) ) return - G.volumebar = setTimeout( volumeBarHide, 3000 ); + V.volumebar = setTimeout( volumeBarHide, 3000 ); $( '#volume-text' ) - .text( G.status.volumemute === 0 ? G.status.volume : G.status.volumemute ) - .toggleClass( 'bl', G.status.volumemute !== 0 ); - $( '#volume-bar' ).css( 'width', G.status.volume +'%' ); + .text( S.volumemute === 0 ? S.volume : S.volumemute ) + .toggleClass( 'bl', S.volumemute !== 0 ); + $( '#volume-bar' ).css( 'width', S.volume +'%' ); $( '#volume-bar, #volume-text' ).removeClass( 'hide' ); $( '#volume-band-dn, #volume-band-up' ).removeClass( 'transparent' ); } function volumeColorMute() { $volumetooltip - .text( G.status.volumemute ) + .text( S.volumemute ) .addClass( 'bl' ); $volumehandle.addClass( 'bgr60' ); $( '#volmute' ) @@ -1905,8 +1910,8 @@ function volumeColorUnmute() { $( '#i-mute, #ti-mute' ).addClass( 'hide' ); } function vu() { - if ( G.status.state !== 'play' || G.display.vumeter || $( '#vu' ).hasClass( 'hide' ) ) { - clearInterval( G.intVu ); + if ( S.state !== 'play' || D.vumeter || $( '#vu' ).hasClass( 'hide' ) ) { + clearInterval( V.intVu ); $( '#vuneedle' ).css( 'transform', '' ); return } @@ -1915,9 +1920,9 @@ function vu() { var range = 8; // -/+ var deg = 0; var inc; - clearInterval( G.intVu ); + clearInterval( V.intVu ); $( '#vuneedle' ).css( 'transform', 'rotate( '+ Math.random() * range +'deg )' ); - G.intVu = setInterval( () => { + V.intVu = setInterval( () => { inc = Math.random() * range * 2; deg += inc; if ( deg < -range ) { diff --git a/srv/http/assets/js/main.js b/srv/http/assets/js/main.js index fc3d1ea15..caac77941 100644 --- a/srv/http/assets/js/main.js +++ b/srv/http/assets/js/main.js @@ -1,4 +1,8 @@ -G = { +C = {}; // counts +D = {}; // display +O = []; // order +S = {}; // status +V = { // var global addplay : 0 , apikeyfanart : '06f56465de874e4c75a2e9f0cc284fa3' , apikeylastfm : 'd666cd06ec4fcf84c3b86279831a1c8e' @@ -7,8 +11,6 @@ G = { , coverart : '/assets/img/coverart.svg' , coversave : 0 , covervu : '/assets/img/vu.svg' - , debounce : '' - , debouncems : 300 , guide : 0 , library : 0 , librarylist : 0 @@ -85,7 +87,7 @@ if ( navigator.maxTouchPoints ) { // swipeleft / right ///////////////////////// var xstart; window.addEventListener( 'touchstart', function( e ) { var $target = $( e.target ); - if ( G.display.noswipe + if ( D.noswipe || [ 'time-band', 'time-knob', 'volume-band', 'volume-knob' ].includes( e.target.id ) || $target.parents( '#time-knob' ).length || $target.parents( '#volume-knob' ).length @@ -100,7 +102,7 @@ if ( navigator.maxTouchPoints ) { // swipeleft / right ///////////////////////// if ( ! xstart ) return var diff = xstart - e.changedTouches[ 0 ].pageX; - if ( Math.abs( diff ) > 100 ) $( '#'+ pagenext[ G.page ][ diff > 0 ? 1 : 0 ] ).click(); + if ( Math.abs( diff ) > 100 ) $( '#'+ pagenext[ V.page ][ diff > 0 ? 1 : 0 ] ).click(); xstart = 0; } ); } else { @@ -122,13 +124,13 @@ $( '#loader' ).click( function() { loaderHide(); } ); $( '#coverart' ).on( 'load', function() { - if ( G.status.player === 'mpd' && G.status.coverart.slice( 10, 16 ) === 'online' && G.status.file.slice( 0, 4 ) !== 'http' ) { + if ( ! S.stream && S.player === 'mpd' && S.coverart.slice( 0, 16 ) === '/data/shm/online' ) { $( '#coverart' ).after( icoversave ); } else { $( '#divcover .coveredit' ).remove(); $( '#coverart' ).css( 'opacity', '' ); } - if ( ( G.wW - $( '#divcover' ).width() ) < 80 ) { + if ( ( V.wW - $( '#divcover' ).width() ) < 80 ) { $( '#volume-band-dn' ).css( 'left', 0 ); $( '#volume-band-up' ).css( 'right', 0 ); } else { @@ -143,15 +145,15 @@ $( '#logo, #button-library, #button-playlist, #refresh' ).press( function() { location.reload(); } ); $( '#logo, #refresh' ).click( function() { - if ( ! G.localhost ) window.open( 'https://github.com/rern/rAudio-1/discussions' ); + if ( ! V.localhost ) window.open( 'https://github.com/rern/rAudio-1/discussions' ); } ); $( '#status' ).click( function() { - $( '#data' ).html( highlightJSON( G.status ) ) + $( '#data' ).html( highlightJSON( S ) ) $( '#button-data, #data' ).removeClass( 'hide' ); $( '.page' ).addClass( 'hide' ); } ); $( '#button-data' ).click( function() { - $( '#page-'+ G.page ).removeClass( 'hide' ); + $( '#page-'+ V.page ).removeClass( 'hide' ); $( '#button-data, #data' ).addClass( 'hide' ); } ); $( '#button-settings' ).click( function( e ) { @@ -186,7 +188,7 @@ $( '#settings' ).on( 'click', '.submenu', function() { case 'snapclient': var active = $( this ).hasClass( 'on' ); if ( active ) { - if ( G.status.snapclient ) { + if ( S.snapclient ) { bash( '/srv/http/bash/snapcast.sh stop' ); } else { $( '#stop' ).click(); @@ -208,24 +210,24 @@ $( '#settings' ).on( 'click', '.submenu', function() { break; case 'relays': $( '#stop' ).click(); - bash( '/srv/http/bash/settings/relays.sh '+ ! G.status.relayson ); + bash( '/srv/http/bash/settings/relays.sh '+ ! S.relayson ); break; case 'guide': location.href = 'settings.php?p=guide'; break; case 'screenoff': bash( [ 'screenoff', 'dpms force off' ] ); - G.screenoff = 1; + V.screenoff = 1; break; case 'update': infoUpdate( '' ); break; case 'displaycolor': - G.color = 1; - if ( ! G.library ) { + V.color = 1; + if ( ! V.library ) { $( '#library' ).click(); } else { - G.mode !== 'webradio' && $( '#mode-webradio' ).click() || colorSet(); + V.mode !== 'webradio' && $( '#mode-webradio' ).click() || colorSet(); } break; case 'multiraudio': @@ -271,10 +273,10 @@ $( '#displayplayback' ).click( function() { , buttons : 'Buttons' , noswipe : 'Disable swipe' } - if ( 'coverTL' in G ) $( '#coverTL' ).click(); + if ( 'coverTL' in V ) $( '#coverTL' ).click(); var keys = Object.keys( chkplayback ); var values = []; - keys.forEach( k => values.push( G.display[ k ] ) ); + keys.forEach( k => values.push( D[ k ] ) ); info( { icon : 'playback' , title : 'Playback' @@ -303,14 +305,14 @@ $( '#displayplayback' ).click( function() { .prop( 'checked', check ) .parent().toggleClass( 'gr', ! enable ); } - if ( ! G.display.bars ) displayInfoChk( $el.barsalways ); - if ( ! G.display.cover ) displayInfoChk( $el.vumeter ); - if ( G.display.volumenone ) displayInfoChk( $el.volume, 0, 0 ); - if ( ! G.display.time && ! G.display.volume ) { + if ( ! D.bars ) displayInfoChk( $el.barsalways ); + if ( ! D.cover ) displayInfoChk( $el.vumeter ); + if ( D.volumenone ) displayInfoChk( $el.volume, 0, 0 ); + if ( ! D.time && ! D.volume ) { displayInfoChk( $el.cover ); displayInfoChk( $el.buttons ); } - if ( ! G.display.time && ! G.display.cover ) displayInfoChk( $el.bars, 0, 1 ); + if ( ! D.time && ! D.cover ) displayInfoChk( $el.bars, 0, 1 ); $el.time.add( $el.volume ).change( function() { var t = $el.time.prop( 'checked' ); var c = $el.cover.prop( 'checked' ); @@ -322,7 +324,7 @@ $( '#displayplayback' ).click( function() { displayInfoChk( $el.cover, 0, 1 ); displayInfoChk( $el.buttons, 0, 0 ); } - if ( ! t && ( ! v || G.display.volumenone ) ) displayInfoChk( $el.cover, 1, 1 ); + if ( ! t && ( ! v || D.volumenone ) ) displayInfoChk( $el.cover, 1, 1 ); displayInfoBars( t, c ); } ); $el.bars.change( function() { @@ -341,7 +343,7 @@ $( '#displayplayback' ).click( function() { $el.covervu.add( $el.vumeter ).prop( 'disabled', 0 ); } else { displayInfoChk( $el.vumeter, 0, 0 ); - if ( ! t && ( ! v || G.display.volumenone ) ) displayInfoChk( $el.time, 1, 1 ); + if ( ! t && ( ! v || D.volumenone ) ) displayInfoChk( $el.time, 1, 1 ); displayInfoChk( $el.covervu, 0, 0 ); displayInfoChk( $el.vumeter, 0, 0 ); $el.covervu.add( $el.vumeter ).prop( 'disabled', 1 ); @@ -364,10 +366,10 @@ $( '#displayplaylist' ).click( function() { , plsimilar : 'Confirm on Add similar' , audiocdplclear : 'Clear on Audio CD load' } - if ( 'coverTL' in G ) $( '#coverTL' ).click(); + if ( 'coverTL' in V ) $( '#coverTL' ).click(); var keys = Object.keys( chkplaylist ); var values = []; - keys.forEach( k => values.push( G.display[ k ] ) ); + keys.forEach( k => values.push( D[ k ] ) ); info( { icon : 'playlist' , title : 'Playlist' @@ -380,7 +382,7 @@ $( '#displayplaylist' ).click( function() { } ); } ); $( '#colorok' ).click( function() { - var hsv = G.colorpicker.getCurColorHsv(); // hsv = { h: N, s: N, v: N } N = 0-1 + var hsv = V.colorpicker.getCurColorHsv(); // hsv = { h: N, s: N, v: N } N = 0-1 var s = hsv.s; var v = hsv.v; var L = ( 2 - s ) * v / 2; @@ -408,8 +410,8 @@ $( '#colorcancel' ).click( function() { , #lib-list li, #lib-list li.active, #lib-list i, #lib-list .li2 \ , .menu a, .submenu, #colorcancel, #colorok' ).removeAttr( 'style' ); $( 'body' ).removeClass( 'disablescroll' ); - if ( G.status.player !== 'mpd' ) switchPage( 'playback' ); - G.colorpicker.destroy(); + if ( S.player !== 'mpd' ) switchPage( 'playback' ); + V.colorpicker.destroy(); } ); $( '#colorpicker' ).click( function( e ) { if ( e.target.id === 'colorpicker' ) $( '#colorcancel' ).click(); @@ -432,7 +434,7 @@ $( '#addons' ).click( function () { loader(); } ); $( '#library, #button-library' ).click( function() { - if ( G.library && G.librarylist ) { + if ( V.library && V.librarylist ) { libraryHome(); } else { switchPage( 'library' ); @@ -440,7 +442,7 @@ $( '#library, #button-library' ).click( function() { } } ); $( '#playback' ).click( function() { - if ( G.playback && ( G.wH - $( '#coverart' )[ 0 ].getBoundingClientRect().bottom ) < 30 ) { + if ( V.playback && ( V.wH - $( '#coverart' )[ 0 ].getBoundingClientRect().bottom ) < 30 ) { $( '#stop' ).click(); } else { getPlaybackStatus(); @@ -448,19 +450,19 @@ $( '#playback' ).click( function() { } } ); $( '#playlist, #button-playlist' ).click( function() { - if ( ! G.local ) G.pladd = {} - var savedpl = G.savedlist || G.savedplaylist; - if ( G.playlist ) { + if ( ! V.local ) V.pladd = {} + var savedpl = V.savedlist || V.savedplaylist; + if ( V.playlist ) { if ( savedpl ) getPlaylist(); } else { savedpl ? switchPage( 'playlist' ) : getPlaylist(); // switchPage( 'playlist' ) in setPlaylistScroll() } } ); $( '#page-playback' ).click( function( e ) { - if ( G.press + if ( V.press || [ 'coverT', 'timeT', 'volume-bar', 'volume-band', 'volume-band-dn', 'volume-band-up' ].includes( e.target.id ) ) return - if ( G.guide ) hideGuide(); + if ( V.guide ) hideGuide(); if ( $( '#divcover .coveredit' ).length ) { if ( ! $( e.target ).hasClass( 'coveredit' ) ) { $( '#divcover .cover-change' ).remove(); @@ -469,7 +471,7 @@ $( '#page-playback' ).click( function( e ) { } } ); $( '#bar-top, #bar-bottom, #page-library' ).click( function() { - if ( G.guide ) hideGuide(); + if ( V.guide ) hideGuide(); if ( ! $( '#colorpicker' ).hasClass( 'hide' ) ) $( '#colorcancel' ).click(); } ); $( '#bar-top' ).click( function( e ) { @@ -479,12 +481,12 @@ $( '#settings' ).click( function() { $( this ).addClass( 'hide' ); } ); $( '#page-library, #page-playlist' ).on( 'click', 'p', function() { - if ( G.library ) { + if ( V.library ) { $( '.licover .cover-change' ).remove(); $( '.licover img' ).css( 'opacity', '' ); $( '#lib-list li' ).removeClass( 'active' ); if ( ! $( '#lib-search-input' ).val() ) $( '#lib-search-close' ).click(); - } else if ( G.playlist && ! G.savedlist && ! G.savedplaylist ) { + } else if ( V.playlist && ! V.savedlist && ! V.savedplaylist ) { $( '#pl-savedlist li' ).removeClass( 'active' ); $( '#pl-list li' ).removeClass( 'updn' ); $( '#pl-list .name' ).css( 'max-width', '' ); @@ -493,7 +495,7 @@ $( '#page-library, #page-playlist' ).on( 'click', 'p', function() { } ); // PLAYBACK ///////////////////////////////////////////////////////////////////////////////////// $( '#info' ).click( function() { - if ( G.localhost ) setInfoScroll(); + if ( V.localhost ) setInfoScroll(); } ); $( '.emptyadd' ).click( function( e ) { if ( $( e.target ).hasClass( 'fa-plus-circle' ) ) { @@ -503,7 +505,7 @@ $( '.emptyadd' ).click( function( e ) { } } ); $( '#artist, #guide-bio' ).click( function() { - if ( $( '#bio legend' ).text() != G.status.Artist ) { + if ( $( '#bio legend' ).text() != S.Artist ) { getBio( $( '#artist' ).text() ); } else { $( '#bar-top, #bar-bottom' ).addClass( 'hide' ); @@ -515,8 +517,8 @@ $( '#title, #guide-lyrics' ).click( function() { var title = $( '#title' ).text(); var album = $( '#album' ).text(); if ( album.includes( '://' ) ) album = ''; - if ( G.lyrics - && ! G.status.webradio + if ( V.lyrics + && ! S.webradio && artist === $( '#lyricsartist' ).text() && title === $( '#lyricstitle' ).text() ) { @@ -526,9 +528,9 @@ $( '#title, #guide-lyrics' ).click( function() { artist = artist.replace( /(["`])/g, '\\$1' ); title = title.replace( /(["`])/g, '\\$1' ); - file = G.status.player === 'mpd' ? '/mnt/MPD/'+ G.status.file : ''; + file = S.player === 'mpd' ? '/mnt/MPD/'+ S.file : ''; var src = $( '#coverart' ).attr( 'src' ); - G.lyricsCover = src.slice( 0, 7 ) === '/asses' ? '' : src; + V.lyricsCover = src.slice( 0, 7 ) === '/asses' ? '' : src; var noparen = title.slice( -1 ) !== ')'; var titlenoparen = title.replace( / $|\(.*$/, '' ); var paren = title.replace( /^.*\(/, '(' ); @@ -566,29 +568,29 @@ $( '#title, #guide-lyrics' ).click( function() { $( '#infoContent .scrobble' ).toggleClass( 'disabled', $this.val() === '' ); } ); $( '#infoContent .album' ).toggleClass( 'hide', album === '' ); - $( '#infoContent .pladd' ).toggleClass( 'hide', G.status.player !== 'mpd' ); - $( '#infoContent .scrobble' ).toggleClass( 'hide', ! G.status.scrobble || ! G.status.webradio ); + $( '#infoContent .pladd' ).toggleClass( 'hide', S.player !== 'mpd' ); + $( '#infoContent .scrobble' ).toggleClass( 'hide', ! S.scrobble || ! S.webradio ); $( '#infoContent' ).on( 'click', '.btnbottom span', function() { var values = infoVal(); var artist = values[ 0 ] var title = values[ 1 ] var $this = $( this ); if ( $this.hasClass( 'lyrics' ) ) { - G.lyricsArtist = artist; - G.lyricsTitle = title; + V.lyricsArtist = artist; + V.lyricsTitle = title; bash( [ 'lyrics', artist, title, file ], data => { lyricsShow( data ); } ); banner( 'search blink', 'Lyrics', 'Fetch ...', 20000 ); } else if ( $this.hasClass( 'bio' ) ) { - if ( $( '#bio legend' ).text() != G.status.Artist ) { + if ( $( '#bio legend' ).text() != S.Artist ) { getBio( artist ); } else { $( '#bar-top, #bar-bottom' ).addClass( 'hide' ); $( '#bio' ).removeClass( 'hide' ); } } else if ( $this.hasClass( 'pladd' ) ) { - saveToPlaylist( G.status.Title, G.status.Album, G.status.file ); + saveToPlaylist( S.Title, S.Album, S.file ); } else if ( $this.hasClass( 'scrobble' ) ) { bash( [ 'scrobble', ...values ] ); banner( 'lastfm blink', 'Scrobble', 'Send ...' ); @@ -600,7 +602,7 @@ $( '#title, #guide-lyrics' ).click( function() { } ); } ); $( '#album, #guide-album' ).click( function() { - if ( ! G.localhost ) window.open( 'https://www.last.fm/music/'+ $( '#artist' ).text() +'/'+ $( '#album' ).text(), '_blank' ); + if ( ! V.localhost ) window.open( 'https://www.last.fm/music/'+ $( '#artist' ).text() +'/'+ $( '#album' ).text(), '_blank' ); } ); $( '#infoicon' ).on( 'click', '.fa-audiocd', function() { info( { @@ -612,7 +614,7 @@ $( '#infoicon' ).on( 'click', '.fa-audiocd', function() { } ); } ); $( '#elapsed' ).click( function() { - G.status.state === 'play' ? $( '#pause' ).click() : $( '#play' ).click(); + S.state === 'play' ? $( '#pause' ).click() : $( '#play' ).click(); } ); $( '#time' ).roundSlider( { sliderType : 'min-range' @@ -629,10 +631,10 @@ $( '#time' ).roundSlider( { $timeprogress = $( '#time .rs-transition, #time-bar' ); } , start : function () { // drag start - G.drag = 1; + V.drag = 1; clearIntervalAll(); $( '.map' ).removeClass( 'mapshow' ); - if ( G.status.state !== 'play' ) $( '#title' ).addClass( 'gr' ); + if ( S.state !== 'play' ) $( '#title' ).addClass( 'gr' ); } , drag : function ( e ) { // drag with no transition by default $( '#elapsed' ).text( second2HMS( e.value ) ); @@ -642,25 +644,25 @@ $( '#time' ).roundSlider( { mpcSeek( e.value ); } , stop : function() { - G.drag = 0; + V.drag = 0; } } ); $( '#time-band' ).on( 'touchstart mousedown', function() { - if ( G.status.player !== 'mpd' || G.status.stream ) return + if ( S.player !== 'mpd' || S.stream ) return - G.start = 1; + V.start = 1; hideGuide(); clearIntervalAll(); - if ( G.status.state !== 'play' ) $( '#title' ).addClass( 'gr' ); + if ( S.state !== 'play' ) $( '#title' ).addClass( 'gr' ); } ).on( 'touchmove mousemove', function( e ) { - if ( ! G.start ) return + if ( ! V.start ) return - G.drag = 1; + V.drag = 1; mpcSeekBar( e.pageX || e.changedTouches[ 0 ].pageX ); } ).on( 'touchend mouseup', function( e ) { - if ( ! G.start ) return + if ( ! V.start ) return - G.start = G.drag = 0; + V.start = V.drag = 0; mpcSeekBar( e.pageX || e.changedTouches[ 0 ].pageX ); } ); $( '#volume' ).roundSlider( { @@ -679,58 +681,58 @@ $( '#volume' ).roundSlider( { , editableTooltip : false , animation : false , create : function () { - G.create = 1; + V.create = 1; $volumeRS = this; $volumetooltip = $( '#volume .rs-tooltip' ); $volumehandle = $( '#volume .rs-handle' ); $volumehandlerotate = $( '#volume .rs-transition, #volume .rs-handle' ); } , start : function( e ) { - G.drag = 1; + V.drag = 1; if ( e.value === 0 ) volumeColorUnmute(); // restore handle color immediately on start drag $( '.map' ).removeClass( 'mapshow' ); } , beforeValueChange : function( e ) { - if ( G.local || G.drag ) return + if ( V.local || V.drag ) return - var diff = e.value - G.status.volume || G.status.volume - G.status.volumemute; // change || mute/unmute + var diff = e.value - S.volume || S.volume - S.volumemute; // change || mute/unmute var speed = Math.round( Math.abs( diff ) / 5 * 0.2 * 10 ) / 10; // @5 0.2s > round 1 digit: * 10 / 10 $volumehandlerotate.css( 'transition-duration', speed +'s' ); setTimeout( () => $volumehandlerotate.css( 'transition-duration','' ), speed * 1000 + 500 ); } , drag : function( e ) { - G.status.volume = e.value; + S.volume = e.value; $volumehandle.rsRotate( - this._handle1.angle ); - bash( [ 'volume', 'drag', e.value, G.status.card, G.status.control ] ); + bash( [ 'volume', 'drag', e.value, S.card, S.control ] ); } , change : function( e ) { - if ( G.drag ) return + if ( V.drag ) return $( '#volume-knob, #vol-group i' ).addClass( 'disabled' ); - bash( [ 'volume', G.status.volume, e.value, G.status.card, G.status.control ] ); + bash( [ 'volume', S.volume, e.value, S.card, S.control ] ); $volumehandle.rsRotate( - this._handle1.angle ); } , valueChange : function( e ) { - if ( G.drag || ! G.create ) return // ! G.create - suppress fire before 'create' + if ( V.drag || ! V.create ) return // ! V.create - suppress fire before 'create' - G.status.volume = e.value; + S.volume = e.value; $volumehandle.rsRotate( - this._handle1.angle ); } , stop : function() { - G.drag = 0; + V.drag = 0; bash( [ 'volumepushstream' ] ); } } ); $( '#volume-band' ).on( 'touchstart mousedown', function() { hideGuide(); - clearTimeout( G.volumebar ); - if ( G.status.volumenone || $( '#volume-bar' ).hasClass( 'hide' ) ) return + clearTimeout( V.volumebar ); + if ( S.volumenone || $( '#volume-bar' ).hasClass( 'hide' ) ) return - G.start = 1; + V.start = 1; } ).on( 'touchmove mousemove', function( e ) { - if ( ! G.start ) return + if ( ! V.start ) return - G.drag = 1; + V.drag = 1; volumeBarSet( e.pageX || e.changedTouches[ 0 ].pageX ); } ).on( 'touchend mouseup', function( e ) { if ( $( '#volume-bar' ).hasClass( 'hide' ) ) { @@ -738,9 +740,9 @@ $( '#volume-band' ).on( 'touchstart mousedown', function() { return } - if ( ! G.start ) return + if ( ! V.start ) return - G.start = G.drag = 0; + V.start = V.drag = 0; volumeBarSet( e.pageX || e.changedTouches[ 0 ].pageX ); } ); $( '#volmute, #volM' ).click( function() { @@ -749,36 +751,36 @@ $( '#volmute, #volM' ).click( function() { } ); $( '#volup, #voldn, #volT, #volB, #volL, #volR' ).click( function( e ) { var voldn = [ 'voldn', 'volB', 'volL' ].includes( e.currentTarget.id ); - if ( ( G.status.volume === 0 && voldn ) || ( G.status.volume === 100 && ! voldn ) ) return + if ( ( S.volume === 0 && voldn ) || ( S.volume === 100 && ! voldn ) ) return - bash( [ 'volumeupdown', voldn ? '-' : '+', G.status.card, G.status.control ] ); + bash( [ 'volumeupdown', voldn ? '-' : '+', S.card, S.control ] ); } ).on( 'touchend mouseup mouseleave', function() { - if ( G.volhold ) { - G.volhold = 0; - clearInterval( G.intVolume ); + if ( V.volhold ) { + V.volhold = 0; + clearInterval( V.intVolume ); bash( [ 'volumepushstream' ] ); } } ).press( function( e ) { - G.volhold = 1; + V.volhold = 1; var voldn = e.currentTarget.id === 'voldn'; var voldn = [ 'voldn', 'volB', 'volL' ].includes( e.currentTarget.id ); - var vol = G.status.volume; + var vol = S.volume; if ( ( vol === 0 && voldn ) || ( vol === 100 && ! voldn ) ) return - G.intVolume = setInterval( () => { + V.intVolume = setInterval( () => { if ( ( vol === 0 && voldn ) || ( vol === 100 && ! voldn ) ) return voldn ? vol-- : vol++; $volumeRS.setValue( vol ); - bash( [ 'volume', 'drag', vol, G.status.card, G.status.control ] ); + bash( [ 'volume', 'drag', vol, S.card, S.control ] ); }, 100 ); } ); $( '#volume-band-dn, #volume-band-up' ).click( function() { hideGuide(); - if ( G.status.volumenone ) return + if ( S.volumenone ) return var updn = this.id.slice( -2 ); - var vol = G.status.volume; + var vol = S.volume; if ( updn === 'dn' ) { if ( vol > 0 ) vol--; } else { @@ -790,37 +792,37 @@ $( '#volume-band-dn, #volume-band-up' ).click( function() { $( '#volume-bar' ).css( 'width', vol +'%' ); } ).on( 'touchend mouseup mouseleave', function() { bash( [ 'volumepushstream' ] ); - clearTimeout( G.intVolume ); - clearTimeout( G.volumebar ); + clearTimeout( V.intVolume ); + clearTimeout( V.volumebar ); setTimeout( volumeBarHide, 3000 ); } ).press( function( e ) { - if ( G.status.volumenone ) return + if ( S.volumenone ) return - clearTimeout( G.volumebar ); + clearTimeout( V.volumebar ); $( '#volume-bar, #volume-text' ).removeClass( 'hide' ); var voldn = e.currentTarget.id === 'volume-band-dn'; - var vol = G.status.volume; + var vol = S.volume; if ( ( vol === 0 && voldn ) || ( vol === 100 && ! voldn ) ) return - G.intVolume = setInterval( () => { + V.intVolume = setInterval( () => { if ( ( vol === 0 && voldn ) || ( vol === 100 && ! voldn ) ) return voldn ? vol-- : vol++; - G.status.volume = vol; + S.volume = vol; $( '#volume-text' ).text( vol ); $( '#volume-bar' ).css( 'width', vol +'%' ); - bash( [ 'volume', 'drag', vol, G.status.card, G.status.control ] ); + bash( [ 'volume', 'drag', vol, S.card, S.control ] ); }, 100 ); } ); $( '#volume-text' ).click( function() { // mute / unmute - clearTimeout( G.volumebar ); + clearTimeout( V.volumebar ); volumeBarSet( 'toggle' ); } ); $( '#divcover' ).press( function( e ) { if ( - ( G.status.stream && G.status.state === 'play' ) - || ! G.status.pllength - || G.guide + ( S.stream && S.state === 'play' ) + || ! S.pllength + || V.guide || $( e.target ).hasClass( 'band' ) || e.target.id === 'coverT' ) return @@ -831,7 +833,7 @@ $( '#divcover' ).press( function( e ) { } ).on( 'click', '.cover-save', function() { coverartSave(); } ).on( 'click', '.cover-change', function() { - G.status.webradio ? webRadioCoverart() : coverartChange(); + S.webradio ? webRadioCoverart() : coverartChange(); } ); $( '#coverT' ).press( function() { if ( typeof Android === 'object' ) { @@ -862,11 +864,11 @@ var btnctrl = { } $( '.map' ).click( function( e ) { e.stopPropagation(); - if ( G.press ) return + if ( V.press ) return if ( $( '#info' ).hasClass( 'hide' ) ) { $( '#info' ).removeClass( 'hide' ); - clearTimeout( G.volumebar ); + clearTimeout( V.volumebar ); volumeBarHide(); return @@ -875,30 +877,30 @@ $( '.map' ).click( function( e ) { $( '#coverart' ).css( 'opacity', '' ); return - } else if ( 'screenoff' in G ) { - delete G.screenoff; + } else if ( 'screenoff' in V ) { + delete V.screenoff; return } var cmd = btnctrl[ this.id ]; if ( cmd === 'guide' ) { - clearTimeout( G.volumebar ); - if ( G.guide ) { + clearTimeout( V.volumebar ); + if ( V.guide ) { hideGuide(); return } - G.guide = 1; + V.guide = 1; var time = $time.is( ':visible' ); var volume = $volume.is( ':visible' ); $( '#coverTR' ).removeClass( 'empty' ); $( '.covermap, .guide' ).addClass( 'mapshow' ); - $( '.guide' ).toggleClass( 'hide', ! G.status.pllength && G.status.player === 'mpd' ); - $( '#guide-bio, #guide-lyrics' ).toggleClass( 'hide', G.status.stream && G.status.state === 'stop' ); + $( '.guide' ).toggleClass( 'hide', ! S.pllength && S.player === 'mpd' ); + $( '#guide-bio, #guide-lyrics' ).toggleClass( 'hide', S.stream && S.state === 'stop' ); $( '#guide-album' ).toggleClass( 'hide', $( '#album' ).hasClass( 'disabled' ) ); - $( '#guide-bio, #guide-lyrics, #guide-album' ).toggleClass( 'hide', ! G.status.pllength ); - $( '#coverL, #coverM, #coverR, #coverB' ).toggleClass( 'disabled', ! G.status.pllength ); - $( '.timemap' ).toggleClass( 'mapshow', ! G.display.cover ); + $( '#guide-bio, #guide-lyrics, #guide-album' ).toggleClass( 'hide', ! S.pllength ); + $( '#coverL, #coverM, #coverR, #coverB' ).toggleClass( 'disabled', ! S.pllength ); + $( '.timemap' ).toggleClass( 'mapshow', ! D.cover ); $( '.volmap' ).toggleClass( 'mapshow', volume ); $( '#bar-bottom' ).toggleClass( 'translucent', $bartop.is( ':hidden' ) ); if ( time || volume ) { @@ -910,13 +912,13 @@ $( '.map' ).click( function( e ) { .removeClass( 'fa-scale-up' ) .addClass( 'fa-scale-dn' ); } - if ( G.status.player === 'mpd' ) { - if ( ! time && ! G.status.stream ) { + if ( S.player === 'mpd' ) { + if ( ! time && ! S.stream ) { $( '#time-band' ) .removeClass( 'transparent' ) - .text( G.status.Time ? second2HMS( G.status.Time ) : '' ); + .text( S.Time ? second2HMS( S.Time ) : '' ); } - if ( ! volume && ! G.display.volumenone ) { + if ( ! volume && ! D.volumenone ) { $( '.volumeband' ).removeClass( 'transparent hide' ); $( '#volume-bar' ).removeClass( 'hide' ); } @@ -930,9 +932,9 @@ $( '.map' ).click( function( e ) { switch ( cmd ) { case 'cover': $( '#bar-bottom' ).removeClass( 'translucent' ); - if ( ! ( 'coverTL' in G ) - && ( G.wH - $( '#coverart' )[ 0 ].getBoundingClientRect().bottom ) < 40 - && ! G.display.volumenone + if ( ! ( 'coverTL' in V ) + && ( V.wH - $( '#coverart' )[ 0 ].getBoundingClientRect().bottom ) < 40 + && ! D.volumenone && $volume.is( ':hidden' ) ) { if ( $( '#info' ).hasClass( 'hide' ) ) { @@ -945,43 +947,43 @@ $( '.map' ).click( function( e ) { } var list = [ 'bars', 'time', 'cover', 'volume', 'buttons' ]; - if ( 'coverTL' in G ) { - list.forEach( el => G.display[ el ] = G.coverTL[ el ] ); - delete G.coverTL; + if ( 'coverTL' in V ) { + list.forEach( el => D[ el ] = V.coverTL[ el ] ); + delete V.coverTL; } else { - G.coverTL = {}; - list.forEach( el => G.coverTL[ el ] = G.display[ el ] ); + V.coverTL = {}; + list.forEach( el => V.coverTL[ el ] = D[ el ] ); if ( this.id === 'coverTL' ) { - if ( G.display.time || G.display.volume ) { - G.display.bars = G.display.time = G.display.volume = G.display.buttons = false; + if ( D.time || D.volume ) { + D.bars = D.time = D.volume = D.buttons = false; } else { - G.display.bars = G.display.time = G.display.volume = G.display.buttons = true; + D.bars = D.time = D.volume = D.buttons = true; } } else { - G.display.time = G.display.cover = G.display.volume = G.display.buttons = true; + D.time = D.cover = D.volume = D.buttons = true; } } $( '.band' ).addClass( 'transparent' ); $( '#volume-bar, #volume-text' ).addClass( 'hide' ); - $( '.volumeband' ).toggleClass( 'hide', G.display.volumenone ); + $( '.volumeband' ).toggleClass( 'hide', D.volumenone ); displayBars(); setButtonControl(); displayPlayback(); - if ( G.status.state === 'play' && ! G.status.stream && ! G.localhost ) { + if ( S.state === 'play' && ! S.stream && ! V.localhost ) { setProgress(); setTimeout( setProgressAnimate, 0 ); } - if ( 'coverTL' in G && ! G.display.cover ) $( '#timemap' ).removeClass( 'hide' ); + if ( 'coverTL' in V && ! D.cover ) $( '#timemap' ).removeClass( 'hide' ); break; case 'settings': $( '#button-settings' ).click(); break; case 'repeat': - if ( G.status.repeat ) { - if ( G.status.single ) { + if ( S.repeat ) { + if ( S.single ) { $( '#single' ).click(); - G.status.repeat = false; - G.status.single = false; + S.repeat = false; + S.single = false; setButtonOptions(); local( 600 ); bash( [ 'mpcoption', 'repeat', false ] ); @@ -994,7 +996,7 @@ $( '.map' ).click( function( e ) { } break default: - if ( cmd === 'play' && G.status.state === 'play' ) cmd = ! G.status.stream ? 'pause' : 'stop'; + if ( cmd === 'play' && S.state === 'play' ) cmd = ! S.stream ? 'pause' : 'stop'; $( '#'+ cmd ).click(); } } ); @@ -1002,51 +1004,51 @@ $( '.btn-cmd' ).click( function() { var $this = $( this ); var cmd = this.id; if ( $this.hasClass( 'btn-toggle' ) ) { - var onoff = ! G.status[ cmd ]; - G.status[ cmd ] = onoff; + var onoff = ! S[ cmd ]; + S[ cmd ] = onoff; bash( [ 'mpcoption', cmd, onoff ] ); setButtonOptions(); local( 600 ); } else { - if ( G.status.stream ) { + if ( S.stream ) { $( '#divcover .cover-change' ).remove(); $( '#coverart' ).css( 'opacity', '' ); } if ( cmd === 'play' ) { - if ( G.status.state === 'play' ) return + if ( S.state === 'play' ) return - G.status.state = cmd; - if ( ! G.status.elapsed ) $( '#elapsed' ).empty(); // 0 or false - if ( ! G.status.stream && G.status.elapsed !== false ) setProgressAnimate(); + S.state = cmd; + if ( ! S.elapsed ) $( '#elapsed' ).empty(); // 0 or false + if ( ! S.stream && S.elapsed !== false ) setProgressAnimate(); bash( [ 'mpcplayback', 'play' ] ); $( '#title' ).removeClass( 'gr' ); $( '#elapsed' ).removeClass( 'bl gr' ); $( '#total' ) - .text( second2HMS( G.status.Time ) ) + .text( second2HMS( S.Time ) ) .removeClass( 'wh' ); $( '#progress i' ).removeAttr( 'class' ).addClass( 'fa fa-play' ); - if ( G.status.stream ) $( '#title, #elapsed' ).html( blinkdot ); + if ( S.stream ) $( '#title, #elapsed' ).html( blinkdot ); vu(); } else if ( cmd === 'stop' ) { - G.status.state = cmd; - clearInterval( G.intElapsed ); - clearInterval( G.intElapsedPl ); - elapsedscrobble = G.status.webradio ? '' : G.status.elapsed; - if ( G.status.player !== 'mpd' ) { + S.state = cmd; + clearInterval( V.intElapsed ); + clearInterval( V.intElapsedPl ); + elapsedscrobble = S.webradio ? '' : S.elapsed; + if ( S.player !== 'mpd' ) { bash( [ 'playerstop', elapsedscrobble ] ); - banner( G.status.player, icon_player[ G.status.player ], 'Stop ...' ); + banner( S.player, icon_player[ S.player ], 'Stop ...' ); return } $( '#title' ).removeClass( 'gr' ); - if ( ! G.status.pllength ) return + if ( ! S.pllength ) return bash( [ 'mpcplayback', 'stop', elapsedscrobble ] ); $( '#pl-list .elapsed' ).empty(); - if ( G.playback ) { + if ( V.playback ) { $( '#total' ).empty(); - if ( G.status.Time ) { - var timehms = second2HMS( G.status.Time ); + if ( S.Time ) { + var timehms = second2HMS( S.Time ); setProgress( 0 ); $( '#elapsed' ) .text( timehms ) @@ -1058,37 +1060,37 @@ $( '.btn-cmd' ).click( function() { $( '#elapsed, #progress' ).empty(); vu(); } - if ( G.playback && G.status.stream ) { - [ 'Artist', 'Title', 'Album', 'coverart' ].forEach( el => G.status[ el ] = '' ); + if ( V.playback && S.stream ) { + [ 'Artist', 'Title', 'Album', 'coverart' ].forEach( el => S[ el ] = '' ); setInfo(); setCoverart(); } - } else if ( G.playlist ) { + } else if ( V.playlist ) { $( '#pl-list .song' ).empty(); $( '#pl-list .li1' ).find( '.name, .song' ).css( 'max-width', '' ); $( '#pl-list .li2 .radioname' ).addClass( 'hide' ); $( '#pl-list .li1 .radioname' ).removeClass( 'hide' ); } } else if ( cmd === 'pause' ) { - if ( G.status.state === 'stop' ) return + if ( S.state === 'stop' ) return - G.status.state = cmd; + S.state = cmd; bash( [ 'mpcplayback', 'pause' ] ); $( '#title' ).addClass( 'gr' ); $( '#elapsed' ).addClass( 'bl' ); $( '#total' ).addClass( 'wh' ); $( '#progress i' ).removeAttr( 'class' ).addClass( 'fa fa-pause' ); } else if ( cmd === 'previous' || cmd === 'next' ) { - var pllength = G.status.pllength; - var song = G.status.song; + var pllength = S.pllength; + var song = S.song; if ( pllength < 2 ) return clearIntervalAll(); $timeRS.setValue( 0 ); $( '#elapsed, #total, #progress' ).empty(); - elapsedscrobble = G.status.webradio ? '' : G.status.elapsed || ''; - bash( [ 'mpcprevnext', cmd, song, pllength, G.status.state, elapsedscrobble ] ); - if ( G.playlist ) { + elapsedscrobble = S.webradio ? '' : S.elapsed || ''; + bash( [ 'mpcprevnext', cmd, song, pllength, S.state, elapsedscrobble ] ); + if ( V.playlist ) { $( '#pl-list li.active' ) .removeClass( 'active' ) .find( '.elapsed' ).empty(); @@ -1104,21 +1106,21 @@ $( '#bio' ).on( 'click', '.biosimilar', function() { getBio( $( this ).text(), 'getsimilar' ); } ); $( '#bio' ).on( 'click', '.bioback', function() { - G.bioartist.pop(); - var getsimilar = G.bioartist.length > 1 ? 'getsimilar' : ''; - getBio( G.bioartist.pop(), getsimilar ); + V.bioartist.pop(); + var getsimilar = V.bioartist.length > 1 ? 'getsimilar' : ''; + getBio( V.bioartist.pop(), getsimilar ); } ); $( '#bio' ).on( 'click', '.closebio', function() { - G.bioartist = []; + V.bioartist = []; $( '#bio' ).addClass( 'hide' ); } ); // LIBRARY ///////////////////////////////////////////////////////////////////////////////////// $( '#lib-breadcrumbs' ).on( 'click', 'a', function() { - G.query = []; - delete G.gmode; - if ( G.query.length > 1 ) G.scrolltop[ G.query[ G.query.length - 1 ].modetitle ] = $( window ).scrollTop(); + V.query = []; + delete V.gmode; + if ( V.query.length > 1 ) V.scrolltop[ V.query[ V.query.length - 1 ].modetitle ] = $( window ).scrollTop(); var path = $( this ).find( '.lidir' ).text(); - if ( G.mode.slice( -5 ) === 'radio' ) { + if ( V.mode.slice( -5 ) === 'radio' ) { var query = { query : 'radio' , string : path @@ -1130,9 +1132,9 @@ $( '#lib-breadcrumbs' ).on( 'click', 'a', function() { , format : [ 'file' ] } } - query.gmode = G.mode; + query.gmode = V.mode; list( query, function( html ) { - if ( ! path && G.mode.slice( -5 ) === 'radio' ) path = G.mode.toUpperCase(); + if ( ! path && V.mode.slice( -5 ) === 'radio' ) path = V.mode.toUpperCase(); var data = { html : html , modetitle : path @@ -1188,9 +1190,9 @@ $( '#lib-search-btn' ).click( function() { // search if ( ! keyword ) { $( '#lib-search-close' ).click(); } else { - if ( G.mode.slice( -5 ) === 'radio' ) { + if ( V.mode.slice( -5 ) === 'radio' ) { var query = { - query : G.mode + query : V.mode , string : keyword , mode : 'search' } @@ -1198,7 +1200,7 @@ $( '#lib-search-btn' ).click( function() { // search var query = { query : 'search' , string : keyword - , gmode : G.mode + , gmode : V.mode , format : [ 'album', 'artist', 'file', 'title', 'time', 'track' ] } } @@ -1241,30 +1243,30 @@ $( '#lib-search-input' ).keyup( function( e ) { $( '#button-lib-back' ).click( function() { var $breadcrumbs = $( '#lib-breadcrumbs a' ); var bL = $breadcrumbs.length - var backmode = 'gmode' in G && G.gmode !== G.mode; - if ( G.mode === $( '#mode-title' ).text().replace( ' ', '' ).toLowerCase() + var backmode = 'gmode' in V && V.gmode !== V.mode; + if ( V.mode === $( '#mode-title' ).text().replace( ' ', '' ).toLowerCase() || ( bL && bL < 2 ) - || ( ! bL && G.query.length === 1 ) + || ( ! bL && V.query.length === 1 ) ) { $( '#library' ).click(); - } else if ( bL && G.mode !== 'latest' && ! backmode ) { + } else if ( bL && V.mode !== 'latest' && ! backmode ) { bL > 1 ? $breadcrumbs.eq( -2 ).click() : $( '#library' ).click(); } else { - G.query.pop(); - var query = G.query[ G.query.length - 1 ]; - var backmode = 'gmode' in G && G.gmode !== G.mode; + V.query.pop(); + var query = V.query[ V.query.length - 1 ]; + var backmode = 'gmode' in V && V.gmode !== V.mode; if ( query === 'album' ) { $( '#mode-album' ).click(); } else { - if ( 'gmode' in query ) G.mode = query.gmode; + if ( 'gmode' in query ) V.mode = query.gmode; list( query, function( html ) { if ( html != -1 ) { - if ( backmode ) G.mode = G.gmode; - if ( G.mode === 'album' ) { + if ( backmode ) V.mode = V.gmode; + if ( V.mode === 'album' ) { var path = 'ALBUM'; } else { var path = query.path; - G.scrolltop[ $( '#lib-path .lipath' ).text() ] = $( window ).scrollTop(); + V.scrolltop[ $( '#lib-path .lipath' ).text() ] = $( window ).scrollTop(); } var data = { html : html @@ -1280,17 +1282,17 @@ $( '#button-lib-back' ).click( function() { } } ); $( '#lib-mode-list' ).click( function( e ) { - if ( ! G.press && $( '.bkedit' ).length && ! $( e.target ).hasClass( 'bkedit' ) ) setBookmarkEdit(); + if ( ! V.press && $( '.bkedit' ).length && ! $( e.target ).hasClass( 'bkedit' ) ) setBookmarkEdit(); } ).on( 'click', '.mode', function() { var $this = $( this ); - G.mode = $this.data( 'mode' ); + V.mode = $this.data( 'mode' ); $( '#lib-search-close' ).click(); - if ( G.mode === 'bookmark' ) return + if ( V.mode === 'bookmark' ) return - if ( ! G.counts[ G.mode ] && G.mode.slice( -5 ) !== 'radio' ) { - if ( G.mode === 'playlists' ) { + if ( ! C[ V.mode ] && V.mode.slice( -5 ) !== 'radio' ) { + if ( V.mode === 'playlists' ) { var message = 'No saved playlists found.'; - } else if ( G.mode === 'latest' ) { + } else if ( V.mode === 'latest' ) { var message = 'No new albums added since last update.'; } else { var message = ''+ $this.find( '.label' ).text() +' data not available.' @@ -1305,14 +1307,14 @@ $( '#lib-mode-list' ).click( function( e ) { return } - if ( ! G.color && ! G.counts[ G.mode ] && G.status.updating_db ) { + if ( ! V.color && ! C[ V.mode ] && S.updating_db ) { infoUpdate(); return } - G.modescrolltop = $( window ).scrollTop(); + V.modescrolltop = $( window ).scrollTop(); - if ( G.mode === 'playlists' ) { + if ( V.mode === 'playlists' ) { if ( $( this ).find( 'gr' ).text() ) { $( '#button-pl-playlists' ).click(); $( '#playlist' ).click(); @@ -1320,28 +1322,28 @@ $( '#lib-mode-list' ).click( function( e ) { return } - var path = G.mode.toUpperCase(); - // G.modes: sd, nas, usb, webradio, dabradio, album, artist, albumartist, composer, conductor, genre, playlists + var path = V.mode.toUpperCase(); + // V.modes: sd, nas, usb, webradio, dabradio, album, artist, albumartist, composer, conductor, genre, playlists // ( coverart, bookmark by other functions ) - if ( [ 'sd', 'nas', 'usb' ].includes( G.mode ) ) { // browse by directory + if ( [ 'sd', 'nas', 'usb' ].includes( V.mode ) ) { // browse by directory var query = { query : 'ls' , string : path , format : [ 'file' ] } - } else if ( G.mode.slice( -5 ) === 'radio' ) { + } else if ( V.mode.slice( -5 ) === 'radio' ) { var query = { query : 'radio' - , gmode : G.mode + , gmode : V.mode } } else { // browse by modes var query = { query : 'list' - , mode : G.mode - , format : [ G.mode ] + , mode : V.mode + , format : [ V.mode ] } } - query.gmode = G.mode; + query.gmode = V.mode; list( query, function( html ) { var data = { html : html @@ -1350,37 +1352,45 @@ $( '#lib-mode-list' ).click( function( e ) { } renderLibraryList( data ); } ); - query.path = G.mode.slice( -5 ) === 'radio' ? '' : path; + query.path = V.mode.slice( -5 ) === 'radio' ? '' : path; query.modetitle = path; - if ( query.query !== 'ls' && query.query !== 'radio' ) G.query.push( query ); -} ).on( 'click', '.mode-bookmark', function( e ) { // delegate - id changed on renamed + if ( query.query !== 'ls' && query.query !== 'radio' ) V.query.push( query ); +} ).on( 'click', '.bkradio', function( e ) { // delegate - id changed on renamed $( '#lib-search-close' ).click(); - if ( G.press || $( '.bkedit' ).length ) return + if ( V.press || $( '.bkedit' ).length ) return - var path = $( this ).find( '.lipath' ).text(); - if ( [ 'http', 'rtsp' ].includes( path.slice( 0, 4 ) ) ) { - var name = $( this ).find( '.bkname' ).text(); - if ( G.display.tapaddplay ) { - addReplace( 'addplay', [ 'mpcadd', path, 'addplay' ], 'Add to Playlist and play', name ); - return - } - - var $img = $( this ).find( '.bkcoverart' ); - var icon = $img.length ? '' : ''; - info( { - icon : 'plus-o' - , title : 'Add to Playlist' - , message : icon - +'
'+ $( this ).find( '.bkname' ).text() +'' - , buttonlabel : 'Add' - , buttoncolor : 'var( --cg )' - , button : () => addReplace( 'add', [ 'mpcadd', path ], 'Add to Playlist', name ) - , oklabel : 'Play' - , ok : () => addReplace( 'addplay', [ 'mpcadd', path, 'addplay' ], 'Add to Playlist and play', name ) - } ); + var $this = $( this ); + var path = $this.find( '.lipath' ).text(); + var name = $this.find( '.bkname' ).text(); + if ( D.tapaddplay ) { + bookmarkRadioAddPlaylist( 'addplay', path, name ); + return + } + + if ( D.tapreplaceplay ) { + bookmarkRadioAddPlaylist( 'replaceplay', path, name ) return } + var $img = $this.find( '.bkcoverart' ); + var icon = $img.length ? '' : ''; + info( { + icon : 'plus-o' + , title : 'Add to Playlist' + , message : icon + +'
'+ name +'' + , buttonlabel : 'Add' + , buttoncolor : 'var( --cg )' + , button : () => bookmarkRadioAddPlaylist( 'add', path, name ) + , oklabel : 'Play' + , ok : () => bookmarkRadioAddPlaylist( 'addplay', path, name ) + } ); +} ).on( 'click', '.mode-bookmark', function( e ) { // delegate - id changed on renamed + var $this = $( this ); + $( '#lib-search-close' ).click(); + if ( V.press || $( '.bkedit' ).length || $this.hasClass( 'bkradio' ) ) return + + var path = $this.find( '.lipath' ).text(); var path0 = path.split( '/' )[ 0 ]; var mode = path0.toLowerCase(); if ( path0.slice( 3 ) !== 'radio' ) { @@ -1398,7 +1408,7 @@ $( '#lib-mode-list' ).click( function( e ) { , gmode : mode } } - G.mode = mode; + V.mode = mode; list( query, function( html ) { var data = { html : html @@ -1409,7 +1419,7 @@ $( '#lib-mode-list' ).click( function( e ) { } ); query.path = path; query.modetitle = path; - G.query.push( query ); + V.query.push( query ); } ).on( 'click', '.bk-remove', function() { var $this = $( this ).parent(); var name = $this.find( '.bkname' ).text(); @@ -1470,8 +1480,7 @@ $( '#lib-mode-list' ).click( function( e ) { , button : ! thumbnail ? '' : () => bash( [ 'bookmarkcoverreset', imagepath, name ] ) , ok : () => imageReplace( 'bookmark', imagepath +'/coverart', name ) // no ext } ); -} ) -$( '#lib-mode-list' ).press( '.mode-bookmark', setBookmarkEdit ); +} ).press( '.mode-bookmark', setBookmarkEdit ); new Sortable( document.getElementById( 'lib-mode-list' ), { // onChoose > onClone > onStart > onMove > onChange > onUnchoose > onUpdate > onSort > onEnd ghostClass : 'lib-sortable-ghost' @@ -1488,9 +1497,9 @@ new Sortable( document.getElementById( 'lib-mode-list' ), { } } ); $( '#page-library' ).on( 'click', '#lib-list .coverart', function() { - if ( G.press ) return + if ( V.press ) return - G.scrolltop[ 'ALBUM' ] = $( window ).scrollTop(); + V.scrolltop[ 'ALBUM' ] = $( window ).scrollTop(); var $this = $( this ); var path = $this.find( '.lipath' ).text(); var query = { @@ -1503,17 +1512,17 @@ $( '#page-library' ).on( 'click', '#lib-list .coverart', function() { list( query, function( html ) { var data = { html : html - , modetitle : $this.find( G.display.albumbyartist ? '.coverart2' : '.coverart1' ).text() + , modetitle : $this.find( D.albumbyartist ? '.coverart2' : '.coverart1' ).text() , path : 'ALBUM' } renderLibraryList( data ); } ); query.modetitle = 'ALBUM'; - G.query.push( query ); + V.query.push( query ); } ).press( '.coverart', function( e ) { var $this = $( e.currentTarget ); var src = $this.find( 'img' ).attr( 'src' ); - var i = G.display.albumbyartist ? '21' : '12'; + var i = D.albumbyartist ? '21' : '12'; var album = $this.find( '.coverart'+ i[ 0 ] ).text(); var artist = $this.find( '.coverart'+ i[ 1 ] ).text(); info( { @@ -1540,23 +1549,21 @@ Exclude this thumbnail?` var artist = $thisli.find( '.liartist' ).text(); var lipath = $thisli.next().find( '.lipath' ).text(); var path = '/mnt/MPD/'+ dirName( lipath ); - if ( $this.hasClass( 'fa-save' ) ) { + if ( $this.hasClass( 'cover-save' ) ) { coverartSave(); } else { coverartChange(); } -} ); -$( '#page-library' ).press( '.licoverimg', function( e ) { +} ).press( '.licoverimg', function( e ) { var $this = $( e.currentTarget ); $this.parent().removeClass( 'active' ); $( '#menu-album' ).addClass( 'hide' ); $this.find( 'img' ) .css( 'opacity', '0.33' ) .after( icoveredit ); -} ); -$( '#page-library' ).on( 'click', '#lib-list li', function( e ) { +} ).on( 'click', '#lib-list li', function( e ) { e.stopPropagation(); - if ( G.press ) return + if ( V.press ) return if ( $( '.licover .cover-change' ).length ) { $( '.licover .cover-change' ).remove(); @@ -1570,7 +1577,7 @@ $( '#page-library' ).on( 'click', '#lib-list li', function( e ) { var menushow = $( '.contextmenu:not( .hide )' ).length; var active = $this.hasClass( 'active' ); menuHide(); - if ( ( menushow && G.mode !== 'webradio' ) || $target.hasClass( 'lib-icon' ) || $target.hasClass( 'licoverimg' ) ) { + if ( ( menushow && V.mode !== 'webradio' ) || $target.hasClass( 'lib-icon' ) || $target.hasClass( 'licoverimg' ) ) { if ( ! active ) contextmenuLibrary( $this, $target ); return } @@ -1580,15 +1587,15 @@ $( '#page-library' ).on( 'click', '#lib-list li', function( e ) { var name = ( $target.is( '.licomposer, .fa-composer' ) ) ? $this.find( '.licomposer' ).text() : $this.find( '.liartist' ).text(); getBio( name ); } else if ( $target.hasClass( 'liinfopath' ) ) { - G.gmode = G.mode; + V.gmode = V.mode; var path = $target.text(); - G.mode = path.replace( /\/.*/, '' ).toLowerCase(); + V.mode = path.replace( /\/.*/, '' ).toLowerCase(); var query = { query : 'ls' , string : path , format : [ 'file' ] } - query.gmode = G.mode; + query.gmode = V.mode; list( query, function( html ) { var data = { html : html @@ -1597,11 +1604,11 @@ $( '#page-library' ).on( 'click', '#lib-list li', function( e ) { } renderLibraryList( data ); } ); - G.query.push( query ); + V.query.push( query ); } return } else if ( $target.hasClass( 'lialbum' ) ) { - if ( ! G.localhost ) window.open( 'https://www.last.fm/music/'+ $this.find( '.liartist' ).text() +'/'+ $this.find( '.lialbum' ).text(), '_blank' ); + if ( ! V.localhost ) window.open( 'https://www.last.fm/music/'+ $this.find( '.liartist' ).text() +'/'+ $this.find( '.lialbum' ).text(), '_blank' ); return } else if ( $this.find( '.fa-music' ).length || $target.data( 'target' ) ) { contextmenuLibrary( $this, $target ); @@ -1613,7 +1620,7 @@ $( '#page-library' ).on( 'click', '#lib-list li', function( e ) { var path = $this.find( '.lipath' ).text(); var name = $this.find( '.liname' ).text(); var mode = $this.data( 'mode' ); - var modefile = [ 'sd', 'nas', 'usb' ].includes( G.mode ); + var modefile = [ 'sd', 'nas', 'usb' ].includes( V.mode ); // modes: sd, nas, usb, webradio, album, artist, albumartist, composer, conductor, date, genre if ( [ 'sd', 'nas', 'usb' ].includes( mode ) ) { // list by directory var query = { @@ -1622,7 +1629,7 @@ $( '#page-library' ).on( 'click', '#lib-list li', function( e ) { , format : [ 'file' ] } var modetitle = modefile ? path : $( '#mode-title' ).text(); - } else if ( G.mode.slice( -5 ) === 'radio' ) { + } else if ( V.mode.slice( -5 ) === 'radio' ) { if ( $this.hasClass( 'dir' ) ) { var query = { query : 'radio' @@ -1634,22 +1641,22 @@ $( '#page-library' ).on( 'click', '#lib-list li', function( e ) { return } } else if ( mode !== 'album' ) { // list by mode (non-album) - if ( [ 'date', 'genre' ].includes( G.mode ) ) { + if ( [ 'date', 'genre' ].includes( V.mode ) ) { var format = [ 'artist', 'album' ]; - } else if ( [ 'conductor', 'composer' ].includes( G.mode ) ) { + } else if ( [ 'conductor', 'composer' ].includes( V.mode ) ) { var format = [ 'album', 'artist' ]; } else { var format = [ 'album' ]; } var query = { query : 'find' - , mode : G.mode + , mode : V.mode , string : path , format : format } var modetitle = path; } else { // track list - if ( G.mode === 'album' ) { + if ( V.mode === 'album' ) { if ( name ) { // albums with the same names var query = { query : 'find' @@ -1669,14 +1676,14 @@ $( '#page-library' ).on( 'click', '#lib-list li', function( e ) { } else { var query = { query : 'find' - , mode : [ 'album', G.mode ] + , mode : [ 'album', V.mode ] , string : [ name, libpath ] } var modetitle = libpath; } } - G.scrolltop[ libpath ] = $( window ).scrollTop(); - query.gmode = G.mode; + V.scrolltop[ libpath ] = $( window ).scrollTop(); + query.gmode = V.mode; list( query, function( html ) { var data = { html : html @@ -1687,7 +1694,7 @@ $( '#page-library' ).on( 'click', '#lib-list li', function( e ) { } ); query.path = path; query.modetitle = modetitle; - if ( query.query !== 'ls' || ! modefile ) G.query.push( query ); + if ( query.query !== 'ls' || ! modefile ) V.query.push( query ); } ); $( '.page' ).on( 'click', '.index a', function() { var index = $( this ).find( 'wh' ).text()[ 0 ]; @@ -1696,8 +1703,8 @@ $( '.page' ).on( 'click', '.index a', function() { if ( index === '#' ) { var scrollT = 0; } else { - if ( G.library ) { - var el = G.mode === 'album' || G.mode === 'latest' ? '.coverart' : '#lib-list li'; + if ( V.library ) { + var el = V.mode === 'album' || V.mode === 'latest' ? '.coverart' : '#lib-list li'; } else { var el = '#pl-savedlist li'; } @@ -1707,15 +1714,15 @@ $( '.page' ).on( 'click', '.index a', function() { } ); // PLAYLIST ///////////////////////////////////////////////////////////////////////////////////// $( '#button-pl-back' ).click( function() { - if ( G.savedplaylist ) { + if ( V.savedplaylist ) { $( '#button-pl-playlists' ).click(); } else { getPlaylist(); } } ); $( '#button-pl-playlists' ).click( function() { - G.savedlist = 1; - G.savedplaylist = 0; + V.savedlist = 1; + V.savedplaylist = 0; list( { cmd: 'list' }, ( data ) => renderPlaylistList( data ), 'json' ); } ); $( '#button-pl-save' ).click( function() { @@ -1739,22 +1746,22 @@ $( '#button-pl-consume' ).click( function() { var $this = $( this ); var icon = 'playlist'; var title = 'Consume Mode'; - if ( G.status.consume ) { + if ( S.consume ) { $this.removeClass( 'bl' ); banner( icon, title, 'Off' ); } else { $this.addClass( 'bl' ); banner( icon, title, 'On - Remove each song after played.' ); } - G.status.consume = ! G.status.consume; - bash( [ 'mpcoption', 'consume', G.status.consume ] ); + S.consume = ! S.consume; + bash( [ 'mpcoption', 'consume', S.consume ] ); } ); $( '#button-pl-librandom' ).click( function() { var $this = $( this ); var icon = 'librandom'; var title = 'Roll The Dice'; - if ( G.status.librandom ) { - G.status.librandom = false; + if ( S.librandom ) { + S.librandom = false; $this.removeClass( 'bl' ); banner( icon, title, 'Off ...' ); bash( [ 'librandom', false ] ); @@ -1765,9 +1772,9 @@ $( '#button-pl-librandom' ).click( function() { , message : 'Randomly add songs and play continuously.' , checkbox : [ 'Start playing the random songs' ] , values : [ true ] - , beforeshow : () => $( '#infoContent table' ).toggleClass( 'hide', G.status.song + 1 === G.status.pllength ) + , beforeshow : () => $( '#infoContent table' ).toggleClass( 'hide', S.song + 1 === S.pllength ) , ok : () => { - G.status.librandom = true; + S.librandom = true; $this.addClass( 'bl' ); banner( icon, title, 'On ...' ); bash( [ 'librandom', true, infoVal() ] ); @@ -1784,7 +1791,7 @@ $( '#button-pl-shuffle' ).click( function() { } ); } ); $( '#button-pl-clear' ).click( function() { - if ( G.status.pllength === 1 ) { + if ( S.pllength === 1 ) { info( { icon : 'playlist' , title : 'Clear Playlist' @@ -1807,7 +1814,7 @@ $( '#button-pl-clear' ).click( function() { $( '#pl-list .name' ).css( 'max-width', 'calc( 100% - 135px )' ); } , () => { - if ( ! G.status.librandom ) local(); + if ( ! S.librandom ) local(); bash( [ 'mpccrop' ] ); $( '#pl-list li:not( .active )' ).remove(); } @@ -1845,7 +1852,7 @@ new Sortable( document.getElementById( 'pl-list' ), { $( '#pl-list li.active' ).addClass( 'sortactive' ); } , onUpdate : function ( e ) { - G.status.song = $( '#pl-list li.sortactive' ).index(); + S.song = $( '#pl-list li.sortactive' ).index(); $( '#pl-list li.sortactive' ).removeClass( 'sortactive' ); sortPlaylist( 'pl-list', e.oldIndex, e.newIndex ); } @@ -1864,7 +1871,7 @@ $( '#pl-list' ).on( 'click', 'li', function( e ) { if ( $target.hasClass( 'fa-save' ) || $target.hasClass( 'pl-icon' ) || $target.hasClass( 'pl-remove' ) ) return var $this = $( this ); - if ( ! [ 'mpd', 'upnp' ].includes( G.status.player ) ) { + if ( ! [ 'mpd', 'upnp' ].includes( S.player ) ) { $this.find( '.pl-icon' ).click(); return } @@ -1876,7 +1883,7 @@ $( '#pl-list' ).on( 'click', 'li', function( e ) { $liactive.find( '.li1 .radioname' ).removeClass( 'hide' ); $liactive.find( '.li2 .radioname' ).addClass( 'hide' ); if ( $this.hasClass( 'active' ) ) { - if ( G.status.state == 'play' ) { + if ( S.state == 'play' ) { if ( $this.find( '.lipath' ).text().slice( 0, 4 ) !== 'http' ) { $( '#pause' ).click(); $this.find( '.elapsed i' ).removeClass( 'fa-play' ).addClass( 'fa-pause' ); @@ -1894,18 +1901,18 @@ $( '#pl-list' ).on( 'click', 'li', function( e ) { $this.add( '#play' ).addClass( 'active' ); } } ).on( 'click', '.savewr', function() { - G.list.li = $( this ).parent(); + V.list.li = $( this ).parent(); webRadioSave( $( this ).next().next().text() ); menuHide(); } ).on( 'click', '.pl-icon', function() { var $this = $( this ); var $thisli = $this.parent(); - G.list = {}; - G.list.li = $thisli; - G.list.path = $thisli.find( '.lipath' ).text(); - G.list.artist = $thisli.find( '.artist' ).text(); - G.list.name = $thisli.find( '.name' ).text(); - G.list.index = $thisli.index(); + V.list = {}; + V.list.li = $thisli; + V.list.path = $thisli.find( '.lipath' ).text(); + V.list.artist = $thisli.find( '.artist' ).text(); + V.list.name = $thisli.find( '.name' ).text(); + V.list.index = $thisli.index(); var $menu = $( '#menu-plaction' ); var menushow = ! $menu.hasClass( 'hide' ); var updn = $thisli.hasClass( 'updn' ); @@ -1913,7 +1920,7 @@ $( '#pl-list' ).on( 'click', 'li', function( e ) { $( '.pl-remove' ).remove(); if ( menushow && updn) return - var state = G.status.state; + var state = S.state; var play = state === 'play'; var active = $thisli.hasClass( 'active' ); var audiocd = $thisli.hasClass( 'audiocd' ); @@ -1923,7 +1930,7 @@ $( '#pl-list' ).on( 'click', 'li', function( e ) { $thisli.addClass( 'updn' ); $( '#menu-plaction a' ).removeClass( 'hide' ); $menu.find( '.current' ).toggleClass( 'hide', active || play ); - if ( G.status.player === 'mpd' || G.status.player === 'upnp' ) { + if ( S.player === 'mpd' || S.player === 'upnp' ) { if ( active ) { $menu.find( '.play' ).toggleClass( 'hide', play ); $menu.find( '.pause' ).toggleClass( 'hide', ! play || radio ); @@ -1934,7 +1941,7 @@ $( '#pl-list' ).on( 'click', 'li', function( e ) { } else { $menu.find( '.play, .pause, .stop, .current' ).addClass( 'hide' ); } - $menu.find( '.savedpladd' ).toggleClass( 'hide', audiocd || notsaved || upnp || G.counts.playlists === 0 ); + $menu.find( '.savedpladd' ).toggleClass( 'hide', audiocd || notsaved || upnp || C.playlists === 0 ); $menu.find( '.similar, .submenu' ).toggleClass( 'hide', radio ); $menu.find( '.tag' ).toggleClass( 'hide', audiocd || radio || upnp ); $menu.find( '.tagcd' ).toggleClass( 'hide', ! audiocd ); @@ -1949,7 +1956,7 @@ $( '#pl-path' ).click( '.savedlist', function() { menuHide(); if ( active ) return - G.list.path = $( '#pl-path .lipath' ).text(); + V.list.path = $( '#pl-path .lipath' ).text(); $menu.find( '.plrename, .pldelete' ).addClass( 'hide' ); contextmenuScroll( $menu, 88 ); } ); @@ -1964,60 +1971,60 @@ $( '#pl-savedlist' ).on( 'click', 'li', function( e ) { menuHide(); if ( menushow && active ) return - var pladd = 'file' in G.pladd; + var pladd = 'file' in V.pladd; var plicon = $target.hasClass( 'pl-icon' ); - if ( G.savedplaylist || plicon ) { + if ( V.savedplaylist || plicon ) { if ( pladd ) { playlistInsertSelect( $this ); } else { var datatarget = $target.data( 'target' ) || $this.find( '.pl-icon' ).data ( 'target' ); var $menu = $( datatarget ); - G.list = {}; - G.list.li = $this; // for contextmenu + V.list = {}; + V.list.li = $this; // for contextmenu $( '#pl-savedlist li' ).removeClass( 'active' ); - if ( G.savedlist ) { - G.list.name = $this.find( '.plname' ).text().trim(); - G.list.path = G.list.name; + if ( V.savedlist ) { + V.list.name = $this.find( '.plname' ).text().trim(); + V.list.path = V.list.name; } else { - G.list.artist = $this.find( '.artist' ).text().trim(); - G.list.name = $this.find( '.name' ).text().trim(); - G.list.path = $this.find( '.lipath' ).text().trim() || G.list.name; - G.list.track = $this.data( 'track' ); - $( '.plus-refresh, .play-plus-refresh' ).toggleClass( 'hide', ! G.status.pllength ); + V.list.artist = $this.find( '.artist' ).text().trim(); + V.list.name = $this.find( '.name' ).text().trim(); + V.list.path = $this.find( '.lipath' ).text().trim() || V.list.name; + V.list.track = $this.data( 'track' ); + $( '.plus-refresh, .play-plus-refresh' ).toggleClass( 'hide', ! S.pllength ); $( '.minus-circle' ).removeClass( 'hide' ); $( '.tag' ).addClass( 'hide' ); - if ( ( G.display.tapaddplay || G.display.tapreplaceplay ) - && G.savedplaylist + if ( ( D.tapaddplay || D.tapreplaceplay ) + && V.savedplaylist && ! plicon - && G.status.player === 'mpd' + && S.player === 'mpd' ) { $menu.find( 'a:eq( 0 ) .submenu' ).click(); return } - $menu.find( '.replace' ).toggleClass( 'hide', ! G.status.pllength ); - $menu.find( '.similar' ).toggleClass( 'hide', G.list.path.slice( 0, 4 ) === 'http' ); + $menu.find( '.replace' ).toggleClass( 'hide', ! S.pllength ); + $menu.find( '.similar' ).toggleClass( 'hide', V.list.path.slice( 0, 4 ) === 'http' ); $menu.find( '.wrsave' ).toggleClass( 'hide', ! $this.hasClass( 'notsaved' ) ); } $this.addClass( 'active' ); - $menu.find( '.submenu' ).toggleClass( 'disabled', G.status.player !== 'mpd' ); + $menu.find( '.submenu' ).toggleClass( 'disabled', S.player !== 'mpd' ); contextmenuScroll( $menu, $this.position().top + 48 ); } } else { - G.savedlist = 0; - G.savedplaylist = 1; + V.savedlist = 0; + V.savedplaylist = 1; renderSavedPlaylist( $this.find( '.plname' ).text() ); if ( pladd ) playlistInsertTarget(); } } ).on( 'click', '.savewr', function() { var $this = $( this ); - G.list.li = $this.parent(); + V.list.li = $this.parent(); webRadioSave( $this.next().next().text() ); menuHide(); } ); // lyrics ///////////////////////////////////////////////////////////////////////////////////// $( '#lyricstextarea' ).on( 'input', function() { - if ( G.lyrics === $( this ).val() ) { + if ( V.lyrics === $( this ).val() ) { $( '#lyricsundo, #lyricssave' ).addClass( 'hide' ); $( '#lyricsback' ).removeClass( 'hide' ); } else { @@ -2027,15 +2034,15 @@ $( '#lyricstextarea' ).on( 'input', function() { } ); $( '#lyricsedit' ).click( function() { $( '#lyricsundo, #lyricssave' ).addClass( 'hide' ); - $( '#lyricsdelete' ).toggleClass( 'hide', ! G.lyrics ); + $( '#lyricsdelete' ).toggleClass( 'hide', ! V.lyrics ); $( '#lyricseditbtngroup' ).removeClass( 'hide' ); $( '#lyricsedit, #lyricstext' ).addClass( 'hide' ); $( '#lyricstextarea' ) - .val( G.lyrics ) + .val( V.lyrics ) .scrollTop( $( '#lyricstext' ).scrollTop() ); } ); $( '#lyricsclose' ).click( function() { - if ( $( '#lyricstextarea' ).val() === G.lyrics || ! $( '#lyricstextarea' ).val() ) { + if ( $( '#lyricstextarea' ).val() === V.lyrics || ! $( '#lyricstextarea' ).val() ) { lyricsHide(); } else { info( { @@ -2056,7 +2063,7 @@ $( '#lyricsundo' ).click( function() { , title : 'Lyrics' , message : 'Discard changes made to this lyrics?' , ok : () => { - $( '#lyricstextarea' ).val( G.lyrics ); + $( '#lyricstextarea' ).val( V.lyrics ); $( '#lyricsundo, #lyricssave' ).addClass( 'hide' ); $( '#lyricsback' ).removeClass( 'hide' ); } @@ -2068,12 +2075,12 @@ $( '#lyricssave' ).click( function() { , title : 'Lyrics' , message : 'Save this lyrics?' , ok : () => { - G.lyrics = $( '#lyricstextarea' ).val(); + V.lyrics = $( '#lyricstextarea' ).val(); var artist = $( '#lyricsartist' ).text(); var title = $( '#lyricstitle' ).text(); - bash( [ 'lyrics', artist, title, 'save', G.lyrics.replace( /\n/g, '\\n' ) ] ); + bash( [ 'lyrics', artist, title, 'save', V.lyrics.replace( /\n/g, '\\n' ) ] ); lyricstop = $( '#lyricstextarea' ).scrollTop(); - lyricsShow( G.lyrics ); + lyricsShow( V.lyrics ); $( '#lyricseditbtngroup' ).addClass( 'hide' ); $( '#lyricsedit, #lyricstext' ).removeClass( 'hide' ); } @@ -2090,7 +2097,7 @@ $( '#lyricsdelete' ).click( function() { var artist = $( '#lyricsartist' ).text(); var title = $( '#lyricstitle' ).text(); bash( [ 'lyrics', artist, title, 'delete' ] ); - G.lyrics = ''; + V.lyrics = ''; lyricsHide(); } } ); diff --git a/srv/http/assets/js/networks.js b/srv/http/assets/js/networks.js index c7f63aad1..9e307d84d 100644 --- a/srv/http/assets/js/networks.js +++ b/srv/http/assets/js/networks.js @@ -9,7 +9,7 @@ $( 'body' ).click( function() { $( 'li' ).removeClass( 'active' ); } ); $( '.back' ).click( function() { - clearTimeout( G.timeoutScan ); + clearTimeout( V.timeoutscan ); $( '#help, #divinterface' ).removeClass( 'hide' ); $( '#divbluetooth, #divwifi, #divwebui' ).addClass( 'hide' ); $( '#listwlscan, #listbtscan' ).empty(); @@ -62,10 +62,10 @@ $( '#listwlscan' ).on( 'click', 'li', function() { } } ); $( '.wladd' ).click( function() { - G.hostapd ? infoAccesspoint() : infoWiFi(); + S.hostapd ? infoAccesspoint() : infoWiFi(); } ); $( '.wlscan' ).click( function() { - if ( G.hostapd ) { + if ( S.hostapd ) { infoAccesspoint(); } else { $( '#help, #divinterface, #divwebui, #divaccesspoint' ).addClass( 'hide' ); @@ -84,30 +84,29 @@ $( '.lanadd' ).click( function() { } ); $( '.entries:not( .scan )' ).on( 'click', 'li', function( e ) { e.stopPropagation(); - G.li = $( this ); - if ( G.li.hasClass( 'accesspoint' ) ) return + V.li = $( this ); + if ( V.li.hasClass( 'accesspoint' ) ) return - G.list = G.li.parent().prop( 'id' ); - G.liactive = G.li.hasClass( 'active' ); + V.listid = V.li.parent().prop( 'id' ); if ( ! $( '#menu' ).hasClass( 'hide' ) ) { $( '#menu' ).addClass( 'hide' ); - if ( G.liactive ) return + if ( V.li.hasClass( 'active' ) ) return } $( 'li' ).removeClass( 'active' ); - G.li.addClass( 'active' ); - if ( G.list === 'listbt' ) { - var connected = G.li.find( 'grn' ).length === 1; + V.li.addClass( 'active' ); + if ( V.listid === 'listbt' ) { + var connected = V.li.find( 'grn' ).length === 1; $( '#menu a' ).addClass( 'hide' ); $( '#menu' ).find( '.forget, .info' ).removeClass( 'hide' ); $( '#menu .connect' ).toggleClass( 'hide', connected ); $( '#menu .disconnect' ).toggleClass( 'hide', ! connected ); - $( '#menu .info' ).toggleClass( 'hide', G.li.data( 'mac' ) === $( '#codebluetooth' ).data( 'mac' ) ); - } else if ( G.list === 'listlan' ) { + $( '#menu .info' ).toggleClass( 'hide', V.li.data( 'mac' ) === $( '#codebluetooth' ).data( 'mac' ) ); + } else if ( V.listid === 'listlan' ) { $( '#menu a' ).addClass( 'hide' ); $( '#menu .edit' ).removeClass( 'hide' ); } else { - var notconnected = G.li.hasClass( 'notconnected' ); + var notconnected = V.li.hasClass( 'notconnected' ); $( '#menu a' ).removeClass( 'hide' ); $( '#menu .connect' ).toggleClass( 'hide', ! notconnected ); $( '#menu .disconnect' ).toggleClass( 'hide', notconnected ); @@ -116,43 +115,43 @@ $( '.entries:not( .scan )' ).on( 'click', 'li', function( e ) { var menuH = $( '#menu' ).height(); $( '#menu' ) .removeClass( 'hide' ) - .css( 'top', G.li.position().top + 48 ); + .css( 'top', V.li.position().top + 48 ); var targetB = $( '#menu' ).offset().top + menuH; var wH = window.innerHeight; if ( targetB > wH - 40 + $( window ).scrollTop() ) $( 'html, body' ).animate( { scrollTop: targetB - wH + 42 } ); } ); $( '.connect' ).click( function() { - clearTimeout( G.timeoutScan ); - if ( G.list === 'listbt' ) { - var icon = G.li.find( 'i' ).hasClass( 'fa-btsender' ) ? 'btsender' : 'bluetooth'; - notify( icon, G.li.data( 'name' ), 'Connect ...' ); - bluetoothCommand( 'connect', G.li.data( 'mac' ) ); + clearTimeout( V.timeoutscan ); + if ( V.listid === 'listbt' ) { + var icon = V.li.find( 'i' ).hasClass( 'fa-btsender' ) ? 'btsender' : 'bluetooth'; + notify( icon, V.li.data( 'name' ), 'Connect ...' ); + bluetoothCommand( 'connect', V.li.data( 'mac' ) ); return } - if ( G.hostapd ) { + if ( S.hostapd ) { infoAccesspoint(); return } - var ssid = G.li.data( 'ssid' ); + var ssid = V.li.data( 'ssid' ); notify( 'wifi', ssid, 'Connect ...' ); bash( [ 'profileconnect', ssid ] ); } ); $( '.disconnect' ).click( function() { - if ( G.list === 'listbt' ) { - var icon = G.li.find( 'i' ).hasClass( 'fa-btsender' ) ? 'btsender' : 'bluetooth'; - notify( icon, G.li.data( 'name' ), 'Disconnect ...' ); - bluetoothCommand( 'disconnect', G.li.data( 'mac' ) ); + if ( V.listid === 'listbt' ) { + var icon = V.li.find( 'i' ).hasClass( 'fa-btsender' ) ? 'btsender' : 'bluetooth'; + notify( icon, V.li.data( 'name' ), 'Disconnect ...' ); + bluetoothCommand( 'disconnect', V.li.data( 'mac' ) ); return } - var ssid = G.li.data( 'ssid' ); + var ssid = V.li.data( 'ssid' ); var icon = 'wifi'; info( { icon : icon , title : ssid - , message : ( G.listeth ? '' : iconwarning +'No network connections after this.
' ) +'Disconnect?' + , message : ( S.listeth ? '' : iconwarning +'No network connections after this.
' ) +'Disconnect?' , okcolor : orange , ok : () => { notify( icon, ssid, 'Disconnect ...' ); @@ -161,32 +160,32 @@ $( '.disconnect' ).click( function() { } ); } ); $( '.edit' ).click( function() { - G.list === 'listwl' ? editWiFi() : editLAN(); + V.listid === 'listwl' ? editWiFi() : editLAN(); } ); $( '.forget' ).click( function() { - if ( G.list === 'listbt' ) { - var name = G.li.data( 'name' ); - var icon = G.li.find( 'i' ).hasClass( 'fa-btsender' ) ? 'btsender' : 'bluetooth'; + if ( V.listid === 'listbt' ) { + var name = V.li.data( 'name' ); + var icon = V.li.find( 'i' ).hasClass( 'fa-btsender' ) ? 'btsender' : 'bluetooth'; info( { icon : icon , title : name - , message : G.listeth ? '' : iconwarning +'No network connections after this.' + , message : S.listeth ? '' : iconwarning +'No network connections after this.' , oklabel : 'Forget' , okcolor : red , ok : () => { notify( icon, name, 'Forget ...' ); - bluetoothCommand( 'remove', G.li.data( 'mac' ) ); + bluetoothCommand( 'remove', V.li.data( 'mac' ) ); } } ); return } - var ssid = G.li.data( 'ssid' ); + var ssid = V.li.data( 'ssid' ); var icon = 'wifi'; info( { icon : icon , title : ssid - , message : G.ipeth || G.ipwl ? '' : iconwarning +'Current Web interface will be dropped.' + , message : S.ipeth || S.ipwl ? '' : iconwarning +'Current Web interface will be dropped.' , oklabel : 'Forget' , okcolor : red , ok : () => { @@ -196,7 +195,7 @@ $( '.forget' ).click( function() { } ); } ); $( '.info' ).click( function() { - bluetoothInfo( G.li.data( 'mac' ) ); + bluetoothInfo( V.li.data( 'mac' ) ); } ); $( '.hostapdset' ).click( function() { var icon = 'accesspoint'; @@ -206,8 +205,8 @@ $( '.hostapdset' ).click( function() { , title : title , footer : '(8 characters or more)' , textlabel : [ 'IP', 'Password' ] - , values : G.hostapd.conf - , checkchanged : G.hostapd + , values : S.hostapd.conf + , checkchanged : S.hostapd , checkblank : 1 , checklength : { 1: [ 8, 'min' ] } , ok : () => { @@ -219,7 +218,7 @@ $( '.hostapdset' ).click( function() { var ip012 = ips.join( '.' ); var iprange = ip012 +'.'+ ( +ip3 + 1 ) +','+ ip012 +'.254,24h'; bash( [ 'hostapd', true, iprange, ip, pwd ] ); - notify( icon, title, G.hostapd ? 'Change ...' : 'Enable ...' ); + notify( icon, title, S.hostapd ? 'Change ...' : 'Enable ...' ); } } ); } ); @@ -244,7 +243,7 @@ function bluetoothInfo( mac ) { } ); } function connectWiFi( data ) { // { add:..., gw:..., hidden:..., ip:..., password:..., ssid:..., wpa:... } - clearTimeout( G.timeoutScan ); + clearTimeout( V.timeoutscan ); var ssid = data.ESSID; var icon = 'wifi'; if ( 'Address' in data ) { @@ -257,11 +256,11 @@ function connectWiFi( data ) { // { add:..., gw:..., hidden:..., ip:..., passwor notify( icon, ssid, 'Change URL to '+ ip ); } } else { - notify( icon, ssid, G.connectedwl ? 'Change ...' : 'Connect ...' ); + notify( icon, ssid, S.connectedwl ? 'Change ...' : 'Connect ...' ); } bash( [ 'connect', JSON.stringify( data ) ], connected => { if ( connected == -1 ) { - G.wlconnected = ''; + S.wlconnected = ''; info( { icon : icon , title : 'Wi-Fi' @@ -271,9 +270,9 @@ function connectWiFi( data ) { // { add:..., gw:..., hidden:..., ip:..., passwor } ); } function editLAN() { - var static = G.listeth.static; - var ip = G.ipeth; - var gw = G.listeth.gateway; + var static = S.listeth.static; + var ip = S.ipeth; + var gw = S.listeth.gateway; var icon = 'lan'; var title = 'Edit LAN Connection'; info( { @@ -293,9 +292,9 @@ function editLAN() { } , buttonlabel : ! static ? '' : 'DHCP' , button : ! static ? '' : () => { - notify( icon, title, 'Change URL to '+ G.hostname +'.local ...' ); + notify( icon, title, 'Change URL to '+ S.hostname +'.local ...' ); loader(); - location.href = 'http://'+ G.hostname +'.local/settings.php?p=networks'; + location.href = 'http://'+ S.hostname +'.local/settings.php?p=networks'; bash( [ 'editlan' ] ); } , ok : () => editLANSet( infoVal() ) @@ -320,7 +319,7 @@ function editLANSet( values ) { } ); } function editWiFi() { - bash( [ 'profileget', G.li.data( 'ssid' ) ], values => infoWiFi( values ), 'json' ); + bash( [ 'profileget', V.li.data( 'ssid' ) ], values => infoWiFi( values ), 'json' ); } function infoAccesspoint() { info( { @@ -394,9 +393,9 @@ function qr( msg ) { } function renderBluetooth() { if ( ! $( '#divbluetooth' ).hasClass( 'hide' ) ) $( '#divbluetooth .back' ).click(); - if ( G.listbt ) { + if ( S.listbt ) { var htmlbt = ''; - G.listbt.forEach( list => { + S.listbt.forEach( list => { var dot = list.connected ? '' : ''; htmlbt += '
  • ' +''+ dot +' '+ list.name +'
  • '; @@ -412,49 +411,49 @@ function renderBluetooth() { $( '#divbt' ).removeClass( 'hide' ); } function renderPage() { - $( '.btscan' ).toggleClass( 'disabled', G.camilladsp ); - if ( ! G.activebt ) { + $( '.btscan' ).toggleClass( 'disabled', S.camilladsp ); + if ( ! S.activebt ) { $( '#divbt' ).addClass( 'hide' ); } else { renderBluetooth(); } - if ( ! G.activewl ) { + if ( ! S.activewl ) { $( '#divwl' ).addClass( 'hide' ); } else { renderWlan(); } - if ( ! G.activeeth ) { + if ( ! S.activeeth ) { $( '#divlan' ).addClass( 'hide' ); } else { var htmlwl = ''; - if ( G.listeth ) htmlwl = '
  •  '+ G.ipeth - +' » '+ G.listeth.gateway +'
  • '; + if ( S.listeth ) htmlwl = '
  •  '+ S.ipeth + +' » '+ S.listeth.gateway +'
  • '; $( '#listlan' ).html( htmlwl ); - $( '.lanadd' ).toggleClass( 'hide', G.listeth !== false ); + $( '.lanadd' ).toggleClass( 'hide', S.listeth !== false ); $( '#divlan' ).removeClass( 'hide' ); } - $( '#divaccesspoint' ).toggleClass( 'hide', ! G.hostapd ); + $( '#divaccesspoint' ).toggleClass( 'hide', ! S.hostapd ); if ( ! $( '#divinterface' ).hasClass( 'hide' ) ) renderQR(); showContent(); } function renderQR() { - var ip = G.ipeth || G.ipwl; + var ip = S.ipeth || S.ipwl; if ( ! ip ) return - if ( ip && ip !== G.hostapd.ip ) { + if ( ip && ip !== S.hostapd.ip ) { $( '#qrwebui' ).html( qr( 'http://'+ ip ) ); - if( G.hostname ) ip += '
    http://'+ G.hostname +'.local'; + if( S.hostname ) ip += '
    http://'+ S.hostname +'.local'; $( '#ipwebui' ).html( ip ); $( '#divwebui' ).removeClass( 'hide' ); } else { $( '#divwebui' ).addClass( 'hide' ); } - if ( G.hostapd ) { - $( '#ipwebuiap' ).html( 'Web User Interface
    http://'+ G.hostapd.ip +'' ); - $( '#ssid' ).text( G.hostapd.ssid ); - $( '#passphrase' ).text( G.hostapd.passphrase ) - $( '#qraccesspoint' ).html( qr( 'WIFI:S:'+ G.hostapd.ssid +';T:WPA;P:'+ G.hostapd.passphrase +';' ) ); - $( '#qrwebuiap' ).html( qr( 'http://'+ G.hostapd.ip ) ); + if ( S.hostapd ) { + $( '#ipwebuiap' ).html( 'Web User Interface
    http://'+ S.hostapd.ip +'' ); + $( '#ssid' ).text( S.hostapd.ssid ); + $( '#passphrase' ).text( S.hostapd.passphrase ) + $( '#qraccesspoint' ).html( qr( 'WIFI:S:'+ S.hostapd.ssid +';T:WPA;P:'+ S.hostapd.passphrase +';' ) ); + $( '#qrwebuiap' ).html( qr( 'http://'+ S.hostapd.ip ) ); $( '#boxqr' ).removeClass( 'hide' ); } else { $( '#ipwebuiap, #ssid, #passphrase, #qraccesspoint, #qrwebuiap' ).empty(); @@ -464,17 +463,17 @@ function renderQR() { function renderWlan() { if ( ! $( '#divwifi' ).hasClass( 'hide' ) ) $( '#divwifi .back' ).click(); var htmlwl = ''; - if ( G.listwl ) { - G.listwl.forEach( list => { + if ( S.listwl ) { + S.listwl.forEach( list => { if ( list.ip ) { - if ( ! G.hostapd ) { + if ( ! S.hostapd ) { var signal = list.dbm > -60 ? '' : ( list.dbm < -67 ? 1 : 2 ); htmlwl += '
  • ' +' '+ list.ssid +' • '+ list.ip +' » '+ list.gateway +'
  • '; } else { htmlwl += '
  •  ' - +'Access point « '+ G.hostapd.hostapdip +'
  • '; + +'Access point « '+ S.hostapd.hostapdip +''; } } else { htmlwl += '
  • • '+ list.ssid +'
  • '; @@ -490,18 +489,18 @@ function renderWlan() { function scanBluetooth() { bash( dirbash +'networks-scan.sh', data => { if ( data ) { - G.listbtscan = data; + S.listbtscan = data; var htmlbt = ''; data.forEach( list => htmlbt += '
  • '+ list.name +'
  • ' ); $( '#listbtscan' ).html( htmlbt ); } - G.timeoutScan = setTimeout( scanBluetooth, 12000 ); + V.timeoutscan = setTimeout( scanBluetooth, 12000 ); }, 'json' ); } function scanWlan() { bash( dirbash +'networks-scan.sh wlan', data => { if ( data ) { - G.listwlscan = data; + S.listwlscan = data; var htmlwl = ''; data.forEach( list => { if ( list.signal.slice( -3 ) === 'dBm' ) { @@ -521,6 +520,6 @@ function scanWlan() { var htmlwl = '
  • (no accesspoints found)
  • '; } $( '#listwlscan' ).html( htmlwl ); - G.timeoutScan = setTimeout( scanWlan, 12000 ); + V.timeoutscan = setTimeout( scanWlan, 12000 ); }, 'json' ); } diff --git a/srv/http/assets/js/passive.js b/srv/http/assets/js/passive.js index 8a234a0cf..21e90fbc3 100644 --- a/srv/http/assets/js/passive.js +++ b/srv/http/assets/js/passive.js @@ -1,12 +1,12 @@ // page resize ----------------------------------------------------------------- window.onresize = () => { // rotate / resize var wW = window.innerWidth; - if ( G.wW === wW ) return // wH changes with address bar toggle on scroll up-down + if ( V.wW === wW ) return // wH changes with address bar toggle on scroll up-down - G.wH = window.innerHeight; - G.wW = wW; + V.wH = window.innerHeight; + V.wW = wW; var barvisible = $bartop.is( ':visible' ); - if ( G.playback ) { + if ( V.playback ) { if ( $( '#bio' ).hasClass( 'hide' ) ) { displayPlayback(); setButtonControl(); @@ -18,8 +18,8 @@ window.onresize = () => { // rotate / resize $( '#biocontent .artist' ).insertBefore( '#bioimg' ); } } - } else if ( G.library ) { - if ( G.librarylist ) { + } else if ( V.library ) { + if ( V.librarylist ) { setTimeout( () => { if ( $( '.licover' ).length ) { $( '#lib-list p' ).css( 'min-height', ( barvisible ? 40 : 0 ) ); @@ -30,7 +30,7 @@ window.onresize = () => { // rotate / resize }, 0 ); } } else { - if ( G.playlist && ! G.savedlist && ! G.savedplaylist ) { + if ( V.playlist && ! V.savedlist && ! V.savedplaylist ) { setTimeout( () => { setPlaylistInfoWidth(); setPlaylistScroll() @@ -41,8 +41,8 @@ window.onresize = () => { // rotate / resize displayBars(); } function radioRefresh() { - if ( G.query.length ) { - var query = G.query[ G.query.length - 1 ]; + if ( V.query.length ) { + var query = V.query[ V.query.length - 1 ]; list( query, function( html ) { var data = { html : html @@ -52,15 +52,15 @@ function radioRefresh() { renderLibraryList( data ); } ); } else { - $( '#mode-'+ G.mode ).click(); + $( '#mode-'+ V.mode ).click(); } } function statusUpdate( data ) { - $.each( data, ( k, v ) => { G.status[ k ] = v } ); // need braces - if ( ! $( '#playback' ).hasClass( 'fa-'+ G.status.player ) ) displayBottom(); + $.each( data, ( k, v ) => { S[ k ] = v } ); // need braces + if ( ! $( '#playback' ).hasClass( 'fa-'+ S.player ) ) displayBottom(); setButtonControl(); setButtonOptions(); - if ( G.display.snapclient ) bash( [ 'lcdcharrefresh', JSON.stringify( G.status ) ] ); + if ( D.snapclient ) bash( [ 'lcdcharrefresh', JSON.stringify( S ) ] ); } function webradioIcon( srcnoext ) { var radiourl = decodeURIComponent( srcnoext ) @@ -73,7 +73,7 @@ function webradioIcon( srcnoext ) { // pushstreamChannel() in common.js var channels = [ 'airplay', 'bookmark', 'btreceiver', 'coverart', 'display', 'equalizer', 'mpdplayer', 'mpdradio', 'mpdupdate', 'notify', 'option', 'order', 'playlist', 'radiolist', 'relays', 'reload', 'savedplaylist', 'volume', 'webradio' ]; -if ( ! G.localhost ) channels.push( 'vumeter' ); +if ( ! V.localhost ) channels.push( 'vumeter' ); pushstreamChannel( channels ); function pushstreamDisconnect() { clearIntervalAll(); @@ -106,7 +106,7 @@ pushstream.onmessage = ( data, id, channel ) => { } function psAirplay( data ) { statusUpdate( data ); - if ( G.playback ) renderPlayback(); + if ( V.playback ) renderPlayback(); } function psBtReceiver( connected ) { var prefix = $time.is( ':visible' ) ? 'ti' : 'i'; @@ -116,52 +116,52 @@ function psBookmark() { refreshData( 'resetdata' ); } function psCoverart( data ) { - clearTimeout( G.timeoutCover ); + clearTimeout( V.timeoutCover ); bannerHide(); $( '#coverart, #liimg' ).css( 'opacity', '' ); - data.type === 'coverart' ? G.status.coverart = data.url : G.status.stationcover = data.url; + data.type === 'coverart' ? S.coverart = data.url : S.stationcover = data.url; setCoverart(); if ( 'Album' in data ) { // online coverarts come with album name - G.status.Album = data.Album; + S.Album = data.Album; setInfo(); } - if ( G.library && data.url.slice( 0, 13 ) === '/data/audiocd' ) return + if ( V.library && data.url.slice( 0, 13 ) === '/data/audiocd' ) return - G.libraryhtml = ''; - G.librarylisthtml = ''; - G.playlisthtml = ''; - G.playlistlisthtml = ''; - if ( ! G.playback ) refreshData(); + V.libraryhtml = ''; + V.librarylisthtml = ''; + V.playlisthtml = ''; + V.playlistlisthtml = ''; + if ( ! V.playback ) refreshData(); } function psDisplay( data ) { bannerHide(); if ( 'submenu' in data ) { - G.display[ data.submenu ] = data.value; + D[ data.submenu ] = data.value; displaySubMenu(); return } if ( 'updateaddons' in data ) { - G.status.updateaddons = data.updateaddons ? true : false; + S.updateaddons = data.updateaddons ? true : false; setButtonUpdateAddons(); return } - $.each( data, ( k, v ) => { G.display[ k ] = v } ); // need braces - G.coverdefault = ! G.display.covervu && ! G.display.vumeter ? G.coverart : G.covervu; + $.each( data, ( k, v ) => { D[ k ] = v } ); // need braces + V.coverdefault = ! D.covervu && ! D.vumeter ? V.coverart : V.covervu; displayBars(); - if ( G.playback ) { + if ( V.playback ) { setButtonControl(); displayPlayback(); renderPlayback(); - } else if ( G.library ) { - if ( ! G.librarylist ) { + } else if ( V.library ) { + if ( ! V.librarylist ) { renderLibrary(); } else if ( $( '.lib-icon' ).eq( 0 ).hasClass( 'fa-music' ) ) { - if ( G.display.hidecover ) { + if ( D.hidecover ) { $( '.licover' ).remove(); } else { - var query = G.query[ G.query.length - 1 ]; + var query = V.query[ V.query.length - 1 ]; list( query, function( html ) { var data = { html : html @@ -172,18 +172,18 @@ function psDisplay( data ) { } ); } } - $( '#button-lib-back' ).toggleClass( 'back-left', G.display.backonleft ); + $( '#button-lib-back' ).toggleClass( 'back-left', D.backonleft ); } } function psEqualizer( data ) { if ( ! $( '#eqpreset' ).length ) return - G.eq = data; + V.eq = data; infoEqualizer( 'update' ); } function psMpdPlayer( data ) { - clearTimeout( G.debounce ); - G.debounce = setTimeout( () => { + clearTimeout( V.debounce ); + V.debounce = setTimeout( () => { if ( data.state === 'play' && ! data.Title && [ 'radiofrance', 'radioparadise' ].includes( data.icon ) ) { bash( [ 'radiorestart' ] ); // fix slow wi-fi - on station changed } @@ -192,46 +192,46 @@ function psMpdPlayer( data ) { delete data.volume; } statusUpdate( data ); - if ( G.playback ) { + if ( V.playback ) { displayPlayback(); renderPlayback(); - } else if ( G.playlist ) { + } else if ( V.playlist ) { setPlaylistScroll(); } - }, G.debouncems ); + }, 300 ); } function psMpdRadio( data ) { statusUpdate( data ); setProgress( 0 ); - if ( G.playback ) { + if ( V.playback ) { setInfo(); setCoverart(); - if ( G.display.radioelapsed ) { + if ( D.radioelapsed ) { $( '#progress' ).html( '' ); setProgressElapsed(); } else { setBlinkDot(); } - } else if ( G.playlist ) { + } else if ( V.playlist ) { setPlaylistScroll(); } } function psMpdUpdate( data ) { if ( 'type' in data ) { if ( data.type === 'mpd' ) { - G.status.updating_db = true; + S.updating_db = true; } else { - G.status.updatingdab = true; + S.updatingdab = true; } setButtonUpdating(); return } - clearTimeout( G.debounce ); - G.debounce = setTimeout( () => { - G.counts = data; - G.status.updating_db = false; - G.status.updatingdab = false; + clearTimeout( V.debounce ); + V.debounce = setTimeout( () => { + C = data; + S.updating_db = false; + S.updatingdab = false; renderLibraryCounts(); setButtonUpdating(); refreshData( 'resetdata' ); @@ -248,16 +248,17 @@ function psNotify( data ) { if ( message === 'Change track ...' ) { // audiocd clearIntervalAll(); } else if ( title === 'Latest' ) { - G.counts.latest = 0; + C.latest = 0; $( '#mode-latest gr' ).empty(); - if ( G.mode === 'latest' ) $( '#button-library' ).click(); + if ( V.mode === 'latest' ) $( '#button-library' ).click(); } else if ( message === 'Online ...' || message === 'Offline ...' ) { // server rAudio power on/off setTimeout( () => location.href = '/', 3000 ); + } else if ( title === 'Power' ) { + pushstreamPower( message ); } - if ( title === 'Power' || title === 'rAudio' ) pushstreamPower( message ); } function psOption( data ) { - if ( G.local ) return + if ( V.local ) return if ( 'addons' in data ) { setButtonUpdateAddons(); @@ -265,61 +266,61 @@ function psOption( data ) { } if ( 'snapclient' in data ) { - G.status.snapclient = data.snapclient; + S.snapclient = data.snapclient; var prefix = $time.is( ':visible' ) ? 'ti' : 'i'; - $( '#'+ prefix +'-snapclient' ).toggleClass( 'hide', ! G.status.snapclient ); + $( '#'+ prefix +'-snapclient' ).toggleClass( 'hide', ! S.snapclient ); return } var option = Object.keys( data )[ 0 ]; - G.status[ option ] = Object.values( data )[ 0 ]; + S[ option ] = Object.values( data )[ 0 ]; setButtonOptions(); } function psOrder( data ) { - if ( G.local ) return + if ( V.local ) return - G.display.order = data; + O = data; orderLibrary(); } function psPlaylist( data ) { if ( ! data.add - && ( G.local || G.sortable || $( '.pl-remove' ).length ) + && ( V.local || V.sortable || $( '.pl-remove' ).length ) ) return - clearTimeout( G.debounce ); - G.debounce = setTimeout( () => { + clearTimeout( V.debounce ); + V.debounce = setTimeout( () => { if ( data == -1 ) { setPlaybackBlank(); renderPlaylist( -1 ); bannerHide(); } else if ( 'autoplaycd' in data ) { - G.autoplaycd = 1; - setTimeout( () => delete G.autoplaycd, 5000 ); + V.autoplaycd = 1; + setTimeout( () => delete V.autoplaycd, 5000 ); } else if ( 'html' in data ) { - G.status.song = data.song; - if ( G.playlist && ! G.savedlist && ! G.savedplaylist ) renderPlaylist( data ); + S.song = data.song; + if ( V.playlist && ! V.savedlist && ! V.savedplaylist ) renderPlaylist( data ); } else { var name = $( '#pl-path .lipath' ).text(); - if ( G.savedplaylist && data.playlist === name ) renderSavedPlaylist( name ); + if ( V.savedplaylist && data.playlist === name ) renderSavedPlaylist( name ); } getPlaybackStatus(); - }, G.debouncems ); + }, 300 ); } function psRadioList( data ) { if ( 'count' in data ) { - G.counts[ data.type ] = data.count; + C[ data.type ] = data.count; $( '#mode-'+ data.type +' gr' ).text( data.count ); } - if ( G.library ) { - if ( G.librarylist && G.mode === data.type ) radioRefresh(); - } else if ( G.playlist ) { - if ( ! G.local ) getPlaylist(); + if ( V.library ) { + if ( V.librarylist && V.mode === data.type ) radioRefresh(); + } else if ( V.playlist ) { + if ( ! V.local ) getPlaylist(); } - G.status.updatingdab = false; + S.updatingdab = false; $( '#i-dabupdate' ).addClass( 'hide' ); } function psRelays( response ) { - clearInterval( G.intRelaysTimer ); + clearInterval( V.intRelaysTimer ); if ( 'on' in response ) { $( '#device'+ response.on ).removeClass( 'gr' ); } else if ( 'off' in response ) { @@ -349,11 +350,11 @@ function psRelays( response ) { } } ); var delay = 59; - G.intRelaysTimer = setInterval( () => { + V.intRelaysTimer = setInterval( () => { if ( delay ) { $( '.infomessage .wh' ).text( delay-- ); } else { - clearInterval( G.intRelaysTimer ); + clearInterval( V.intRelaysTimer ); $( '#relays' ).removeClass( 'on' ); $( '#i-relays, #ti-relays' ).addClass( 'hide' ); } @@ -395,11 +396,11 @@ function psRestore( data ) { } } function psSavedPlaylists( data ) { - var count = data.count; - G.counts.playlists = count; - if ( G.savedlist ) { + var count = data.count; + C.playlists = count; + if ( V.savedlist ) { count ? renderPlaylistList( data ) : $( '#playlist' ).click(); - } else if ( G.savedplaylist ) { + } else if ( V.savedplaylist ) { if ( 'delete' in data && $( '#pl-path .lipath' ).text() === data.delete ) $( '#playlist' ).click(); } $( '#button-pl-playlists' ).toggleClass( 'disabled', count === 0 ); @@ -410,22 +411,22 @@ function psVolume( data ) { $( '#volume-knob, #vol-group i' ).toggleClass( 'disabled', data.val ); return } else if ( 'volumenone' in data ) { - G.display.volumenone = data.volumenone; - $volume.toggleClass( 'hide', ! G.display.volume || G.display.volumenone ); + D.volumenone = data.volumenone; + $volume.toggleClass( 'hide', ! D.volume || D.volumenone ); return } - clearTimeout( G.debounce ); - G.debounce = setTimeout( () => { + clearTimeout( V.debounce ); + V.debounce = setTimeout( () => { if ( data.type === 'mute' ) { - G.status.volume = 0; - G.status.volumemute = data.val; + S.volume = 0; + S.volumemute = data.val; } else { - G.status.volume = data.val; - G.status.volumemute = 0; + S.volume = data.val; + S.volumemute = 0; } setVolume(); - }, G.debouncems ); + }, 300 ); } function psVUmeter( data ) { $( '#vuneedle' ).css( 'transform', 'rotate( '+ data.val +'deg )' ); // 0-100 : 0-42 degree diff --git a/srv/http/assets/js/player.js b/srv/http/assets/js/player.js index b3452f698..375ba875e 100644 --- a/srv/http/assets/js/player.js +++ b/srv/http/assets/js/player.js @@ -10,7 +10,7 @@ Beware of too high volume from speakers. $( '.playback' ).click( function() { if ( ! $( this ).hasClass( 'disabled' ) ) { - var cmd = G.player === 'mpd' ? 'mpcplayback' : 'playerstop'; + var cmd = S.player === 'mpd' ? 'mpcplayback' : 'playerstop'; bash( '/srv/http/bash/cmd.sh '+ cmd ); } } ); @@ -22,13 +22,13 @@ $( '#setting-btreceiver' ).click( function() { info( { icon : 'volume' , title : 'Bluetooth Volume' - , message : G.btaplayname.replace( / - A2DP$/, '' ) + , message : S.btaplayname.replace( / - A2DP$/, '' ) , rangevalue : vol , footer : db +' dB' , beforeshow : () => { $( '#infoButtons' ).toggleClass( 'hide', db === '0.00' ); $( '#infoRange input' ).on( 'click input', function() { - bash( 'amixer -MD bluealsa -q sset "'+ G.btaplayname +'" '+ $( this ).val() +'%' ); + bash( 'amixer -MD bluealsa -q sset "'+ S.btaplayname +'" '+ $( this ).val() +'%' ); } ).on( 'touchend mouseup keyup', function() { bash( [ 'volumepushbt' ] ); } ); @@ -151,13 +151,13 @@ $( '#setting-crossfade' ).click( function() { , textlabel : 'Seconds' , focus : 0 , boxwidth : 60 - , values : G.crossfadeconf || 1 - , checkchanged : G.crossfade + , values : S.crossfadeconf || 1 + , checkchanged : S.crossfade , checkblank : 1 , cancel : () => cancelSwitch( 'crossfade' ) , ok : () => { bash( [ 'crossfade', true, infoVal() ] ); - notify( icon, title, G.crossfade ? 'Change ...' : 'Enable ...' ); + notify( icon, title, S.crossfade ? 'Change ...' : 'Enable ...' ); } } ); } ); @@ -168,12 +168,12 @@ $( '#setting-replaygain' ).click( function() { icon : icon , title : title , radio : { Auto: 'auto', Album: 'album', Track: 'track' } - , values : G.replaygainconf - , checkchanged : G.replaygain + , values : S.replaygainconf + , checkchanged : S.replaygain , cancel : () => cancelSwitch( 'replaygain' ) , ok : () => { bash( [ 'replaygain', true, infoVal() ] ); - notify( icon, title, G.replaygain ? 'Change ...' : 'Enable ...' ); + notify( icon, title, S.replaygain ? 'Change ...' : 'Enable ...' ); } } ); } ); @@ -199,13 +199,13 @@ $( '#setting-buffer' ).click( function() { , footer : '(default: 4096)' , footeralign : 'right' , boxwidth : 110 - , values : G.bufferconf - , checkchanged : G.buffer + , values : S.bufferconf + , checkchanged : S.buffer , checkblank : 1 , cancel : () => cancelSwitch( 'buffer' ) , ok : () => { bash( [ 'buffer', true, infoVal() ] ); - notify( icon, title, G.buffer ? 'Change ...' : 'Enable ...' ); + notify( icon, title, S.buffer ? 'Change ...' : 'Enable ...' ); } } ); } ); @@ -220,18 +220,18 @@ $( '#setting-outputbuffer' ).click( function() { , footer : '(default: 8192)' , footeralign : 'right' , boxwidth : 110 - , values : G.outputbufferconf - , checkchanged : G.outputbuffer + , values : S.outputbufferconf + , checkchanged : S.outputbuffer , checkblank : 1 , cancel : () => cancelSwitch( 'outputbuffer' ) , ok : () => { bash( [ 'outputbuffer', true, infoVal() ] ); - notify( icon, title, G.outputbuffer ? 'Change ...' : 'Enable ...' ); + notify( icon, title, S.outputbuffer ? 'Change ...' : 'Enable ...' ); } } ); } ); $( '#setting-soxr' ).click( function() { - infoSoxr( G.soxrquality || 'very high' ); + infoSoxr( S.soxrquality || 'very high' ); } ); var custominfo = `\ @@ -259,9 +259,9 @@ $( '#setting-custom' ).click( function() { info( { icon : icon , title : title - , content : custominfo.replace( 'N', G.asoundcard ) + , content : custominfo.replace( 'N', S.asoundcard ) , values : [ valglobal, valoutput ] - , checkchanged : G.custom + , checkchanged : S.custom , cancel : () => cancelSwitch( 'custom' ) , ok : () => { var values = infoVal(); @@ -282,7 +282,7 @@ $( '#setting-custom' ).click( function() { } ); } }, 'json' ); - notify( icon, title, G.custom ? 'Change ...' : 'Enable ...' ); + notify( icon, title, S.custom ? 'Change ...' : 'Enable ...' ); } } ); } ); @@ -352,9 +352,9 @@ function infoSoxr( quality ) { , tabfunction : [ infoSoxrPreset, infoSoxrCustom ] , tabactive : custom ? 1 : 0 , content : custom ? soxrcustom : soxr - , values : custom ? G.soxrcustomconf : G.soxrconf + , values : custom ? S.soxrcustomconf : S.soxrconf , checkblank : 1 - , checkchanged : G.soxr && quality === G.soxrquality + , checkchanged : S.soxr && quality === S.soxrquality , boxwidth : custom ? 85 : 180 , cancel : () => cancelSwitch( 'soxr' ) , ok : () => { @@ -363,7 +363,7 @@ function infoSoxr( quality ) { } else { bash( [ 'soxr', true, ...infoVal() ] ); } - notify( icon, title, G.soxr ? 'Change ...' : 'Enable ...' ); + notify( icon, title, S.soxr ? 'Change ...' : 'Enable ...' ); } } ); } @@ -371,42 +371,42 @@ function infoSoxrCustom() { infoSoxr( 'custom' ); } function infoSoxrPreset() { - infoSoxr( G.soxrquality === 'custom' ? 'very high' : G.soxrquality ); + infoSoxr( S.soxrquality === 'custom' ? 'very high' : S.soxrquality ); } function playbackIcon() { $( '.playback' ) .removeClass( 'fa-pause fa-play fa-stop' ) - .addClass( 'fa fa-'+ G.state ) - .toggleClass( 'disabled', G.player !== 'mpd' && G.state !== 'play' ); + .addClass( 'fa fa-'+ S.state ) + .toggleClass( 'disabled', S.player !== 'mpd' && S.state !== 'play' ); } function renderPage() { playbackIcon(); - var htmlstatus = G.version +'
    ' - +' '+ ( G.counts.song || 0 ).toLocaleString() +'  ' - +' '+ ( G.counts.album || 0 ).toLocaleString() +'  ' - +' '+ ( G.counts.webradio || 0 ).toLocaleString() +''; + var htmlstatus = S.version +'
    ' + +' '+ ( S.counts.song || 0 ).toLocaleString() +'  ' + +' '+ ( S.counts.album || 0 ).toLocaleString() +'  ' + +' '+ ( S.counts.webradio || 0 ).toLocaleString() +''; $( '#statusvalue' ).html( htmlstatus ); - if ( G.btaplayname ) { + if ( S.btaplayname ) { $( '#divbtreceiver' ).removeClass( 'hide' ); - $( '#btaplayname' ).html( '' ); + $( '#btaplayname' ).html( '' ); $( '#setting-btreceiver' ).removeClass( 'hide' ); } else { $( '#divbtreceiver' ).addClass( 'hide' ); } - if ( G.asoundcard === -1 ) { + if ( S.asoundcard === -1 ) { $( '#divoutput, #divbitperfect, #divvolume' ).addClass( 'hide' ); } else { - D = G.devices[ G.asoundcard ]; - G.resampled = G.crossfade || G.normalization || G.replaygain || G.camilladsp || G.equalizer || G.soxr; - G.novolume = D.mixertype === 'none' && ! G.resampled; + D = S.devices[ S.asoundcard ]; + S.resampled = S.crossfade || S.normalization || S.replaygain || S.camilladsp || S.equalizer || S.soxr; + S.novolume = D.mixertype === 'none' && ! S.resampled; var htmldevices = ''; - $.each( G.devices, ( i, el ) => { + $.each( S.devices, ( i, el ) => { if ( el.aplayname !== 'Loopback' ) htmldevices += ''; } ); $( '#divoutput, #divbitperfect, #divvolume' ).removeClass( 'hide' ); $( '#audiooutput' ) .html( htmldevices ) - .val( G.asoundcard ); + .val( S.asoundcard ); var htmlhwmixer = D.mixermanual ? '' : ''; if ( 'mixerdevices' in D ) { D.mixerdevices.forEach( mixer => htmlhwmixer += '' ); @@ -421,13 +421,13 @@ function renderPage() { .html( htmlmixertype ) .val( D.mixertype ); $( '#setting-hwmixer' ).toggleClass( 'hide', D.mixers === 0 ); - $( '#novolume' ).prop( 'checked', G.novolume ); + $( '#novolume' ).prop( 'checked', S.novolume ); $( '#divdop' ).toggleClass( 'disabled', D.aplayname.slice( 0, 7 ) === 'bcm2835' ); - $( '#dop' ).prop( 'checked', G.dop ); - $( '#ffmpeg' ).toggleClass( 'disabled', G.dabradio ); - if ( G.camilladsp ) { + $( '#dop' ).prop( 'checked', S.dop ); + $( '#ffmpeg' ).toggleClass( 'disabled', S.dabradio ); + if ( S.camilladsp ) { var label = ''; - } else if ( G.equalizer ) { + } else if ( S.equalizer ) { var label = 'Equalizer'; } else { var label = 'Device'; @@ -446,8 +446,8 @@ function renderPage() { $( '#infoButtons a' ).eq( 1 ).toggleClass( 'hide', db === '0.00' ); } ); } - $( '#divlists' ).toggleClass( 'hide', !G.lists.includes( true ) ); - for ( i = 0; i < 3; i++ ) $( '#divlists .sub' ).eq( i ).toggleClass( 'hide', !G.lists[ i ] ); + $( '#divlists' ).toggleClass( 'hide', ! S.lists.includes( true ) ); + for ( i = 0; i < 3; i++ ) $( '#divlists .sub' ).eq( i ).toggleClass( 'hide', ! S.lists[ i ] ); showContent(); } function setMixerType( mixertype ) { @@ -457,7 +457,7 @@ function setMixerType( mixertype ) { } function setVolumeSlider() { $( '#infoRange input' ).on( 'click input keyup', function() { - bash( 'amixer -c '+ G.asoundcard +' -Mq sset "'+ D.hwmixer +'" '+ $( this ).val() +'%' ); + bash( 'amixer -c '+ S.asoundcard +' -Mq sset "'+ D.hwmixer +'" '+ $( this ).val() +'%' ); } ).on( 'touchend mouseup keyup', function() { bash( [ 'volumepush' ] ); } ); diff --git a/srv/http/assets/js/plugin/jquery-3.6.1.min.js b/srv/http/assets/js/plugin/jquery-3.6.1.min.js deleted file mode 100644 index 2c69bc908..000000000 --- a/srv/http/assets/js/plugin/jquery-3.6.1.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jQuery v3.6.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,y=n.hasOwnProperty,a=y.toString,l=a.call(Object),v={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&v(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!y||!y.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ve(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ye(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ve(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],y=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||y.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||y.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||y.push(".#.+[+~]"),e.querySelectorAll("\\\f"),y.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),y=y.length&&new RegExp(y.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),v=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&v(p,e)?-1:t==C||t.ownerDocument==p&&v(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!y||!y.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),v.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",v.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",v.option=!!ce.lastChild;var ge={thead:[1,"
    ","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),v.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="
    ",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(v.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return B(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=_e(v.pixelPosition,function(e,t){if(t)return t=Be(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return B(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,S)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&v(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!y||!y.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ve(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=E)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{if(d.cssSupportsSelector&&!CSS.supports("selector("+c+")"))throw new Error;return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===E&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[E]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ye(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ve(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,S=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.cssSupportsSelector=ce(function(){return CSS.supports("selector(*)")&&C.querySelectorAll(":is(:jqfake)")&&!CSS.supports("selector(:is(*,:jqfake))")}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=E,!C.getElementsByName||!C.getElementsByName(E).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&S){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&S){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&S)return t.getElementsByClassName(e)},s=[],y=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+E+"-]").length||y.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||y.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+E+"+*").length||y.push(".#.+[+~]"),e.querySelectorAll("\\\f"),y.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),d.cssSupportsSelector||y.push(":has"),y=y.length&&new RegExp(y.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),v=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType&&e.documentElement||e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&v(p,e)?-1:t==C||t.ownerDocument==p&&v(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&S&&!N[t+" "]&&(!s||!s.test(t))&&(!y||!y.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?E.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?E.grep(e,function(e){return e===n!==r}):"string"!=typeof n?E.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(E.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof E?t[0]:t,E.merge(this,E.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:S,!0)),N.test(r[1])&&E.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=S.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(E):E.makeArray(e,this)}).prototype=E.fn,D=E(S);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}E.fn.extend({has:function(e){var t=E(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=S.createDocumentFragment().appendChild(S.createElement("div")),(fe=S.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),v.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",v.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",v.option=!!ce.lastChild;var ge={thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?E.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&E(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),S.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;E.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||E.expando+"_"+Ct.guid++;return this[e]=!0,e}}),E.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||E.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?E(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),v.createHTMLDocument=((Ut=S.implementation.createHTMLDocument("").body).innerHTML="
    ",2===Ut.childNodes.length),E.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(v.createHTMLDocument?((r=(t=S.implementation.createHTMLDocument("")).createElement("base")).href=S.location.href,t.head.appendChild(r)):t=S),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&E(o).remove(),E.merge([],i.childNodes)));var r,i,o},E.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(E.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},E.expr.pseudos.animated=function(t){return E.grep(E.timers,function(e){return t===e.elem}).length},E.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=E.css(e,"position"),c=E(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=E.css(e,"top"),u=E.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,E.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},E.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){E.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===E.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===E.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=E(e).offset()).top+=E.css(e,"borderTopWidth",!0),i.left+=E.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-E.css(r,"marginTop",!0),left:t.left-i.left-E.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===E.css(e,"position"))e=e.offsetParent;return e||re})}}),E.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;E.fn[t]=function(e){return B(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),E.each(["top","left"],function(e,n){E.cssHooks[n]=_e(v.pixelPosition,function(e,t){if(t)return t=Be(e,n),Pe.test(t)?E(e).position()[n]+"px":t})}),E.each({Height:"height",Width:"width"},function(a,s){E.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){E.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return B(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?E.css(e,t,i):E.style(e,t,n,i)},s,n?e:void 0,n)}})}),E.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){E.fn[t]=function(e){return this.on(t,e)}}),E.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),E.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){E.fn[n]=function(e,t){return 0>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +R = {} +var values0; + $( '.gpio-no' ).addClass( 'hide' ); -renderPage = function( changed ) { - if ( typeof D === 'undefined' ) { - D = { val : {}, key : {} }; - D.keys = [ 'pin', 'name', 'on', 'off', 'ond', 'offd' ]; - D.keys.forEach( k => D.val[ k ] = G[ k ] ); - D.val.timer = G.timer; - D.values = [].concat.apply( [], Object.values( D.val ) ).toString(); +$( '.container' ).on( 'change', 'select', function() { + if ( this.id.slice( 0, 3 ) === 'pin' ) { + var i = +this.id.slice( -1 ); + var val = +this.value; + var val0 = R.pin[ i ]; + R.on.forEach( ( el, i ) => { + if ( el == val0 ) R.on[ i ] = val; + } ); + R.off.forEach( ( el, i ) => { + if ( el == val0 ) R.off[ i ] = val; + } ); + } + refreshValues(); +} ); +$( 'input' ).keyup( refreshValues ); +$( '.back' ).click( function() { + location.href = 'settings.php?p=system'; +} ); +$( '#undo' ).click( function() { + R = {} + renderPage( false ); +} ); +$( '#save' ).off( 'click' ).click( function() { + var onorder = []; + var offorder = []; + for ( i = 0; i < 4; i++ ) { + onorder.push( $( '#on'+ i +' option:selected' ).text() ); + offorder.push( $( '#off'+ i+' option:selected' ).text() ); + } + var cmd = [ + 'save' + , 'pin=\'[ '+ R.pin.join( ',' ) +' ]\'' + , 'name=\'[ "'+ R.name.join( '","' ) +'" ]\'' + , 'onorder=\'[ "'+ onorder.join( '","' ) +'" ]\'' + , 'offorder=\'[ "'+ offorder.join( '","' ) +'" ]\'' + , 'on=( '+ R.on.join( ' ' ) +' )' + , 'ond=( '+ R.ond.join( ' ' ) +' )' + , 'off=( '+ R.off.join( ' ' ) +' )' + , 'offd=( '+ R.offd.join( ' ' ) +' )' + , 'timer='+ R.timer + ]; + bash( cmd ); + banner( 'relays', 'Relays', 'Change ...' ); +} ); + +} ); //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + +function refreshValues() { + $( '#gpio-num .pin' ).each( ( i, el ) => R.pin[ i ] = +$( el ).val() ); + $( '.name' ).each( ( i, el ) => R.name[ i ] = $( el ).val() ); + $( '.on.delay' ).each( ( i, el ) => R.ond[ i ] = R.on[ i + 1 ] ? +$( el ).val() : 0 ); + $( '.off.delay' ).each( ( i, el ) => R.offd[ i ] = R.off[ i + 1 ] ? +$( el ).val() : 0 ); + R.timer = +$( '#timer' ).val(); + var values = [].concat.apply( [], Object.values( R ) ).toString(); + renderPage( values !== values0 ); +} +function renderPage( changed ) { + if ( ! ( 'pin' in R ) ) { + R = JSON.parse( JSON.stringify( S ) ); + values0 = [].concat.apply( [], Object.values( S ) ).toString(); } - $( '#save' ).toggleClass( 'disabled', G.enabled && ! changed ) + $( '#save' ).toggleClass( 'disabled', S.enabled && ! changed ) $( '#undo' ).toggleClass( 'disabled', ! changed ) var optnamepin = ''; - for ( i = 0; i < 4; i++ ) optnamepin += ''; - var htmlon = ''; - var htmloff = ''; - var optsec = ''; + for ( i = 0; i < 4; i++ ) optnamepin += ''; + var htmlon = ''; + var htmloff = ''; + var optsec = ''; for ( i = 1; i < 11; i++ ) optsec += ''; - htmlsec = 'sec.'; + htmlsec = 'sec.'; for ( i = 0; i < 4; i++ ) { - htmlon += ''; - htmloff += ''; + htmlon += ''; + htmloff += ''; if ( i < 3 ) { - htmlon += ''+ optsec + htmlsec; htmloff += '0x'+ el.toString( 16 ) +'' ); + if ( ! S.lcdcharaddr ) S.lcdcharaddr = [ 39, 63 ]; + S.lcdcharaddr.forEach( el => i2caddress += '' ); var optpins = ''; @@ -311,7 +311,7 @@ $( '#setting-lcdchar' ).click( function() { `; // cols charmap inf address chip pin_rs pin_rw pin_e pins_data backlight - var i2c = G.lcdcharconf[ 2 ] !== 'gpio'; + var i2c = S.lcdcharconf[ 2 ] !== 'gpio'; var icon = 'lcdchar'; var title = 'Character LCD'; info( { @@ -319,8 +319,8 @@ $( '#setting-lcdchar' ).click( function() { , title : title , content : infolcdchar , boxwidth : 180 - , values : G.lcdcharconf || [ 20, 'A00', 'i2c', 39, 'PCF8574', 15, 18, 16, 21, 22, 23, 24, false ] - , checkchanged : G.lcdchar + , values : S.lcdcharconf || [ 20, 'A00', 'i2c', 39, 'PCF8574', 15, 18, 16, 21, 22, 23, 24, false ] + , checkchanged : S.lcdchar , beforeshow : () => { $( '#infoContent .gpio td:even' ).css( 'width', 55 ); $( '#infoContent .gpio td:odd' ).css( { @@ -336,7 +336,7 @@ $( '#setting-lcdchar' ).click( function() { $( '.i2c' ).toggleClass( 'hide', ! i2c ); $( '.gpio' ).toggleClass( 'hide', i2c ); } ); - if ( G.lcdchar ) { + if ( S.lcdchar ) { $( '#infoOk' ) .before( ' ' ) .after( '  Sleep' ); @@ -349,7 +349,7 @@ $( '#setting-lcdchar' ).click( function() { , cancel : () => cancelSwitch( 'lcdchar' ) , ok : () => { bash( [ 'lcdchar', true, ...infoVal() ] ); - notify( icon, title, G.lcdchar ? 'Change ...' : 'Enabled ...' ); + notify( icon, title, S.lcdchar ? 'Change ...' : 'Enabled ...' ); } } ); } ); @@ -389,11 +389,11 @@ $( '#setting-powerbutton' ).click( function() { , title : title , content : gpiosvg + infopowerbutton , boxwidth : 80 - , values : G.powerbuttonconf || [ 5, 5, 40, 5, false ] - , checkchanged : G.powerbutton + , values : S.powerbuttonconf || [ 5, 5, 40, 5, false ] + , checkchanged : S.powerbutton , beforeshow : () => { - if ( ! G.powerbuttonconf[ 3 ] ) { - $( '#infoContent .reserved' ).toggleClass( 'hide', G.powerbuttonconf[ 0 ] == 5 ); + if ( ! S.powerbuttonconf[ 3 ] ) { + $( '#infoContent .reserved' ).toggleClass( 'hide', S.powerbuttonconf[ 0 ] == 5 ); $( '#infoContent select' ).eq( 0 ).change( function() { $( '#infoContent .reserved' ).toggleClass( 'hide', $( this ).val() == 5 ); } ); @@ -407,7 +407,7 @@ $( '#setting-powerbutton' ).click( function() { , cancel : () => cancelSwitch( 'powerbutton' ) , ok : () => { bash( [ 'powerbutton', true, ...infoVal() ] ); - notify( icon, title, G.powerbutton ? 'Change ...' : 'Enable ...' ); + notify( icon, title, S.powerbutton ? 'Change ...' : 'Enable ...' ); } } ); } ); @@ -435,13 +435,13 @@ $( '#setting-rotaryencoder' ).click( function() { , title : title , content : gpiosvg + inforotaryencoder , boxwidth : 90 - , values : G.rotaryencoderconf || [ 27, 22 ,23 ,1 ] - , checkchanged : G.rotaryencoder + , values : S.rotaryencoderconf || [ 27, 22 ,23 ,1 ] + , checkchanged : S.rotaryencoder , beforeshow : () => $( '#infoContent svg .power' ).remove() , cancel : () => cancelSwitch( 'rotaryencoder' ) , ok : () => { bash( [ 'rotaryencoder', true, ...infoVal() ] ); - notify( icon, title, G.rotaryencoder ? 'Change ...' : 'Enable ...' ); + notify( icon, title, S.rotaryencoder ? 'Change ...' : 'Enable ...' ); } } ); } ); @@ -469,11 +469,11 @@ $( '#setting-mpdoled' ).click( function() { ` - , values : G.mpdoledconf - , checkchanged : G.mpdoled + , values : S.mpdoledconf + , checkchanged : S.mpdoled , boxwidth : 140 , beforeshow : () => { - var i2c = ! G.mpdoled || ( G.mpdoled && G.mpdoledconf[ 1 ] ); + var i2c = ! S.mpdoled || ( S.mpdoled && S.mpdoledconf[ 1 ] ); $( '.baud' ).toggleClass( 'hide', ! i2c ); $( '.oledchip' ).change( function() { var val = $( this ).val(); @@ -481,10 +481,10 @@ $( '#setting-mpdoled' ).click( function() { } ); } , cancel : () => cancelSwitch( 'mpdoled' ) - , buttonlabel : ! G.mpdoled ? '' : 'Logo' - , button : ! G.mpdoled ? '' : () => bash( [ 'mpdoledlogo' ] ) + , buttonlabel : ! S.mpdoled ? '' : 'Logo' + , button : ! S.mpdoled ? '' : () => bash( [ 'mpdoledlogo' ] ) , ok : () => { - notify( icon, title, G.mpdoled ? 'Change ...' : 'Enable ...' ); + notify( icon, title, S.mpdoled ? 'Change ...' : 'Enable ...' ); bash( [ 'mpdoled', true, ...infoVal() ] ); } } ); @@ -503,11 +503,11 @@ $( '#setting-lcd' ).click( function() { , 'Waveshare (B) Rev 2.0' : 'waveshare35b-v2' , 'Waveshare (C)' : 'waveshare35c' } - , values : G.lcdmodel || 'tft35a' - , checkchanged : G.lcd + , values : S.lcdmodel || 'tft35a' + , checkchanged : S.lcd , boxwidth : 190 - , buttonlabel : ! G.lcd ? '' : 'Calibrate' - , button : ! G.lcd ? '' : () => { + , buttonlabel : ! S.lcd ? '' : 'Calibrate' + , button : ! S.lcd ? '' : () => { info( { icon : icon , title : title @@ -521,7 +521,7 @@ $( '#setting-lcd' ).click( function() { } , cancel : () => cancelSwitch( 'lcd' ) , ok : () => { - notify( icon, title, G.lcd ? 'Change ...' : 'Enable ...' ); + notify( icon, title, S.lcd ? 'Change ...' : 'Enable ...' ); bash( [ 'lcd', true, infoVal() ] ); } } ); @@ -540,8 +540,8 @@ $( '#setting-vuled' ).click( function() { , title : title , message : gpiosvg , select : htmlpins - , values : G.vuledconf || [ 14, 15, 18, 23, 24, 25, 8 ] - , checkchanged : G.vuled + , values : S.vuledconf || [ 14, 15, 18, 23, 24, 25, 8 ] + , checkchanged : S.vuled , boxwidth : 80 , cancel : () => cancelSwitch( 'vuled' ) , ok : () => { @@ -583,7 +583,7 @@ $( '#hostname' ).on( 'mousedown touchdown', function() { , title : title , textlabel : 'Name' , focus : 0 - , values : G.hostname + , values : S.hostname , checkblank : 1 , checkchanged : 1 , beforeshow : () => { @@ -604,13 +604,13 @@ $( '#timezone' ).change( function( e ) { $( '#setting-timezone' ).click( function() { var icon = 'globe'; var title = 'Servers'; - if ( G.soc === 'BCM2835' || G.soc === 'BCM2836' ) { // rpi 0, 1 + if ( S.soc === 'BCM2835' || S.soc === 'BCM2836' ) { // rpi 0, 1 info( { icon : icon , title : title , textlabel : 'NTP' , boxwidth : 300 - , values : G.ntp + , values : S.ntp , checkchanged : 1 , checkblank : 1 , ok : () => { @@ -636,12 +636,12 @@ $( '#setting-timezone' ).click( function() { , title : title , content : content , boxwidth : 240 - , values : [ G.ntp, list.current ] + , values : [ S.ntp, list.current ] , checkchanged : 1 , checkblank : [ 0 ] , ok : () => { var values = infoVal(); - if ( values[ 0 ] !== G.ntp ) notify( icon, title, 'Sync ...' ); + if ( values[ 0 ] !== S.ntp ) notify( icon, title, 'Sync ...' ); bash( [ 'servers', ...values ], bannerHide ); } } ); @@ -656,13 +656,13 @@ $( '#setting-soundprofile' ).click( function() { , title : title , textlabel : [ 'vm.swappiness', 'lan mtu', 'lan txqueuelen' ] , boxwidth : 110 - , values : G.soundprofileconf - , checkchanged : G.soundprofile + , values : S.soundprofileconf + , checkchanged : S.soundprofile , checkblank : 1 , cancel : () => cancelSwitch( 'soundprofile' ) , ok : () => { bash( [ 'soundprofile', true, ...infoVal() ] ); - notify( icon, title, G.soundprofile ? 'Change ...' : 'Enable ...' ); + notify( icon, title, S.soundprofile ? 'Change ...' : 'Enable ...' ); } } ); } ); @@ -793,7 +793,7 @@ $( '#shareddata' ).click( function() { return } - if ( G.shareddata ) { + if ( S.shareddata ) { info( { icon : icon , title : title @@ -1014,10 +1014,10 @@ function renderPage() { $( '#codehddinfo' ) .empty() .addClass( 'hide' ); - $( '#systemvalue' ).html( G.system ); - $( '#status' ).html( G.status ); + $( '#systemvalue' ).html( S.system ); + $( '#status' ).html( S.status ); var html = ''; - $.each( G.list, ( i, val ) => { + $.each( S.list, ( i, val ) => { if ( val.mounted ) { var dataunmounted = ''; var dot = ' • '; @@ -1036,18 +1036,18 @@ function renderPage() { } ); $( '#list' ).html( html ); $( '#divhddsleep' ).toggleClass( 'hide', $( '#list .fa-usbdrive' ).length === 0 ); - $( '#hddsleep' ).toggleClass( 'disabled', ! G.hddapm ); - $( '#usbautoupdate' ).toggleClass( 'disabled', G.shareddata || G.nfsserver ); - if ( 'bluetooth' in G || 'wlan' in G ) { - if ( 'bluetooth' in G ) { - $( '#bluetooth' ).parent().prev().toggleClass( 'single', ! G.bluetoothactive ); + $( '#hddsleep' ).toggleClass( 'disabled', ! S.hddapm ); + $( '#usbautoupdate' ).toggleClass( 'disabled', S.shareddata || S.nfsserver ); + if ( 'bluetooth' in S || 'wlan' in S ) { + if ( 'bluetooth' in S ) { + $( '#bluetooth' ).parent().prev().toggleClass( 'single', ! S.bluetoothactive ); } else { $( '#divbluetooth' ).addClass( 'hide' ); } - if ( 'wlan' in G ) { + if ( 'wlan' in S ) { $( '#wlan' ) - .toggleClass( 'disabled', G.hostapd || G.wlanconnected ) - .parent().prev().toggleClass( 'single', ! G.wlan ); + .toggleClass( 'disabled', S.hostapd || S.wlanconnected ) + .parent().prev().toggleClass( 'single', ! S.wlan ); } else { $( '#divwlan' ).addClass( 'hide' ); } @@ -1057,17 +1057,17 @@ function renderPage() { $( '#i2smodule' ).val( 'none' ); $( '#i2smodule option' ).filter( ( i, el ) => { var $this = $( el ); - return $this.text() === G.audiooutput && $this.val() === G.audioaplayname; + return $this.text() === S.audiooutput && $this.val() === S.audioaplayname; } ).prop( 'selected', true ); - G.i2senabled = $( '#i2smodule' ).val() !== 'none'; - $( '#divi2smodulesw' ).toggleClass( 'hide', G.i2senabled ); - $( '#divi2smodule, #setting-i2smodule' ).toggleClass( 'hide', ! G.i2senabled ); - $( '#bluetooth' ).toggleClass( 'disabled', G.btconnected ); - $( '#divsoundprofile' ).toggleClass( 'hide', ! G.soundprofileconf ); - $( '#hostname' ).val( G.hostname ); - $( '#avahiurl' ).text( G.hostname +'.local' ); - $( '#timezone' ).val( G.timezone ); - $( '#shareddata' ).toggleClass( 'disabled', G.nfsserver ); + S.i2senabled = $( '#i2smodule' ).val() !== 'none'; + $( '#divi2smodulesw' ).toggleClass( 'hide', S.i2senabled ); + $( '#divi2smodule, #setting-i2smodule' ).toggleClass( 'hide', ! S.i2senabled ); + $( '#bluetooth' ).toggleClass( 'disabled', S.btconnected ); + $( '#divsoundprofile' ).toggleClass( 'hide', ! S.soundprofileconf ); + $( '#hostname' ).val( S.hostname ); + $( '#avahiurl' ).text( S.hostname +'.local' ); + $( '#timezone' ).val( S.timezone ); + $( '#shareddata' ).toggleClass( 'disabled', S.nfsserver ); $( '#setting-shareddata' ).remove(); showContent(); } diff --git a/srv/http/bash/bluetoothcommand.sh b/srv/http/bash/bluetoothcommand.sh index 8cac1ce4a..35194bb93 100644 --- a/srv/http/bash/bluetoothcommand.sh +++ b/srv/http/bash/bluetoothcommand.sh @@ -151,6 +151,7 @@ if [[ $action == connect || $action == pair ]]; then icon=btsender [[ $mac && $name ]] && echo $mac Source $name >> $dirshm/btconnected else + (( $( grep -c . <<< $btmixer ) > 1 )) && btmixer=$( grep A2DP <<< $btmixer ) btmixer=$( cut -d"'" -f2 <<< $btmixer ) ##### receiver echo $btmixer > $dirshm/btreceiver diff --git a/srv/http/bash/cmd.sh b/srv/http/bash/cmd.sh index 37ffcad87..63547421e 100644 --- a/srv/http/bash/cmd.sh +++ b/srv/http/bash/cmd.sh @@ -65,7 +65,9 @@ plAddPosition() { fi } plAddRandom() { - plLengthSong + total=$( getStatus playlistlength ) + pos=$( getStatus song ) + tail=$(( total - pos )) (( $tail > 1 )) && pushstreamPlaylist add && return dir=$( shuf -n 1 $dirmpd/album | cut -d^ -f7 ) @@ -92,15 +94,6 @@ plAddRandom() { fi (( $tail > 1 )) || plAddRandom } -plLengthSong() { - readarray -t status <<< $( { echo status; sleep 0.05; } \ - | telnet 127.0.0.1 6600 2> /dev/null \ - | grep -E '^playlistlength:|^song:' \ - | cut -d' ' -f2 ) - total=${status[0]} - pos=$(( ${status[1]} + 1 )) - tail=$(( total - pos )) -} pushstreamPlaylist() { [[ $1 ]] && arg=$1 || arg=current pushstream playlist $( php /srv/http/mpdplaylist.php $arg ) @@ -310,9 +303,6 @@ audiocdtag ) sed -i "$track s|.*|$tag|" $diraudiocd/$discid pushstreamPlaylist ;; -autoplaystatus ) - [[ -e $dirsystem/autoplay ]] && $dirbash/status-push.sh - ;; bookmarkadd ) name=${args[1]//\//|} path=${args[2]} @@ -538,6 +528,9 @@ equalizerupdn ) val=${args[2]} sudo -u mpd amixer -D equal sset "$band" $val ;; +getelapsed ) + getElapsed + ;; ignoredir ) touch $dirmpd/updating path=${args[1]} @@ -560,7 +553,9 @@ librandom ) else [[ ${args[2]} == true ]] && play=1 mpc -q random 0 - plLengthSong + total=$( getStatus playlistlength ) + pos=$( getStatus song ) + tail=$(( total - pos )) if [[ $play ]]; then playnext=$(( total + 1 )) (( $tail > 0 )) && mpc -q play $total && mpc -q stop @@ -920,10 +915,7 @@ power ) fi cdda=$( mpc -f %file%^%position% playlist | grep ^cdda: | cut -d^ -f2 ) [[ $cdda ]] && mpc -q del $cdda - if [[ -e $dirshm/relayson ]]; then - $dirsettings/relays.sh - sleep 2 - fi + [[ -e $dirshm/relayson ]] && $dirsettings/relays.sh && sleep 2 systemctl -q is-active camilladsp && camilladsp-gain.py ply-image /srv/http/assets/img/splash.png &> /dev/null if mount | grep -q -m1 $dirnas; then @@ -931,8 +923,10 @@ power ) sleep 3 fi [[ -e /boot/shutdown.sh ]] && . /boot/shutdown.sh - [[ $action == off && -e $dirsystem/lcdchar ]] && lcdchar.py off - [[ $action == reboot ]] && reboot || poweroff + [[ $action == reboot ]] && reboot && exit + + [[ -e $dirsystem/lcdchar ]] && lcdchar.py off + poweroff ;; radiorestart ) [[ -e $disshm/radiorestart ]] && exit diff --git a/srv/http/bash/common.sh b/srv/http/bash/common.sh index 383cd05e0..a3bd15243 100644 --- a/srv/http/bash/common.sh +++ b/srv/http/bash/common.sh @@ -28,24 +28,20 @@ cpuInfo() { data2json() { data="$1" if [[ ${data:0:1} != , ]]; then - data="\ -{ -$data -}" + data+=' +, "login" : '$( exists $dirsystem/login ) + json="{ $data }" else - data="\ -[ -${data:1} -]" + json="[ ${data:1} ]" fi # "k": > "k": false # "k":} > "k": false} # [, > [false, # ,, > ,false, # ,] > ,false] - data=$( sed 's/:\s*$/: false/ + json=$( sed 's/:\s*$/: false/ s/:\s*}$/: false }/ s/^,\s*$/, false/ s/\[\s*,/[ false,/g s/,\s*,/, false,/g - s/,\s*]/, false ]/g' <<< $data ) - [[ $2 ]] && pushstream refresh "$data" || echo "$data" + s/,\s*]/, false ]/g' <<< $json ) + [[ $2 ]] && pushstream refresh "$json" || echo "$json" } exists() { [[ -e $1 ]] && echo true || echo false @@ -53,6 +49,15 @@ exists() { getContent() { [[ -e "$1" ]] && cat "$1" } +getElapsed() { + getStatus elapsed +} +getStatus() { + printf '%.0f' $( { echo status; sleep 0.05; } \ + | telnet 127.0.0.1 6600 2> /dev/null \ + | grep ^$1: \ + | cut -d' ' -f2 ) +} ipAddress() { ifconfig | awk '/inet.*broadcast/ {print $2;exit}' } diff --git a/srv/http/bash/settings/features.sh b/srv/http/bash/settings/features.sh index e4dd4aef5..e90d89420 100644 --- a/srv/http/bash/settings/features.sh +++ b/srv/http/bash/settings/features.sh @@ -109,8 +109,8 @@ equalizer ) else rm -f $dirsystem/equalizer fi - $dirsettings/player-conf.sh pushRefresh + $dirsettings/player-conf.sh pushSubmenu equalizer $enabled ;; hostapdget ) diff --git a/srv/http/bash/settings/player-conf.sh b/srv/http/bash/settings/player-conf.sh index 6ae7ad0f8..442ee8687 100644 --- a/srv/http/bash/settings/player-conf.sh +++ b/srv/http/bash/settings/player-conf.sh @@ -139,8 +139,8 @@ fi ( sleep 2 && systemctl try-restart rotaryencoder ) &> /dev/null & if [[ $equalizer || $dsp || ( ! $Acard && ! $btmixer ) ]]; then - $dirbash/status-push.sh $dirsettings/player-data.sh pushrefresh + $dirbash/status-push.sh exit fi @@ -192,5 +192,5 @@ volume_controller = "alsa"' systemctl try-restart spotifyd fi -$dirbash/status-push.sh $dirsettings/player-data.sh pushrefresh +$dirbash/status-push.sh diff --git a/srv/http/bash/settings/player.sh b/srv/http/bash/settings/player.sh index bc74190c6..7c2bb2961 100644 --- a/srv/http/bash/settings/player.sh +++ b/srv/http/bash/settings/player.sh @@ -1,8 +1,5 @@ #!/bin/bash -# restartMPD - simple changes -# $dirsettings/player-conf.sh - complex changes - . /srv/http/bash/common.sh # convert each line to each args @@ -11,10 +8,6 @@ readarray -t args <<< $1 linkConf() { ln -sf $dirmpdconf/{conf/,}${args[0]}.conf } -restartMPD() { - systemctl restart mpd - pushRefresh -} volumeGet() { card=$( < $dirsystem/asoundcard ) control=$( getContent $dirshm/amixercontrol ) @@ -39,7 +32,8 @@ audiooutput ) ;; autoupdate | ffmpeg | normalization ) [[ ${args[1]} == true ]] && linkConf || rm $dirmpdconf/${args[0]}.conf - restartMPD + systemctl restart mpd + pushRefresh ;; albumignore ) cat $dirmpd/albumignore @@ -64,7 +58,7 @@ buffer | outputbuffer ) else rm $dirmpdconf/$type.conf fi - restartMPD + $dirsettings/player-conf.sh ;; crossfade ) if [[ ${args[1]} == true ]]; then @@ -148,7 +142,7 @@ dop ) else rm -f "$dirsystem/dop-${args[2]}" fi - restartMPD + $dirsettings/player-conf.sh ;; filetype ) type=$( mpd -V \ @@ -222,20 +216,11 @@ replaygain ) fileoutput=$dirmpdconf/output.conf if [[ ${args[1]} == true ]]; then echo 'replaygain "'${args[2]}'"' > $dirmpdconf/conf/replaygain.conf - if (( $( grep -Ec 'mixer_type.*hardware|replay_gain_handler' $fileoutput ) == 1 )); then - sed -i '/}/ i\ replay_gain_handler "mixer"' $fileoutput - fi linkConf else - sed -i '/replay_gain_handler/ d' $fileoutput rm $dirmpdconf/replaygain.conf fi - output="\ -audio_output { -$( grep -Ev '{$|}$' $fileoutput | column -t -s^ ) -}" - echo "$output" > $fileoutput - restartMPD + $dirsettings/player-conf.sh ;; soxr ) rm -f $dirmpdconf/soxr* @@ -268,7 +253,8 @@ EOF else rm -f $dirsystem/soxr fi - restartMPD + systemctl restart mpd + pushRefresh ;; volume0db ) card=$( < $dirsystem/asoundcard ) diff --git a/srv/http/bash/settings/relays.sh b/srv/http/bash/settings/relays.sh index b7123d4a4..7e6857c11 100644 --- a/srv/http/bash/settings/relays.sh +++ b/srv/http/bash/settings/relays.sh @@ -9,8 +9,7 @@ readarray -t args <<< $1 cmd=${args[0]} if [[ $cmd == save ]]; then - data=${args[1]} - echo -e "$data" > $dirsystem/relays.conf + printf "%s\n" "${args[@]:1}" > $dirsystem/relays.conf touch $dirsystem/relays $dirsettings/relays-data.sh pushrefresh pushstream display '{"submenu":"relays","value":true}' diff --git a/srv/http/bash/settings/system.sh b/srv/http/bash/settings/system.sh index 8185a74dd..6e254f79c 100644 --- a/srv/http/bash/settings/system.sh +++ b/srv/http/bash/settings/system.sh @@ -84,7 +84,9 @@ sharedDataSet() { rm -rf $dirbackup/$dir mv -f $dirdata/$dir $dirbackup ln -s $dirshareddata/$dir $dirdata + chown -h http:http $dirdata/$dir done + chown -h mpd:audio $dirdata/{mpd,playlists} if [[ ! -e $dirshareddata/system ]]; then # not server rAudio - initial setup mkdir $dirshareddata/system cp -f $dirsystem/{display,order} $dirshareddata/system @@ -104,7 +106,6 @@ USB" > /mnt/MPD/.mpdignore sharedDataIPlist pushRefresh pushstream refresh '{"page":"features","shareddata":true}' - $dirbash/cmd.sh webradiocopybackup &> /dev/null & } soundProfile() { if [[ $1 == reset ]]; then @@ -739,6 +740,7 @@ $( script -c "timeout 1 rtl_test -t" | grep -v ^Script )" ;; upmpdcli ) skip='not creating entry for' + fileconf=/etc/upmpdcli.conf ;; * ) fileconf=/etc/$id.conf diff --git a/srv/http/bash/status-coverart.sh b/srv/http/bash/status-coverart.sh index 4b728837a..665855436 100644 --- a/srv/http/bash/status-coverart.sh +++ b/srv/http/bash/status-coverart.sh @@ -14,7 +14,16 @@ path="/mnt/MPD/$file" # found cover file localname=$( tr -d ' "`?/#&'"'" <<< $path ) localfile=$dirshm/local/$localname -[[ -f $localfile ]] && cat $localfile && exit +if [[ -f $localfile ]]; then + localpath=$( cat $localfile ) + if [[ -e $localpath ]]; then + php -r "echo rawurlencode( '${localpath//\'/\\\'}' );" + exit + else + rm $localfile + fi +fi + # found embedded embeddedname=$( tr -d ' "`?/#&'"'" <<< $filename ).jpg embeddedfile=$dirshm/embedded/$embeddedname @@ -28,8 +37,8 @@ onlinefile=$( ls -1X $dirshm/online/${covername,,}.{jpg,png} 2> /dev/null | head coverfile=$( ls -1X "$path"/cover.{gif,jpg,png} 2> /dev/null | head -1 ) [[ ! $coverfile ]] && coverfile=$( ls -1X "$path"/*.{gif,jpg,png} 2> /dev/null | grep -E -i -m1 '/album\....$|cover\....$|/folder\....$|/front\....$' ) if [[ $coverfile ]]; then - coverfile=$( php -r "echo rawurlencode( '${coverfile//\'/\\\'}' );" ) # rawurlencode - local path only - echo $coverfile | tee $localfile + echo $coverfile > $localfile + php -r "echo rawurlencode( '${coverfile//\'/\\\'}' );" $dirbash/cmd.sh coverfileslimit exit fi diff --git a/srv/http/bash/status-dab.sh b/srv/http/bash/status-dab.sh index 488dc5d28..ddf9ebbdd 100644 --- a/srv/http/bash/status-dab.sh +++ b/srv/http/bash/status-dab.sh @@ -17,15 +17,11 @@ while true; do if ! cmp -s $filelabel $filetitle; then cp -f $filelabel $filetitle - elapsed=$( printf '%.0f' $( { echo status; sleep 0.05; } \ - | telnet 127.0.0.1 6600 2> /dev/null \ - | grep ^elapsed \ - | cut -d' ' -f2 ) ) data='{ "Album" : "DAB Radio" , "Artist" : "'$station'" , "coverart" : "" -, "elapsed" : '$elapsed' +, "elapsed" : '$( getElapsed )' , "file" : "'$file'" , "icon" : "dabradio" , "sampling" : "'$pos' • 48 kHz 160 kbit/s • DAB" diff --git a/srv/http/bash/status-radio.sh b/srv/http/bash/status-radio.sh index 7cb30096b..5ea6d27d9 100644 --- a/srv/http/bash/status-radio.sh +++ b/srv/http/bash/status-radio.sh @@ -88,15 +88,11 @@ metadataGet() { coverart=/data/shm/webradio/$name.jpg curl -s $coverurl -o $dirshm/webradio/$name.jpg fi - elapsed=$( printf '%.0f' $( { echo status; sleep 0.05; } \ - | telnet 127.0.0.1 6600 2> /dev/null \ - | grep ^elapsed \ - | cut -d' ' -f2 ) ) data='{ "Album" : "'$album'" , "Artist" : "'$artist'" , "coverart" : "'$coverart'" -, "elapsed" : '$elapsed' +, "elapsed" : '$( getElapsed )' , "file" : "'$file'" , "icon" : "'$icon'" , "sampling" : "'$sampling'" diff --git a/srv/http/bash/status.sh b/srv/http/bash/status.sh index 0c27e9b0c..4764227e0 100644 --- a/srv/http/bash/status.sh +++ b/srv/http/bash/status.sh @@ -10,12 +10,6 @@ [[ -L $dirmpd && ! -e $dirmpd/counts ]] && echo -1 && exit -elapsedGet() { - elapsed=$( printf '%.0f' $( { echo status; sleep 0.05; } \ - | telnet 127.0.0.1 6600 2> /dev/null \ - | grep ^elapsed \ - | cut -d' ' -f2 ) ) -} outputStatus() { [[ ! $snapclient ]] && data2json "$status" || echo "$status" # - no braces [[ $1 != noexit ]] && exit @@ -86,7 +80,6 @@ if [[ $1 == withdisplay ]]; then , "color" : "'$( getContent $dirsystem/color )'" , "dabradio" : '$dabradio' , "equalizer" : '$( exists $dirsystem/equalizer )' -, "logout" : '$( exists $dirsystem/login )' , "multiraudio" : '$( exists $dirsystem/multiraudio )' , "relays" : '$( exists $dirsystem/relays )' , "screenoff" : '$screenoff' @@ -156,12 +149,15 @@ fi (( $( grep -cE '"cover".*true|"vumeter".*false' $dirsystem/display ) == 2 )) && displaycover=1 -filter='^Album|^AlbumArtist|^Artist|^audio|^bitrate|^duration|^file|^Name|^song:|^state|^Time|^Title' -[[ ! $snapclient ]] && filter+='|^playlistlength|^random|^repeat|^single' +#filter='^Album|^AlbumArtist|^Artist|^audio|^bitrate|^duration|^file|^Name|^song:|^state|^Time|^Title' +#[[ ! $snapclient ]] && filter+='|^playlistlength|^random|^repeat|^single' +filter='Album AlbumArtist Artist audio bitrate duration file Name song state Time Title' +[[ ! $snapclient ]] && filter+=' playlistlength random repeat single' +filter=^${filter// /:|^}: mpdStatus() { mpdtelnet=$( { echo clearerror; echo status; echo $1; sleep 0.05; } \ | telnet 127.0.0.1 6600 2> /dev/null \ - | grep -E "$filter" ) + | grep -E $filter ) } mpdStatus currentsong # 'file:' missing / blank @@ -367,7 +363,7 @@ $radiosampling" > $dirshm/radio , "webradio" : true' if [[ $id ]]; then sampling="$(( song + 1 ))/$pllength • $radiosampling" - elapsedGet + elapsed=$( getElapsed ) ######## status+=' , "coverart" : "'$coverart'" @@ -508,7 +504,7 @@ status+=' , "sampling" : "'$sampling'"' if [[ $coverart || ! $displaycover ]]; then # webradio $coverart exists - elapsedGet + elapsed=$( getElapsed ) # >>>>>>>>>> webradio with found coverart status+=' , "elapsed" : '$elapsed @@ -523,7 +519,7 @@ $Album $filenoesc" ) [[ $coverart ]] && coverart="$coverart" fi -elapsedGet +elapsed=$( getElapsed ) ######## status+=' , "elapsed" : '$elapsed' diff --git a/srv/http/common.php b/srv/http/common.php index 44163fc02..6386a5e7a 100644 --- a/srv/http/common.php +++ b/srv/http/common.php @@ -77,15 +77,12 @@ $cssp[] = 'select2'; $css[] = 'select2'; } - if ( $relays ) { - $css[] = 'relays'; - $js[] = 'relays'; - } + if ( $relays ) $css[] = 'relays'; if ( $addons ) { - $css[] = 'addons'; + $css[] = 'addons'; } else { - $jsp[] = 'pushstream'; - $js[] = 'settings'; + $jsp[] = 'pushstream'; + $js[] = 'settings'; } $jsp[] = $networks ? 'qrcode' : 'select2'; $js[] = $page; diff --git a/srv/http/mpdlibrary.php b/srv/http/mpdlibrary.php index c78f9a8c1..13f5e9113 100644 --- a/srv/http/mpdlibrary.php +++ b/srv/http/mpdlibrary.php @@ -53,8 +53,8 @@ case 'find': $format = str_replace( '%artist%', '[%artist%|%albumartist%]', $format ); if ( is_array( $mode ) ) { - exec( 'mpc -f %file% find '.$mode[ 0 ].' "'.$string[ 0 ].'" '.$mode[ 1 ].' "'.$string[ 1 ].'" 2> /dev/null'." \ - | awk -F'/[^/]*$' 'NF && !/^\^/ && !a[$0]++ {print $1}' | sort -u" + exec( 'mpc -f %file% find '.$mode[ 0 ].' "'.$string[ 0 ].'" '.$mode[ 1 ].' "'.$string[ 1 ].'" 2> /dev/null'." ' + .'| awk -F'/[^/]*$' 'NF && !/^\^/ && !a[$0]++ {print $1}' | sort -u" , $dirs ); if ( count( $dirs ) > 1 ) { htmlDirectory( $dirs ); @@ -63,12 +63,10 @@ } else { $file = $dirs[ 0 ]; if ( substr( $file, -14, 4 ) !== '.cue' ) { - exec( 'mpc find -f "'.$format.'" '.$mode[ 0 ].' "'.$string[ 0 ].'" '.$mode[ 1 ].' "'.$string[ 1 ].'" 2> /dev/null'." \ - | awk 'NF && !a[$0]++'" + exec( 'mpc find -f "'.$format.'" '.$mode[ 0 ].' "'.$string[ 0 ].'" '.$mode[ 1 ].' "'.$string[ 1 ].'" 2> /dev/null'." | awk 'NF && !a[$0]++'" , $lists ); if ( ! count( $lists ) ) { // find with albumartist - exec( 'mpc find -f "'.$format.'" '.$mode[ 0 ].' "'.$string[ 0 ].'" albumartist "'.$string[ 1 ].'" 2> /dev/null'." \ - | awk 'NF && !a[$0]++'" + exec( 'mpc find -f "'.$format.'" '.$mode[ 0 ].' "'.$string[ 0 ].'" albumartist "'.$string[ 1 ].'" 2> /dev/null'." | awk 'NF && !a[$0]++'" , $lists ); } } else { // $file = '/path/to/file.cue/track0001' @@ -78,8 +76,7 @@ } } } else { - exec( 'mpc find -f "'.$format.'" '.$mode.' "'.$string.'" 2> /dev/null'." \ - | awk 'NF && !a[$0]++'" + exec( 'mpc find -f "'.$format.'" '.$mode.' "'.$string.'" 2> /dev/null'." | awk 'NF && !a[$0]++'" , $lists ); } if ( count( $f ) > 2 ) { @@ -110,15 +107,19 @@ if ( count( $files ) ) { foreach( $files as $name ) { $bkpath = trim( file_get_contents( $dir.'/'.$name ) ); - if ( substr( $bkpath, 0, 4 ) === 'http' ) { - $src = '/data/webradio/img/'.str_replace( '/', '|', $bkpath ).'.jpg'; + $prefix = substr( $bkpath, 0, 4 ); + if ( in_array( $prefix, [ 'http', 'rtsp' ] ) ) { + $bkradio = 'bkradio'; + $dirradio = $prefix === 'http' ? 'webradio' : 'dabradio'; + $src = '/data/'.$dirradio.'/img/'.str_replace( '/', '|', $bkpath ).'.jpg'; } else { - $src = substr( $bkpath, 0, 8 ) === 'webradio' ? '/data/' : '/mnt/MPD/'; - $src .= $bkpath.'/coverart.jpg'; + $bkradio = ''; + $src = substr( $bkpath, 0, 8 ) === 'webradio' ? '/data/' : '/mnt/MPD/'; + $src .= $bkpath.'/coverart.jpg'; } $htmlmode.= <<< EOF
    -
    +
    $bkpath $name @@ -215,8 +216,7 @@ htmlRadio( $subdirs, $files, $dir ); break; case 'search': - exec( 'mpc search -f "'.$format.'" any "'.$string.'" \ - | awk NF' + exec( 'mpc search -f "'.$format.'" any "'.$string.'" | awk NF' , $lists ); htmlTrack( $lists, $f, 'search', $string ); break; @@ -566,8 +566,8 @@ function htmlTrack( $lists, $f, $filemode = '', $string = '', $dirs = '' ) { // $seconds = 0; foreach( $hhmmss as $hms ) $seconds += HMS2second( $hms ); // hh:mm:ss > seconds $totaltime = second2HMS( $seconds ); - $args = escape( implode( "\n", [ $artist, $album, $mpdpath ] ) ); - $coverart = exec( '/usr/bin/sudo /srv/http/bash/status-coverart.sh "'.$args.'"' ); + $args = escape( implode( "\n", [ $artist, $album, $each0->file ] ) ); + $coverart = exec( '/srv/http/bash/status-coverart.sh "'.$args.'"' ); $br = ! $hidegenre || !$hidedate ? '
    ' : ''; $mpdpath = str_replace( '\"', '"', $mpdpath ); $count = count( $array ); diff --git a/srv/http/mpdplaylist.php b/srv/http/mpdplaylist.php index 9e1ebcf41..4d0913312 100644 --- a/srv/http/mpdplaylist.php +++ b/srv/http/mpdplaylist.php @@ -262,22 +262,10 @@ function htmlTrack( $lists, $plname = '' ) { } if ( $countradio ) $counthtml.= ''.$countradio.''; if ( $countupnp ) $counthtml.= ' '; - exec( "{ echo status; sleep 0.05; } \ - | telnet 127.0.0.1 6600 2> /dev/null \ - | grep -E '^song:|^elapsed:'" - , $song_elapsed ); - $elapsed = ''; - foreach( $song_elapsed as $se ) { - if ( substr( $se, 0, 4 ) === 'song' ) { - $song = str_replace( 'song: ', '', $se ); - } else { - $elapsed = round( str_replace( 'elapsed: ', '', $se ) ); - } - } + $elapsed = exec( '/srv/http/bash/cmd.sh getelapsed' ); echo json_encode( [ 'html' => $html , 'counthtml' => $counthtml - , 'song' => $song , 'elapsed' => $elapsed , 'add' => $add ], JSON_NUMERIC_CHECK ); diff --git a/srv/http/settings/features.php b/srv/http/settings/features.php index 4f885558f..d8b8cabed 100644 --- a/srv/http/settings/features.php +++ b/srv/http/settings/features.php @@ -20,9 +20,9 @@ $body = [ [ 'label' => 'AirPlay' - , 'id' => 'shairport-sync' , 'sublabel' => 'shairport-sync' , 'icon' => 'airplay' + , 'id' => 'shairport-sync' , 'setting' => false , 'status' => 'shairport-sync' , 'disabled' => 'AirPlay I^airplay^I is currently active.' @@ -31,9 +31,9 @@ ] , [ 'label' => 'DAB Radio' - , 'id' => 'dabradio' , 'sublabel' => 'rtsp-server' , 'icon' => 'dabradio' + , 'id' => 'dabradio' , 'setting' => false , 'status' => 'rtsp-simple-server' , 'disabled' => 'No DAB devices found.' @@ -43,52 +43,52 @@ , [ 'label' => 'SnapClient' , 'sublabel' => 'snapclient' - , 'id' => 'snapclient' , 'icon' => 'snapcast' + , 'id' => 'snapclient' , 'status' => 'snapclient' , 'disabled' => 'SnapClient I^snapcast^I is currently active.' , 'help' => <<< EOF Snapcast - Multiroom client-server audio player. - • SSH passwords must be default. - • Connect: A^I^networks^I Networks^AI^snapcast sub^I - • SnapClient and SnapServer can be enabled on the same device. - - Enable | SnapServer | before | SnapClient | - - SnapClient auto connect/disconnect on play/stop + · SSH passwords must be default. + · Connect: A^I^networks^I Networks^AI^snapcast sub^I + · SnapClient and SnapServer can be enabled on the same device. + · Enable | SnapServer | before | SnapClient | + · SnapClient auto connect/disconnect on play/stop EOF , 'exist' => file_exists( '/usr/bin/snapclient' ) ] , [ 'label' => 'Spotify' - , 'id' => 'spotifyd' , 'sublabel' => 'spotifyd' , 'icon' => 'spotify' + , 'id' => 'spotifyd' , 'status' => 'spotifyd' , 'disabled' => 'Spotify I^spotify^I is currently active.' , 'help' => <<< EOF Spotifyd - Spotify Connect device. - • Require Premium account. (No Spotify password saved on rAudio.) - • Get credential from Spotify private app: ( Screenshots ) + · Require Premium account. (No Spotify password saved on rAudio.) + · Get credential from Spotify private app: ( Screenshots ) Spotify for Developers (Replace YELLOW with actual values) | LOG IN | - - with normal Spotify account + · with normal Spotify account | CREATE AN APP | - - App name: Name - - App description: Description + · App name: Name + · App description: Description | EDIT SETTINGS | - - Redirect URIs: + · Redirect URIs: | USERS AND ACCESS | ADD NEW USER | - - Name: user - - Spotify Account: email -• | Spotify I^spotify^I ◨ | - - Paste Client ID and Client Secret from the created app + · Name: user + · Spotify Account: email +· | Spotify I^spotify^I ◨ | + · Paste Client ID and Client Secret from the created app EOF , 'exist' => file_exists( '/usr/bin/spotifyd' ) ] , [ 'label' => 'UPnP' - , 'id' => 'upmpdcli' , 'sublabel' => 'upmpdcli' , 'icon' => 'upnp' + , 'id' => 'upmpdcli' , 'status' => 'upmpdcli' , 'disabled' => 'UPnP I^upnp^I is currently active.' , 'help' => 'upmpdcli - UPnP / DLNA rendering device.' @@ -102,9 +102,9 @@ $body = [ [ 'label' => 'For browsers' - , 'id' => 'httpd' , 'sublabel' => 'MPD httpd' , 'icon' => 'webradio' + , 'id' => 'httpd' , 'setting' => false , 'help' => <<< EOF HTTP streaming - Asynchronous streaming for browsers via http://$ip:8000 (Latency - several seconds) @@ -112,17 +112,17 @@ ] , [ 'label' => 'SnapServer' - , 'id' => 'snapserver' , 'sublabel' => 'MPD snapcast' , 'icon' => 'snapcast' + , 'id' => 'snapserver' , 'setting' => false , 'disabled' => 'SnapClient I^snapcast^I is currently connected.' , 'help' => <<< EOF Snapcast - Multiroom client-server audio player. - • SSH passwords must be default. (For metadata update) - • Snapcast control client and player: - - Snapweb - - Snapdroid + · SSH passwords must be default. (For metadata update) + · Snapcast control client and player: + · Snapweb + · Snapdroid EOF , 'exist' => file_exists( '/usr/bin/snapclient' ) ] @@ -132,9 +132,9 @@ $body = [ [ 'label' => 'DSP' - , 'id' => 'camilladsp' , 'sublabel' => 'camilladsp' , 'icon' => 'camilladsp' + , 'id' => 'camilladsp' , 'status' => 'camilladsp' , 'disabled' => $disableddsp , 'help' => <<< EOF @@ -146,19 +146,19 @@ , [ 'label' => 'Equalizer' , 'sublabel' => 'alsaequal' - , 'id' => 'equalizer' , 'icon' => 'equalizer' + , 'id' => 'equalizer' , 'setting' => false , 'disabled' => 'DSP I^camilladsp^I is currently enabled.' , 'help' => <<< EOF Alsaequal - 10 band graphic equalizer with user presets. Control: A^I^features^I Features^AI^equalizer sub^I Presets: - • Flat: All bands at 0dB - • New: Adjust | I^plus-circle^I Add | I^save^I Save | - • Existing: Adjust | I^save^I Save | - • Adjusted values will be listed as (unnamed) until saved. - • If distortions occurred, lower all bands collectively and increase volume + · Flat: All bands at 0dB + · New: Adjust | I^plus-circle^I Add | I^save^I Save | + · Existing: Adjust | I^save^I Save | + · Adjusted values will be listed as (unnamed) until saved. + · If distortions occurred, lower all bands collectively and increase volume EOF ] ]; @@ -167,78 +167,79 @@ $body = [ [ 'label' => 'Access Point' - , 'id' => 'hostapd' , 'sublabel' => 'hostapd' , 'icon' => 'accesspoint' + , 'id' => 'hostapd' , 'status' => 'hostapd' , 'disabled' => 'Wi-Fi is currently connected.' , 'help' => <<< EOF hostapd - Connect with rAudio hotspot directly when no routers available. - • This should be used only when necessary. - • Avoid double quotes " in password. + · This should be used only when necessary. + · Avoid double quotes " in password. EOF , 'exist' => file_exists( '/usr/bin/hostapd' ) ] , [ 'label' => 'AutoPlay' - , 'id' => 'autoplay' , 'icon' => 'play' + , 'id' => 'autoplay' , 'help' => <<< EOF Start playing automatically on: - • Bluetooth connected - • Audio CD inserting - • Power on / Reboot + · Bluetooth connected + · Audio CD inserting + · Power on / Reboot EOF ] , [ 'label' => 'Browser on RPi' - , 'id' => 'localbrowser' , 'sublabel' => 'chromium' , 'icon' => 'chromium' + , 'id' => 'localbrowser' , 'status' => 'localbrowser' , 'help' => <<< EOF Chromium - Browser on RPi connected screen. - • TFT 3.5" LCD: Rotate needs reboot. - • Screen off: A^I^power^I Power^AI^screenoff sub^I - - Also by timer in | I^gear^I | - - Backlight still on - no energy saved - • HDMI display: Must be connected before boot. + · TFT 3.5" LCD: Rotate needs reboot. + · Screen off: A^I^power^I Power^AI^screenoff sub^I + · Also by timer in | I^gear^I | + · Backlight still on - no energy saved + · HDMI display must be connected before boot. EOF , 'exist' => file_exists( '/usr/bin/chromium' ) ] , [ 'label' => 'File Sharing' - , 'id' => 'smb' , 'sublabel' => 'smb' , 'icon' => 'networks' + , 'id' => 'smb' , 'status' => 'smb' , 'disabled' => 'Server rAudio I^rserver^I is currently active.' , 'help' => <<< EOF Samba - Share files on network for Windows clients. - • Much faster than SCP / WinSCP when transfer large or a lot of files - • Set sources permissions for read + write - directory: 0777 file: 0555 - • Windows: $fileexplorer + · Much faster than SCP / WinSCP when transfer large or a lot of files + · Set sources permissions for read + write - directory: 0777 file: 0555 + · Windows: $fileexplorer (For even better performance: | Server rAudio I^rserver^I | ) EOF , 'exist' => file_exists( '/usr/bin/smbd' ) ] , [ - 'label' => 'Lyrics in File' - , 'id' => 'lyricsembedded' - , 'icon' => 'lyrics' + 'label' => 'Lyrics in File' + , 'sublabel' => 'embedded ID3' + , 'icon' => 'lyrics' + , 'id' => 'lyricsembedded' , 'setting' => false - , 'help' => <<< EOF - • Get embedded lyrics from local files. - • Search online if not available. - • Should be disable if most lyrics are not embedded. - • Online fetched lyrics are saved as separate files, not embedded. + , 'help' => <<< EOF + · Get embedded lyrics from local files. + · Search online if not available. + · Should be disable if most lyrics are not embedded. + · Online fetched lyrics are saved as separate files, not embedded. EOF ] , [ 'label' => 'Multiple rAudios' - , 'id' => 'multiraudio' , 'icon' => 'raudiobox' + , 'id' => 'multiraudio' , 'help' => <<< EOF Switch between multiple rAudio devices. Switch: A^I^playlist^I Playlist^AI^raudiobox sub^I @@ -248,9 +249,9 @@ ] , [ 'label' => 'Password Login' - , 'id' => 'login' , 'sublabel' => 'password_hash' , 'icon' => 'lock' + , 'id' => 'login' , 'setting' => 'custom' , 'help' => <<< EOF password_hash - Force browser interface login with password using PASSWORD_BCRYPT. @@ -259,23 +260,23 @@ ] , [ 'label' => 'Scrobbler' - , 'id' => 'scrobble' , 'sublabel' => 'Last.fm' , 'icon' => 'lastfm' + , 'id' => 'scrobble' , 'help' => <<< EOF - • Send artist, title and album of played tracks to Last.fm to save in user's database. - • Require Last.fm account. - • No Last.fm password saved on rAudio. - • Option to include renderers - Exclude if already scrobbleed by sender devices. - • SnapClient already scrobbled by SnapServer. - • Web Radio must be manually scrobbled: | Playing title | I^lastfm wh^I Scrobble | + · Send artist, title and album of played tracks to Last.fm to save in user's database. + · Require Last.fm account. + · No Last.fm password saved on rAudio. + · Option to include renderers - Exclude if already scrobbleed by sender devices. + · SnapClient already scrobbled by SnapServer. + · Web Radio must be manually scrobbled: | Playing title | I^lastfm wh^I Scrobble | EOF ] , [ 'label' => 'Server rAudio' - , 'id' => 'nfsserver' , 'sublabel' => 'nfs-server' , 'icon' => 'rserver' + , 'id' => 'nfsserver' , 'setting' => 'custom' , 'settingicon' => false , 'status' => 'nfs-server' @@ -283,36 +284,36 @@ , 'help' => <<< EOF NFS - Network File System - Server for files and | Shared Data I^networks^I | • rAudio Shared Data server: - - Must be set to static IP address which should be set on router. - - In | I^library^I | Library: - - | I^microsd^I SD | and | I^usbdrive^I USB | will be hidden. - - | I^usb^I USB | items will be displayed in | I^networks^I NAS | instead. - - On reboot / power off: - - Shared Data on clients will be temporarily disabled - - Re-enabled by itself once the server is back online. + · Must be set to static IP address which should be set on router. + · In | I^library^I | Library: + · | I^microsd^I SD | and | I^usbdrive^I USB | will be hidden. + · | I^usb^I USB | items will be displayed in | I^networks^I NAS | instead. + · On reboot / power off: + · Shared Data on clients will be temporarily disabled + · Re-enabled by itself once the server is back online. • rAudio Shared Data clients: - - | I^system^I System | Shared Data I^networks^I ◨ | • rAudio | - - Automatically setup: discover, connect shared files and data + · | I^system^I System | Shared Data I^networks^I ◨ | • rAudio | + · Automatically setup: discover, connect shared files and data • Windows NFS clients: - - Windows Features > Services for NFS > Client for NFS - Enable - - $fileexplorer + · Windows Features > Services for NFS > Client for NFS - Enable + · $fileexplorer (SSH password must be default.) EOF ] , [ 'label' => 'Stop Timer' - , 'id' => 'stoptimer' , 'icon' => 'stopwatch' + , 'id' => 'stoptimer' , 'disabled' => 'Player is currently not playing.' , 'help' => <<< EOF Stop timer: - • Mute - • Stop player - • Set volume back as before mute - • If set, power off. + · Mute + · Stop player + · Set volume back as before mute + · If set, power off. EOF ] ]; diff --git a/srv/http/settings/networks.php b/srv/http/settings/networks.php index 53e9fd837..e8e37d46f 100644 --- a/srv/http/settings/networks.php +++ b/srv/http/settings/networks.php @@ -14,19 +14,19 @@ rAudio as sender: (or pairing non-audio devices) • Pair: - - On receiver: Turn on Discovery / Pairing mode - - On rAudio: | Bluetooth I^search wh^I | Select to pair + · On receiver: Turn on Discovery / Pairing mode + · On rAudio: | Bluetooth I^search wh^I | Select to pair • Connect: - - On receiver: Power on / Power off > Connect / Disconnect - - Receiver buttons can be used to control playback + · On receiver: Power on / Power off > Connect / Disconnect + · Receiver buttons can be used to control playback rAudio as receiver: • Pair: - - On rAudio: | I^system^I System | Bluetooth I^bluetooth^I | • Discoverable by senders | - - On sender: Search > Select rAudio to pair - - Forget / remove should be done on both rAudio and sender + · On rAudio: | I^system^I System | Bluetooth I^bluetooth^I | • Discoverable by senders | + · On sender: Search > Select rAudio to pair + · Forget / remove should be done on both rAudio and sender • Connect: - - On sender: Select rAudio > Connect / Disconnect + · On sender: Select rAudio > Connect / Disconnect
    EOF; echoSetIcon( $html ); @@ -45,9 +45,9 @@ | I^plus-circle^I | Manually connect | I^search^I | Scan to connect - • Avoid double quotes " in Wi-Fi name and password. - -(Access points with 1 bar icon I^wifi1^I might be unstable.)' ) )?>
    +Note: + · Avoid double quotes " in Wi-Fi name and password. + · Access points with 1 bar icon I^wifi1^I might be unstable.' ) )?>
    'volume' , 'help' => <<< EOF I^volume^I Volume setting and control: - • Player: Should be set at 0dB - • Playback: Should be set at 100% - • Use device volume to control level + · Player: Should be set at 0dB + · Playback: Should be set at 100% + · Use device volume to control level EOF ] , [ @@ -89,11 +89,11 @@ , 'settingicon' => false , 'help' => <<< EOF Disable all manipulations for bit-perfect stream from MPD to DAC output. - • No changes in data stream until it reaches amplifier volume control. - • Mixer device volume: | 0dB | - • Volume Control: | None / 0db | - • Disable options: Cross-fading, Normalization, ReplayGain and SoX Resampler - • Disable Signal Processors + · No changes in data stream until it reaches amplifier volume control. + · Mixer device volume: | 0dB | + · Volume Control: | None / 0db | + · Disable options: Cross-fading, Normalization, ReplayGain and SoX Resampler + · Disable Signal Processors Note: Not for DACs with on-board amplifier. EOF @@ -105,34 +105,37 @@ , 'settingicon' => false , 'help' => <<< EOF For DSD-capable devices without drivers dedicated for native DSD. - • Enable if there's static/no sound from the DAC which means not support as native DSD. - • DoP will repack 16bit DSD stream into 24bit PCM frames and transmit to the DAC. - • PCM frames will be reassembled back to original DSD stream, COMPLETELY UNCHANGED, with expense of double bandwith. - • On-board audio and non-DSD devices will always get DSD converted to PCM stream, no bit-perfect + · Enable if there's static/no sound from the DAC which means not support as native DSD. + · DoP will repack 16bit DSD stream into 24bit PCM frames and transmit to the DAC. + · PCM frames will be reassembled back to original DSD stream, COMPLETELY UNCHANGED, with expense of double bandwith. + · On-board audio and non-DSD devices will always get DSD converted to PCM stream, no bit-perfect EOF ] ]; htmlSection( $head, $body, 'bitperfect' ); $head = [ 'title' => 'Volume' ]; ////////////////////////////////// $body = [ - [ 'label' => 'Cross-Fading' - , 'id' => 'crossfade' - , 'help' => <<< EOF + [ 'label' => 'Cross-Fading' + , 'sublabel' => 'crossfade' + , 'id' => 'crossfade' + , 'help' => <<< EOF Fade-out to fade-in between playing tracks (same audio format only) EOF ] , [ - 'label' => 'Normalization' - , 'id' => 'normalization' - , 'setting' => false - , 'help' => <<< EOF + 'label' => 'Normalization' + , 'sublabel' => 'volume_normalization' + , 'id' => 'normalization' + , 'setting' => false + , 'help' => <<< EOF Normalize the volume level of songs as they play. (16 bit PCM only) EOF ] , [ - 'label' => 'ReplayGain' - , 'id' => 'replaygain' - , 'help' => <<< EOF + 'label' => 'ReplayGain' + , 'sublabel' => 'replaygain' + , 'id' => 'replaygain' + , 'help' => <<< EOF ReplayGain - Normalize perceived loudness via ID3v2 ReplayGain tag Support: FLAC, Ogg Vorbis, Musepack and MP3 EOF @@ -145,8 +148,8 @@ $body = [ [ 'label' => 'Buffer - Audio' + , 'sublabel' => 'audio_buffer' , 'id' => 'buffer' - , 'sublabel' => 'custom size' , 'help' => <<< EOF Increase to fix intermittent audio. @@ -155,8 +158,8 @@ ] , [ 'label' => 'Buffer - Output' + , 'sublabel' => 'max_output_buffer' , 'id' => 'outputbuffer' - , 'sublabel' => 'custom size' , 'help' => <<< EOF Increase to fix missing Album list with large Library. @@ -165,8 +168,8 @@ ] , [ 'label' => 'FFmpeg' + , 'sublabel' => 'decoder' , 'id' => 'ffmpeg' - , 'sublabel' => 'decoder plugin' , 'setting' => false , 'disabled' => 'DAB Radio I^dabradio^I is currently enabled.' , 'help' => <<< EOF @@ -176,15 +179,17 @@ EOF ] , [ - 'label' => 'Library Auto Update' - , 'id' => 'autoupdate' - , 'setting' => false - , 'help' => 'Automatic update MPD database when files changed.' + 'label' => 'Library Auto Update' + , 'sublabel' => 'auto_update' + , 'id' => 'autoupdate' + , 'setting' => false + , 'help' => 'Automatic update MPD database when files changed.' ] , [ - 'label' => 'SoX Resampler' - , 'id' => 'soxr' - , 'help' => <<< EOF + 'label' => 'SoX Resampler' + , 'sublabel' => 'resampler' + , 'id' => 'soxr' + , 'help' => <<< EOF SoX Resampler library - One-dimensional sample-rate conversion | I^gear^I | @@ -192,12 +197,12 @@ (default: Quality - | Very high |, Threads - | Single |) • Custom quality: - - Precision - Conversion precision (20 = HQ) - - Phase Response (50 = Linear) - - Passband End - 0dB point bandwidth to preserve (100 = Nyquist) - - Stopband Begin - Aliasing/imaging control - - Attenuation - Lowers the source to prevent clipping - - Flags / Extra settings: + · Precision - Conversion precision (20 = HQ) + · Phase Response (50 = Linear) + · Passband End - 0dB point bandwidth to preserve (100 = Nyquist) + · Stopband Begin - Aliasing/imaging control + · Attenuation - Lowers the source to prevent clipping + · Flags / Extra settings:
     |  0 - Rolloff - small  | (<= 0.01 dB)
     |  1 - Rolloff - medium | (<= 0.35 dB)
    @@ -209,9 +214,10 @@
     EOF
     	]
     	, [
    -		  'label'   => "User's Configurations"
    -		, 'id'      => 'custom'
    -		, 'help'    => 'Insert custom configurations into mpd.conf.'
    +		  'label'    => "User's Configurations"
    +		, 'sublabel' => 'custom'
    +		, 'id'       => 'custom'
    +		, 'help'     => 'Insert custom configurations into mpd.conf.'
     	]
     ];
     htmlSection( $head, $body, 'options' );
    @@ -227,9 +233,9 @@
     	, 'help'    => <<< EOF
     List of albums excluded from Album page.
     To restore:
    - • Edit /srv/http/data/mpd/albumignore
    - • Remove albums to restore
    - • Update Library
    + · Edit /srv/http/data/mpd/albumignore
    + · Remove albums to restore
    + · Update Library
     EOF
     ] );
     htmlHead( [
    diff --git a/srv/http/settings/relays.php b/srv/http/settings/relays.php
    index ddd5cc00a..18fc111f8 100644
    --- a/srv/http/settings/relays.php
    +++ b/srv/http/settings/relays.php
    @@ -46,7 +46,7 @@
     		 Off Sequence
     		

    - UndoSave + UndoSave
    diff --git a/srv/http/settings/system.php b/srv/http/settings/system.php index 6444bd5c3..5273c0ccb 100644 --- a/srv/http/settings/system.php +++ b/srv/http/settings/system.php @@ -71,15 +71,15 @@

    -CPU Load: - • Average number of processes which are being executed and in waiting. - • calculated over 1, 5 and 15 minutes. - • Each one should not be constantly over 0.75 x CPU cores. +• CPU Load: + · Average number of processes which are being executed and in waiting. + · calculated over 1, 5 and 15 minutes. + · Each one should not be constantly over 0.75 x CPU cores. -CPU temperature: - • 80-84°C: ARM cores throttled. - • 85°C: ARM cores and GPU throttled. - • RPi 3B+: 60°C soft limit (optimized throttling) +• CPU temperature: + · 80-84°C: ARM cores throttled. + · 85°C: ARM cores and GPU throttled. + · RPi 3B+: 60°C soft limit (optimized throttling)
    @@ -95,21 +95,19 @@ '| I^usbdrive^I | I^networks^I | Context menu | I^plus-circle^I | Add network storage -USB drives: - • Will be found and mounted automatically. +USB drives: Will be found and mounted automatically. -Network shares: - • If | Storage I^plus-circle^I | failed, try SSH terminal: (replace YELLOW with actual values) - CIFS: +Network shares: If | Storage I^plus-circle^I | failed, try SSH terminal: (replace YELLOW with actual values) +• CIFS: ' ) )?> -
    +
     mkdir -p "/mnt/MPD/NAS/NAME"
     mount -t cifs "//SERVER_IP/SHARENAME" "/mnt/MPD/NAS/NAME" \
           -o noauto,username=USER,password=PASSWORD,uid=,gid=,iocharset=utf8
     #	 (no user - username=guest, no password - password="")
     
    NFS: -
    +-->• NFS:
    +
     mkdir -p "/mnt/MPD/NAS/NAME"
     mount -t nfs "SERVER_IP:/SHARE/PATH" "/mnt/MPD/NAS/NAME" \
           -o defaults,noauto,bg,soft,timeo=5
    @@ -118,16 +116,16 @@
      'Hard Drive Sleep'
    -	, 'id'       => 'hddsleep'
     	, 'icon'     => 'screenoff'
    +	, 'id'       => 'hddsleep'
     	, 'disabled' => 'HDD not support sleep'
     	, 'help'     => 'Sleep timer for USB hard drives.'
     ] );
     htmlSetting( [
     	  'label'    => 'Hotplug Update'
    -	, 'id'       => 'usbautoupdate'
     	, 'sublabel' => 'data on USB'
     	, 'icon'     => 'refresh-library'
    +	, 'id'       => 'usbautoupdate'
     	, 'setting'  => false
     	, 'disabled' => $disabledusbautoupdate
     	, 'help'     => 'Auto update Library database on insert/remove USB drives.'
    @@ -142,26 +140,26 @@
     $body = [
     	[
     		  'label'    => 'Bluetooth'
    -		, 'id'       => 'bluetooth'
     		, 'sublabel' => 'bluetoothctl'
     		, 'icon'     => 'bluetooth'
    +		, 'id'       => 'bluetooth'
     		, 'status'   => 'btcontroller'
     		, 'disabled' => $disabledbt
    -		, 'help'     => '| I^gear^I | • Sampling 16bit | Only for Bluetooth receivers with fixed sampling'
    +		, 'help'     => '| I^gear^I | ⯀ Sampling 16bit | Only for Bluetooth receivers with fixed sampling'
     	]
     	, [
     		  'label'    => 'Wi-Fi'
    -		, 'id'       => 'wlan'
     		, 'sublabel' => 'iw'
     		, 'icon'     => 'wifi'
    +		, 'id'       => 'wlan'
     		, 'status'   => 'iw'
     		, 'disabled' => 'Wi-Fi is currently connected.'
     		, 'help'     => <<< EOF
     | I^gear^I |
     Country of Wi-Fi regulatory domain:
    -	- | 00 | Least common denominator settings, channels and transmit power are permitted in all countries.
    -	- The connected router may override it to a certain country.
    -| • Auto start Access Point | On failed connection or no router
    +	· | 00 | Least common denominator settings, channels and transmit power are permitted in all countries.
    +	· The connected router may override it to a certain country.
    +| ⯀ Auto start Access Point | On failed connection or no router
     EOF
     	]
     ];
    @@ -195,70 +193,71 @@
     	]
     	, [
     		  'label'    => 'Character LCD'
    -		, 'id'       => 'lcdchar'
     		, 'sublabel' => 'HD44780'
     		, 'icon'     => 'lcdchar'
    +		, 'id'       => 'lcdchar'
     		, 'help'     => <<< EOF
     LCD module - display playback data
    - • Support 16x2 and 20x4 LCD modules.
    + · Support 16x2 and 20x4 LCD modules.
     I^warning yl^I LCD with I²C backpack must be modified: 5V to 3.3V I²C and 5V LCD
     EOF
     	]
     	, [
     		  'label'    => 'Power Button'
    -		, 'id'       => 'powerbutton'
     		, 'sublabel' => 'Power LED'
     		, 'icon'     => 'power'
    +		, 'id'       => 'powerbutton'
     		, 'help'     => <<< EOF
     Power button and LED - power on/off rAudio
    - • On - Fixed to pin 5
    - • Off - Default to pin 5 (single pin on+off)
    + · On - Fixed to pin 5
    + · Off - Default to pin 5 (single pin on+off)
    + 
     If pin 5 is used by DAC or LCD - Set 2 unused pins for:
    - • Off (default: 7)
    - • Reserved (default: 29)
    + · Off (default: 7)
    + · Reserved (default: 29)
     EOF
     	]
     	, [
     		  'label'   => 'Relay Module'
    -		, 'id'      => 'relays'
     		, 'icon'    => 'relays'
    +		, 'id'      => 'relays'
     		, 'help'    => <<< EOF
     Relay module - power on/off peripheral equipments
     On/Off: A^I^raudio^I System^AI^relays sub^I
    - • More info: +R GPIO
    - • Can be enabled and run as a test without a connected relay module.
    + · More info: +R GPIO
    + · Can be enabled and run as a test without a connected relay module.
     EOF
     	],
     	[
     		  'label'    => 'Rotary Encoder'
    -		, 'id'       => 'rotaryencoder'
     		, 'icon'     => 'volume'
    +		, 'id'       => 'rotaryencoder'
     		, 'help'     => <<< EOF
     Rotary encoder for:
    - • Turn volume up/down
    - • Push to play/pause
    + · Turn volume up/down
    + · Push to play/pause
     EOF
     	]
     	,[
     		  'label'    => 'Spectrum OLED'
    -		, 'id'       => 'mpdoled'
     		, 'icon'     => 'mpdoled'
    +		, 'id'       => 'mpdoled'
     		, 'help'     => 'OLED module - display audio level spectrum'
     	]
     	, [
     		  'label'    => 'TFT 3.5" LCD'
    -		, 'id'       => 'lcd'
     		, 'icon'     => 'lcd'
    +		, 'id'       => 'lcd'
     		, 'help'     => 'TFT LCD module with resistive touchscreen - local display'
     		, 'exist'    => file_exists( '/etc/systemd/system/localbrowser.service' )
     	]
     	, [
     		  'label'   => 'VU LED'
    -		, 'id'      => 'vuled'
     		, 'icon'    => 'led'
    +		, 'id'      => 'vuled'
     		, 'help'    => <<< EOF
     7 LEDs - display audio level
    - • LED resister calculator
    + · LED resister calculator
     EOF
     	]
     ];
    @@ -267,22 +266,22 @@
     $body = [
     	[
     		  'label'   => 'Host Name'
    -		, 'id'      => 'hostname'
     		, 'icon'    => 'raudio'
    +		, 'id'      => 'hostname'
     		, 'input'   => ''
     		, 'setting' => false
     		, 'help'    => <<< EOF
     For:
    - • Access point, AirPlay, Bluetooth, SnapCast, Spotify, UPnP
    - • Web Interface URL: 
    - • System hostname
    + · Access point, AirPlay, Bluetooth, SnapCast, Spotify, UPnP
    + · Web Interface URL: 
    + · System hostname
     EOF
     	]
     	, [
     		  'label'    => 'Time Zone'
    -		, 'id'       => 'timezone'
     		, 'sublabel' => 'timedatectl'
     		, 'icon'     => 'globe'
    +		, 'id'       => 'timezone'
     		, 'status'   => 'timedatectl'
     		, 'input'    => $selecttimezone
     		, 'setting'  => 'custom'
    @@ -290,9 +289,9 @@
     	]
     	, [
     		  'label'    => 'Sound Profile'
    -		, 'id'       => 'soundprofile'
     		, 'sublabel' => 'sysctl'
     		, 'icon'     => 'soundprofile'
    +		, 'id'       => 'soundprofile'
     		, 'status'   => 'soundprofile'
     		, 'help'     => 'Tweak kernel parameters for sound profiles.'
     	]
    @@ -302,37 +301,37 @@
     $body = [
     	[
     		  'label'   => 'Backup'
    -		, 'id'      => 'backup'
     		, 'icon'    => 'sd'
    +		, 'id'      => 'backup'
     		, 'setting' => 'nobanner'
     		, 'help'    => <<< EOF
     Backup all data and settings:
    - • Library: Database, Bookmarks, DAB Radio, Web Radio
    - • Playback: Lyrics
    - • Playlist: Audio CD, Saved playlists
    - • Settings
    + · Library: Database, Bookmarks, DAB Radio, Web Radio
    + · Playback: Lyrics
    + · Playlist: Audio CD, Saved playlists
    + · Settings
     EOF
     	]
     	, [
     		  'label'   => 'Restore'
    -		, 'id'      => 'restore'
     		, 'icon'    => 'restore'
    +		, 'id'      => 'restore'
     		, 'setting' => 'nobanner'
     		, 'help'    => 'Restore all data and settings from a backup file.'
     	]
     	, [
     		  'label'    => 'Shared Data'
    -		, 'id'       => 'shareddata'
     		, 'sublabel' => 'client'
     		, 'icon'     => 'networks'
    +		, 'id'       => 'shareddata'
     		, 'setting'  => 'custom'
     		, 'disabled' => 'Server rAudio I^rserver^I is currently active.'
     		, 'help'     => <<< EOF
     Connect shared data as client for:
    -	- Library database
    -	- Data - Audio CD, bookmarks, lyrics, saved playlists and Web Radio
    -	- Show / hide items (Library | I^microsd^I SD | and | I^usbdrive^I USB | will be hidden.)
    -	- Display order of Library home
    +	· Library database
    +	· Data - Audio CD, bookmarks, lyrics, saved playlists and Web Radio
    +	· Show / hide items (Library | I^microsd^I SD | and | I^usbdrive^I USB | will be hidden.)
    +	· Display order of Library home
     	
      • rAudio as server: (Alternative 1)
     	Server: | I^features^I Features | Server rAudio I^rserver^I ◨ |
    @@ -340,16 +339,15 @@
     	
      • Other servers: (Alternative 2)
     	Server: Create a share for data with full permissions
    -		- Linux:
    +		· Linux:
     			NFS: 777
     			CIFS/SMB: read only = no
    -		- Windows:
    +		· Windows:
     			| Sharing | Permissions | Everyone - Full Control
     			| Security | Everyone - Full Control
     	Clients:
    -		- | Storage I^plus-circle^I | Add music file share with the same name, share path/share name
    -		- | Shared Data I^networks^I ◨ | Add the created share on server
    -		- Data on 1st connected client will be used as initial shared.
    +		· | Shared Data I^networks^I ◨ | Add the created share
    +		· Data on 1st connected client will be used as initial shared.
     		
     (SSH password must be default.)
     EOF