diff --git a/install.sh b/install.sh index ee72677bc..8632535be 100644 --- a/install.sh +++ b/install.sh @@ -4,9 +4,28 @@ alias=r1 # restore 20230522 #. /srv/http/bash/settings/addons.sh -# 20230522 [[ -e /srv/http/bash/settings/addons.sh ]] && . /srv/http/bash/settings/addons.sh || . /srv/http/bash/addons.sh +# 20230610 +rm -f $dirshm/system + +file=$dirsystem/localbrowser.conf +if [[ -e $file ]]; then + rotate=$( getVar rotate $file | tr -dc [A-Z] ) + if [[ $rotate ]]; then + case $rotate in + NORMAL ) degree=0;; + CCW ) degree=270;; + CW ) degree=90;; + UD ) degree=180;; + esac + sed -i "s/^rotate.*/rotate=$degree/" $file + fi +fi +rm -f /tmp/localbrowser.conf + +[[ $( pacman -Q bluealsa ) != 'bluealsa 4.1.0-1' ]] && pacman -Sy --noconfirm bluealsa + # 20230528 file=$dirmpdconf/conf/snapserver.conf if grep -q port $file; then @@ -26,11 +45,8 @@ if [[ ! -e /boot/kernel.img && -e /lib/python3.11 && ! -e /lib/python3.11/site-p fi # 20230522 -if crontab -l | grep -q addonsupdates; then - echo "\ -00 01 * * * $dirsettings/addons-data.sh -$( crontab -l | grep -v addonsupdates )" | crontab - -fi +crontab -l | grep -q addonsupdates && echo "00 01 * * * $dirsettings/addons-data.sh" | crontab - +systemctl restart cronie if ls $dirsystem/autoplay* &> /dev/null && [[ ! -s $dirsystem/autoplay ]]; then k=( startup bluetooth cd ) @@ -207,15 +223,8 @@ sed -i "s/?v=.*/$hash';/" /srv/http/common.php installfinish #------------------------------------------------------------------------------- -# 20230528 -if [[ -e $dirshm/mixernone && $( volumeGet valdb | jq .db ) != 0 ]]; then - rm -f $dirshm/mixernone $dirsystem/mixertype-* - $dirsettings/player-conf.sh - echo "$info Re-enable again: Volume Control - None/0dB" -fi - # 20230522 -[[ ! -e $dirshm/cpuinfo ]] && cpuInfo +[[ ! -e $dirshm/cpuinfo ]] && $dirsettings/system.sh cpuinfo ! grep -q listing $dirbash/mpdidle.sh && systemctl restart mpd @@ -232,3 +241,10 @@ if grep -q /srv/http/data /etc/exports; then - Disable server - Re-enable again" fi + +# 20230528 +if [[ -e $dirshm/mixernone && $( volumeGet valdb | jq .db ) != 0 ]]; then + rm -f $dirshm/mixernone $dirsystem/mixertype-* + $dirsettings/player-conf.sh + echo "$info Re-enable again: Volume Control - None/0dB" +fi diff --git a/srv/http/assets/css/common.css b/srv/http/assets/css/common.css index 3b9976988..277977c83 100644 --- a/srv/http/assets/css/common.css +++ b/srv/http/assets/css/common.css @@ -10,7 +10,7 @@ @font-face { font-family : rern; - src : url( '/assets/fonts/rern.woff2?v=1685410296' ); + src : url( '/assets/fonts/rern.woff2?v=1685865311' ); } @font-face { font-family : Lato; @@ -727,6 +727,9 @@ hr { margin: 10px auto; text-align: left; } +#infoContent .menu a { + height: 41px; +} #infoContent .menu i { width: 40px; } diff --git a/srv/http/assets/css/main.css b/srv/http/assets/css/main.css index 43d848e35..17758f686 100644 --- a/srv/http/assets/css/main.css +++ b/srv/http/assets/css/main.css @@ -1237,9 +1237,6 @@ i.map.disabled, .map.disabled i { text-align: center; color: var( --cg60 ); } -.mode gr { - margin-left: 8px; -} #lib-mode-list gr { font-size: 14px; } @@ -1392,13 +1389,18 @@ i.map.disabled, .map.disabled i { #infoIcon .button-coverart { margin-left: 0; } +.button-coverart::before, .button-coverart::after { position: relative; margin-left: 4px; content: '\f528'; font-family: rern; font-size: 26px; - text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000; +} +.button-coverart::before { + position: absolute; + content: '\f52C'; + color: var( --cg ); } .button-coverart img { position: absolute; @@ -1546,11 +1548,10 @@ i.map.disabled, .map.disabled i { .coverart2 { display: block; padding-left: 2px; - line-height: 18px; + line-height: 15px; } .coverart1 { padding-top: 3px; - line-height: 15px; } .coverart2 { color: var( --cg60 ); @@ -2184,7 +2185,7 @@ li.active .li2 bl { /************************************************************************************/ @media ( max-width: 320px ) and ( max-height: 480px ) { #page-playback { - padding-top: 30px !important; + padding: 30px 0 0 0; overflow: hidden; } #sampling, @@ -2197,6 +2198,7 @@ li.active .li2 bl { } @media ( max-width: 480px ) and ( max-height: 320px ) { #page-playback { + height: 100vh; --scale: 0.65; padding: 40px 0 0 !important; } diff --git a/srv/http/assets/fonts/rern.woff2 b/srv/http/assets/fonts/rern.woff2 index d95e31b5c..9a53e4ddb 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/addons.js b/srv/http/assets/js/addons.js index b917fe8e5..c42851f2d 100644 --- a/srv/http/assets/js/addons.js +++ b/srv/http/assets/js/addons.js @@ -112,7 +112,7 @@ function renderPage() { var version = 'version' in addon ? ' '+ addon.version +' ' : ''; if ( 'revision' in addon ) { var revision = '

'; - addon.revision.forEach( el => revision += ''+ el +'
' ); + addon.revision.forEach( el => revision += ' '+ el +'
' ); revision += '

'; } else { var revision = ''; diff --git a/srv/http/assets/js/common.js b/srv/http/assets/js/common.js index 140bdf3f8..c3e06a66b 100644 --- a/srv/http/assets/js/common.js +++ b/srv/http/assets/js/common.js @@ -145,10 +145,11 @@ $( '.col-r .switch' ).press( function( e ) { // ---------------------------------------------------------------------- function banner( icon, title, message, delay ) { clearTimeout( I.timeoutbanner ); + var bottom = $( '#bar-bottom' ).is( '.transparent, :hidden' ) || ! $( '#loader' ).hasClass( 'hide' ) ? '10px' : ''; $( '#banner' ) .html( '
'+ ico( icon ) +'
'+ title +'
' +'
'+ message +'
' ) - .css( 'bottom', $( '#bar-bottom' ).is( '.transparent, :hidden' ) ? '10px' : '' ) + .css( 'bottom', bottom ) .removeClass( 'hide' ); if ( delay !== -1 ) I.timeoutbanner = setTimeout( bannerHide, delay || 3000 ); } @@ -987,25 +988,15 @@ function local( delay ) { // pushstream ----------------------------------------------------------------- if ( ! [ 'addonsprogress', 'guide' ].includes( page ) ) { - var pushstream = new PushStream( { - modes : 'websocket' - , reconnectOnChannelUnavailableInterval : 3000 - } ); - function pushstreamChannel( channels ) { - channels.forEach( channel => pushstream.addChannel( channel ) ); - pushstream.connect(); - } function psNotify( data ) { var icon = data.icon; var title = data.title; var message = data.message; var delay = data.delay; - - banner( icon, title, message, delay ); if ( [ 'Off ...', 'Reboot ...' ].includes( message ) ) { var type = message.split( ' ' )[ 0 ].toLowerCase(); V[ type ] = true; - setTimeout( loader, 0 ); + loader(); } else if ( ! page ) { if ( message === 'Change track ...' ) { // audiocd clearIntervalAll(); @@ -1015,8 +1006,17 @@ if ( ! [ 'addonsprogress', 'guide' ].includes( page ) ) { if ( V.mode === 'latest' ) $( '#button-library' ).trigger( 'click' ); } } + banner( icon, title, message, delay ); } + var pushstream = new PushStream( { + modes : 'websocket' + , reconnectOnChannelUnavailableInterval : 3000 + } ); + function pushstreamChannel( channels ) { + channels.forEach( channel => pushstream.addChannel( channel ) ); + pushstream.connect(); + } pushstream.onstatuschange = status => { // 0 - disconnected; 1 - reconnect; 2 - connected if ( status === 2 ) { // connected if ( V.reboot ) { diff --git a/srv/http/assets/js/context.js b/srv/http/assets/js/context.js index ed65825fc..f9af3a080 100644 --- a/srv/http/assets/js/context.js +++ b/srv/http/assets/js/context.js @@ -23,9 +23,9 @@ function addToPlaylist() { function addToPlaylistCommand() { if ( V.action !== 'add' && V.action !== 'playnext' ) $( '#stop' ).trigger( 'click' ); if ( D.playbackswitch && V.action.slice( -4 ) === 'play' ) $( '#playback' ).trigger( 'click' ); - var sleep = [ 'http', 'rtsp' ].includes( V.list.path.slice( 0, 4 ) ) ? 1 : 0.2; - if ( S.state === 'play' && S.webradio ) sleep += 1; - if ( V.action.slice( -4 ) === 'play' ) sleep += 1; + var sleep = 0; + if ( S.stream ) sleep++; + if ( V.action.slice( -4 ) === 'play' ) sleep++; var varaction = ''; if ( V.action === 'addplay' ) { varaction = ' ACTION DELAY'; diff --git a/srv/http/assets/js/features.js b/srv/http/assets/js/features.js index 8e76734bc..edb0e39c7 100644 --- a/srv/http/assets/js/features.js +++ b/srv/http/assets/js/features.js @@ -5,7 +5,7 @@ var default_v = { , STARTUP : true } , localbrowser : { - ROTATE : 'NORMAL' + ROTATE : 0 , ZOOM : 100 , SCREENOFF : 0 , ONWHILEPLAY : false @@ -169,10 +169,10 @@ $( '#setting-localbrowser' ).on( 'click', function() { @@ -195,8 +195,8 @@ $( '#setting-localbrowser' ).on( 'click', function() {
Rotation
Zoom
Brightness

-  Reload${ ico( 'redo' ) } - ${ ico( 'screenoff' ) }On/Off +  Reload ${ ico( 'redo' ) }  + ${ ico( 'screenoff' ) } On/Off
 
`; info( { icon : SW.icon diff --git a/srv/http/assets/js/function.js b/srv/http/assets/js/function.js index 85ff3868f..6e45cb570 100644 --- a/srv/http/assets/js/function.js +++ b/srv/http/assets/js/function.js @@ -11,7 +11,6 @@ function list( args, callback, json ) { function bio( artist, getsimilar ) { if ( artist === $( '#biocontent .artist' ).text() ) { $( '#bio' ).removeClass( 'hide' ); - bioTitleSet(); return } @@ -35,7 +34,7 @@ function bio( artist, getsimilar ) { V.bioartist.push( artist ); var data = data.artist; - artistname = data.name; + var name = data.name; var content = data.bio.content.replace( /\n/g, '
' ).replace( /Read more on Last.fm.*/, '' ); var genre = data.tags.tag[ 0 ].name; var backhtml = getsimilar ? ico( 'arrow-left bioback' ) : ''; @@ -48,8 +47,8 @@ function bio( artist, getsimilar ) { var biohtml = `
-

${ artistname + ico( 'close close-root closebio' ) }

-

${ ico( 'genre i-lg' ) } ${ genre }${ backhtml }

+

${ ico( 'close close-root closebio' ) + name }

+

${ backhtml + ico( 'genre i-lg' ) +' '+ genre }

${ similarhtml }

${ content }

@@ -66,29 +65,36 @@ function bio( artist, getsimilar ) { .scrollTop( 0 ); $.get( 'https://webservice.fanart.tv/v3/music/'+ data.mbid +'?api_key='+ V.apikeyfanart ).done( data => { if ( 'error message' in data ) { - loaderHide(); + bioImageSet(); return } if ( 'musicbanner' in data && data.musicbanner[ 0 ].url ) $( '#biocontent' ).before( '' ) + var imageshtml = ''; if ( 'artistthumb' in data && data.artistthumb[ 0 ].url ) { - var imageshtml = ''; data.artistthumb.forEach( el => imageshtml += '' ); - $( '#biocontent .artist' ) - .before( '
'+ imageshtml +'
' ) - .prepend( '' ); - bioTitleSet(); } - loaderHide(); + bioImageSet( imageshtml ) $( '#bio' ).scrollTop( 0 ); } ).fail( function() { // 404 not found - loaderHide(); + bioImageSet(); } ); } ); } ); } -function bioTitleSet() { +function bioImageSet( imageshtml ) { var $artist = $( '#biocontent .artist' ); + if ( ! imageshtml ) { + if ( $artist.text() !== S.Artist || ! S.coverart ) { + loaderHide(); + return + } + + imageshtml = ''; + } + $artist + .before( '
'+ imageshtml +'
' ) + .prepend( '' ); var titleafter = $artist.prev().prop('id') === 'bioimg'; if ( 'observer' in V ) V.observer.disconnect(); if ( V.wW < 481 ) { @@ -102,6 +108,7 @@ function bioTitleSet() { } V.observer = new IntersectionObserver( entries => $( '#biotitleimg' ).toggleClass( 'hide', entries[ 0 ].isIntersecting ), options ); V.observer.observe( $( '#bioimg' )[ 0 ] ); + loaderHide(); } function blinkDot() { if ( ! localhost ) return @@ -295,14 +302,14 @@ function contextmenuLibrary( $li, $target ) { $li.addClass( 'active' ); return } - var filemode = [ 'nas', 'sd', 'usb', 'dabradio', 'webradio' ].includes( V.mode ); + var filemode = [ 'album', 'nas', 'sd', 'usb', 'dabradio', 'webradio' ].includes( V.mode ); $menu.find( '.playnext, .replace' ).toggleClass( 'hide', ! S.pllength ); $menu.find( '.replace' ).next().toggleClass( 'hide', ! S.pllength ); $menu.find( '.refresh-library' ).toggleClass( 'hide', ! ( 'updating_db' in S ) ); - $( '#menu-folder a:not(.sub)' ).toggleClass( 'hide', V.list.licover && ! filemode && V.mode !== 'album' ); + $( '#menu-folder a:not(.sub)' ).toggleClass( 'hide', V.list.licover && ! filemode ); $menu.find( '.bookmark, .exclude, .update, .thumb' ).toggleClass( 'hide', ! filemode ); $menu.find( '.directory' ).toggleClass( 'hide', filemode ); - $menu.find( '.tag' ).toggleClass( 'hide', ! V.librarytrack || ! filemode ); + $menu.find( '.tag' ).toggleClass( 'hide', ! V.librarytrack || ( ! filemode ) ); $menu.find( '.wredit' ).toggleClass( 'hide', V.mode !== 'webradio' ); $menu.find( '.wrdirrename' ).toggleClass( 'hide', V.mode.slice( -5 ) !== 'radio' ); $li.addClass( 'active' ); @@ -668,6 +675,12 @@ function infoLibraryOption() { keys.forEach( ( k, i ) => $el[ k ] = $( '#infoContent input' ).eq( i ) ); $( '#infoContent tr' ).css( 'height', '36px' ); $( '#infoContent td' ).css( 'width', '294px' ); + $el.fixedcover.prop( 'disabled', D.hidecover ); + $el.albumbyartist.on( 'click', function() { + var enable = $( this ).prop( 'checked' ); + if ( ! enable ) $el.albumyear.prop( 'checked', false ); + $el.albumyear.prop( 'disabled', ! enable ) + } ); $el.tapaddplay.on( 'click', function() { if ( $( this ).prop( 'checked' ) ) $el.tapreplaceplay.prop( 'checked', false ); } ); @@ -678,9 +691,8 @@ function infoLibraryOption() { var enable = $( this ).prop( 'checked' ) ? false : true; $el.fixedcover .prop( 'disabled', ! enable ) - .prop( 'checked', false ); + .prop( 'checked', enable ); } ); - $el.fixedcover.prop( 'disabled', D.hidecover ); } , ok : displaySave } ); @@ -1148,10 +1160,9 @@ function renderLibrary() { // library home renderLibraryCounts(); } function renderLibraryCounts() { - $( '.mode gr' ).toggleClass( 'hide', ! D.count ); var songs = C.song ? C.song.toLocaleString() + ico( 'music' ) : ''; $( '#li-count' ).html( songs ); - $.each( C, ( k, v ) => $( '#mode-'+ k ).find( 'gr' ).text( v ? v.toLocaleString() : '' ) ); + $.each( C, ( k, v ) => $( '#mode-'+ k ).find( 'gr' ).html( v ? ' '+ v.toLocaleString() : '' ) ); } function renderLibraryList( data ) { // V.librarylist if ( V.librarylist && data.html === V.librarylisthtml ) { @@ -1210,11 +1221,10 @@ function renderLibraryList( data ) { // V.librarylist var hash = versionHash(); var html = data.html.replace( /\^\^\^/g, hash ); $( '#lib-mode-list' ).after( html ).promise().done( () => { + V.librarytrack = $( '#lib-list .li-icon' ).hasClass( 'i-music' ); if ( $( '.licover' ).length ) { // V.librarytrack - V.librarytrack = true; if ( $( '#liimg' ).attr( 'src' ).slice( 0, 16 ) === '/data/shm/online' ) $( '.licoverimg ' ).append( V.icoversave ); } else { - V.librarytrack = false; imageLoad( 'lib-list' ); } $( '.liinfopath' ).toggleClass( 'hide', [ 'sd', 'nas', 'usb', 'webradio' ].includes( V.mode ) ); @@ -2038,11 +2048,15 @@ function volumeColorUnmute() { $( '#mi-mute, #ti-mute' ).addClass( 'hide' ); } function volumeUpDown( up ) { - var vol = S.volume; - up ? vol++ : vol--; - if ( vol < 0 || vol > 100 ) return + up ? S.volume++ : S.volume--; + if ( S.volume < 0 || S.volume > 100 ) return - $volumeRS.setValue( vol ); + if ( D.volume ) { + $volumeRS.setValue( S.volume ); + } else { + $( '#volume-text' ).text( S.volume ); + $( '#volume-bar' ).css( 'width', S.volume +'%' ); + } var cmd = 'volumeupdn'; if ( S.btreceiver ) { cmd += 'bt'; diff --git a/srv/http/assets/js/main.js b/srv/http/assets/js/main.js index 2c21ecebd..6209ebb82 100644 --- a/srv/http/assets/js/main.js +++ b/srv/http/assets/js/main.js @@ -84,11 +84,11 @@ var chkdisplay = { , label : 'Label' } , liboption : { - albumbyartist : ico( 'album' ) +'Album - Sort by artists' + albumbyartist : ico( 'album' ) +'Album - Sort by artist' + , albumyear : ico( 'album' ) +'Sort by artist > year' , tapaddplay : 'Select track = '+ ico( 'play-plus infomenusub' ) +'Add + Play' , tapreplaceplay : 'Select track = '+ ico( 'play-replace infomenusub' ) +'Replace + Play' , playbackswitch : 'Switch to Playback on '+ ico( 'play-plus infomenusub' ) +'or '+ ico( 'play-replace infomenusub' ) - , '-' : '' , backonleft : ico( 'arrow-left bl' ) +'Back button on left side' , hidecover : 'Hide coverart band in tracks view' , fixedcover : 'Fix coverart band on large screen' @@ -397,8 +397,8 @@ $( '#displayplaylist' ).on( 'click', function() { } if ( 'coverTL' in V ) $( '#coverTL' ).trigger( 'click' ); var keys = Object.keys( chkplaylist ); - var values = []; - keys.forEach( k => values.push( D[ k ] ) ); + var values = {}; + keys.forEach( k => values[ k ] = D[ k ] ); info( { icon : 'playlist' , title : 'Playlist' @@ -680,24 +680,22 @@ $( '#volmute, #volM' ).on( 'click', function() { $( '#voldn, #volup, #volT, #volB, #volL, #volR, #volume-band-dn, #volume-band-up' ).on( 'click', function( e ) { local(); volumeUpDown( $( e.currentTarget ).hasClass( 'up' ) ); - if ( [ 'volume-band-dn', 'volume-band-up' ].includes( e.currentTarget.id ) ) $( '#volume-text, #volume-bar' ).removeClass( 'hide' ); + if ( $( e.currentTarget ).hasClass( 'band' ) ) $( '#volume-text, #volume-bar' ).removeClass( 'hide' ); } ).on( 'touchend mouseup', function( e ) { clearInterval( V.interval.volume ); - if ( ! $( '#volume-bar' ).hasClass( 'hide' ) ) { + if ( D.volume ) { + $( '#volume-text' ).text( S.volume ); + $( '#volume-bar' ).css( 'width', S.volume +'%' ); + } else { + $volumeRS.setValue( S.volume ); clearTimeout( V.volumebar ); V.volumebar = setTimeout( volumeBarHide, 3000 ); } } ).press( function( e ) { + clearTimeout( V.volumebar ); + if ( ! D.volume ) $( '#volume-bar, #volume-text' ).removeClass( 'hide' ); var up = $( e.currentTarget ).hasClass( 'up' ); - V.interval.volume = setInterval( () => { - volumeUpDown( up ); - if ( $( e.currentTarget ).hasClass( 'band' ) ) { - clearTimeout( V.volumebar ); - $( '#volume-bar, #volume-text' ).removeClass( 'hide' ); - $( '#volume-text' ).text( vol ); - $( '#volume-bar' ).css( 'width', vol +'%' ); - } - }, 100 ); + V.interval.volume = setInterval( () => volumeUpDown( up ), 100 ); } ); $( '#volume-text' ).on( 'click', function() { // mute / unmute clearTimeout( V.volumebar ); @@ -1185,27 +1183,28 @@ $( '#lib-mode-list' ).on( 'click', function( e ) { if ( V.mode === 'bookmark' ) return if ( ! C[ V.mode ] && V.mode.slice( -5 ) !== 'radio' ) { + var json = { + icon : 'library' + , title : 'Library Database' + } if ( V.mode === 'playlists' ) { - var message = 'No saved playlists found.'; + json.message = 'No saved playlists found.'; } else if ( V.mode === 'latest' ) { - var message = 'No new albums added since last update.'; + json.message = 'No new albums added since last update.'; } else { - var message = 'Database not yet available in this mode.' - +'
If music files already in SD, NAS or USB,' - +'
import them to database:' - +'' - } - info( { - icon : 'library' - , title : 'Library Database' - , message : message - , okno : true - , beforeshow : () => { + json.message = 'Database not yet available in this mode.' + +'
If music files already in SD, NAS or USB,' + +'
import them to database:' + +''; + json.okno = true; + json.beforeshow = () => { $( '#infoContent' ).on( 'click', '.submenu', function() { $( '#update' ).trigger( 'click' ); } ); } - } ); + } + info( json ); return } @@ -1433,7 +1432,7 @@ $( '#page-library' ).on( 'click', '#lib-list .coverart', function() { list( query, function( html ) { var data = { html : html - , modetitle : $this.find( D.albumbyartist ? '.coverart2' : '.coverart1' ).text() + , modetitle : $this.find( '.liname' ).text() , path : 'ALBUM' } renderLibraryList( data ); diff --git a/srv/http/assets/js/networks.js b/srv/http/assets/js/networks.js index e2c605452..aa36adde1 100644 --- a/srv/http/assets/js/networks.js +++ b/srv/http/assets/js/networks.js @@ -141,16 +141,21 @@ $( '.disconnect' ).on( 'click', function() { var ssid = V.li.data( 'ssid' ); var icon = 'wifi'; - info( { - icon : icon - , title : ssid - , message : ( S.listeth ? '' : iconwarning +'No network connections after this.
' ) +'Disconnect?' - , okcolor : orange - , ok : () => { - notify( icon, ssid, 'Disconnect ...' ); - bash( [ 'disconnect' ] ) - } - } ); + if ( S.ipeth ) { + notify( icon, ssid, 'Disconnect ...' ); + bash( [ 'disconnect' ] ) + } else { + info( { + icon : icon + , title : ssid + , message : ( S.listeth ? '' : iconwarning +'No network connections after this.
' ) +'Disconnect?' + , okcolor : orange + , ok : () => { + notify( icon, ssid, 'Disconnect ...' ); + bash( [ 'disconnect' ] ) + } + } ); + } } ); $( '.edit' ).on( 'click', function() { V.listid === 'listwl' ? infoWiFiGet() : infoLan(); diff --git a/srv/http/assets/js/passive.js b/srv/http/assets/js/passive.js index bda47d4e3..a1e510611 100644 --- a/srv/http/assets/js/passive.js +++ b/srv/http/assets/js/passive.js @@ -129,6 +129,8 @@ function psDisplay( data ) { return } + var albumlistchanged = D.albumbyartist !== data.albumbyartist || D.albumyear !== data.albumyear; + var hidecoverchanged = D.hidecover !== data.hidecover; $.each( data, ( k, v ) => { D[ k ] = v } ); // need braces V.coverdefault = ! D.covervu && ! D.vumeter ? V.coverart : V.covervu; if ( ! D.covervu && ! D.vumeter ) { @@ -144,22 +146,24 @@ function psDisplay( data ) { } else if ( V.library ) { if ( ! V.librarylist ) { renderLibrary(); - } else if ( $( '.li-icon' ).eq( 0 ).hasClass( 'i-music' ) ) { - if ( D.hidecover ) { - $( '.licover' ).remove(); - } else { - var query = V.query.slice( -1 )[ 0 ]; - list( query, function( html ) { - var data = { - html : html - , modetitle : query.modetitle - , path : query.path - } - renderLibraryList( data ); - } ); + } else { + $( '#button-lib-back' ).toggleClass( 'back-left', D.backonleft ); + if ( V.librarytrack ) { + if ( hidecoverchanged ) { + var query = V.query.slice( -1 )[ 0 ]; + list( query, function( html ) { + var data = { + html : html + , modetitle : query.modetitle + , path : query.path + } + renderLibraryList( data ); + } ); + } + } else if ( V.mode === 'album' ) { + if ( albumlistchanged ) $( '#mode-album' ).trigger( 'click' ); } } - $( '#button-lib-back' ).toggleClass( 'back-left', D.backonleft ); } } function psEqualizer( data ) { diff --git a/srv/http/assets/js/system.js b/srv/http/assets/js/system.js index 3e0b11530..07d57f5ad 100644 --- a/srv/http/assets/js/system.js +++ b/srv/http/assets/js/system.js @@ -452,7 +452,7 @@ $( '#setting-tft' ).on( 'click', function() { , 'Waveshare (B) Rev 2.0' : 'waveshare35b-v2' , 'Waveshare (C)' : 'waveshare35c' } - , values : S.tftconf || 'tft35a' + , values : { MODEL: S.tftconf || 'tft35a' } , checkchanged : S.tft , boxwidth : 190 , buttonlabel : ! buttoncalibrate ? '' : 'Calibrate' diff --git a/srv/http/bash/cmd-list.sh b/srv/http/bash/cmd-list.sh index fd3c543aa..32fabf7e8 100644 --- a/srv/http/bash/cmd-list.sh +++ b/srv/http/bash/cmd-list.sh @@ -33,7 +33,7 @@ touch $dirmpd/listing ##### normal list ############################################# listAll() { - mpc -f '%album%^^[%albumartist%|%artist%]^^%file%' listall 2> /dev/null \ + mpc -f '[%albumartist%|%artist%]^^%date%^^%album%^^%file%' listall 2> /dev/null \ | awk -F'/[^/]*$' 'NF && !/^\^/ {print $1}' \ | sort -u # -F'/[^/]*$' - truncate %file% to path without filename @@ -71,7 +71,7 @@ if [[ ! $album_artist_file ]]; then # very large database fi if [[ $albums ]]; then for album in "${albums[@]}"; do - album_artist_file+=$( mpc -f '%album%^^[%albumartist%|%artist%]^^%file%' find album "$album" \ + album_artist_file+=$( mpc -f '[%albumartist%|%artist%]^^%date^^%album%^^%file%' find album "$album" \ | awk -F'/[^/]*$' 'NF && !/^\^/ && !a[$0]++ {print $1}' \ | sort -u )$'\n' done @@ -103,7 +103,7 @@ fi filealbum=$dirmpd/album filealbumprev=$dirmpd/albumprev -if [[ $( awk NF $dirmpd/album ) && $( getContent $dirmpd/updating ) != rescan ]]; then +if [[ -s $filealbum && $( getContent $dirmpd/updating ) != rescan ]]; then cp -f $filealbum{,prev} else > $dirmpd/latest @@ -113,6 +113,7 @@ fi for mode in album albumartist artist composer conductor genre date; do filemode=$dirmpd/$mode if [[ $mode == album ]]; then + filemode+=byartist-year album=$( awk NF <<< $album_artist_file | sort -uf ) if [[ -e $dirmpd/albumignore ]]; then readarray -t albumignore < $dirmpd/albumignore @@ -120,7 +121,7 @@ for mode in album albumartist artist composer conductor genre date; do album=$( sed "/^$line^/ d" <<< $album ) done fi - album=$( awk NF <<< $album | tee $filealbum | wc -l ) + album=$( awk NF <<< $album | tee $filemode | wc -l ) else printf -v $mode '%s' $( mpc list $mode | awk NF | awk '{$1=$1};1' | tee $filemode | wc -l ) fi @@ -139,7 +140,7 @@ if [[ -e $filealbumprev ]]; then # latest mv -f $dirmpd/latest{new,} fi fi - [[ -e $dirmpd/latest ]] && latest=$( wc -l < $dirmpd/latest ) || latest=0 + latest=$( wc -l < $dirmpd/latest ) fi ##### count ############################################# dabradio=$( find -L $dirdata/dabradio -type f ! -path '*/img/*' 2> /dev/null | wc -l ) # no $dirdabradio if dab not installed diff --git a/srv/http/bash/cmd-listsort.php b/srv/http/bash/cmd-listsort.php index 325b4004b..5fa5aede5 100644 --- a/srv/http/bash/cmd-listsort.php +++ b/srv/http/bash/cmd-listsort.php @@ -16,7 +16,7 @@ function stripSort( $str ) { ); if ( !preg_match( '/[\x80-\xff]/', $string ) ) return $string; - // strip accents + // strip accents: https://stackoverflow.com/a/10790734 $chars = array( // Decompositions for Latin-1 Supplement chr(195).chr(128) => 'A', chr(195).chr(129) => 'A', @@ -26,27 +26,30 @@ function stripSort( $str ) { chr(195).chr(137) => 'E', chr(195).chr(138) => 'E', chr(195).chr(139) => 'E', chr(195).chr(140) => 'I', chr(195).chr(141) => 'I', chr(195).chr(142) => 'I', - chr(195).chr(143) => 'I', chr(195).chr(145) => 'N', + chr(195).chr(143) => 'I', + chr(195).chr(145) => 'N', chr(195).chr(146) => 'O', chr(195).chr(147) => 'O', chr(195).chr(148) => 'O', chr(195).chr(149) => 'O', chr(195).chr(150) => 'O', chr(195).chr(153) => 'U', chr(195).chr(154) => 'U', chr(195).chr(155) => 'U', - chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y', - chr(195).chr(159) => 's', chr(195).chr(160) => 'a', - chr(195).chr(161) => 'a', chr(195).chr(162) => 'a', - chr(195).chr(163) => 'a', chr(195).chr(164) => 'a', - chr(195).chr(165) => 'a', chr(195).chr(167) => 'c', + chr(195).chr(156) => 'U', + chr(195).chr(157) => 'Y', + chr(195).chr(159) => 's', + chr(195).chr(160) => 'a', chr(195).chr(161) => 'a', + chr(195).chr(162) => 'a', chr(195).chr(163) => 'a', + chr(195).chr(164) => 'a', chr(195).chr(165) => 'a', + chr(195).chr(167) => 'c', chr(195).chr(168) => 'e', chr(195).chr(169) => 'e', chr(195).chr(170) => 'e', chr(195).chr(171) => 'e', chr(195).chr(172) => 'i', chr(195).chr(173) => 'i', chr(195).chr(174) => 'i', chr(195).chr(175) => 'i', - chr(195).chr(177) => 'n', chr(195).chr(178) => 'o', - chr(195).chr(179) => 'o', chr(195).chr(180) => 'o', - chr(195).chr(181) => 'o', chr(195).chr(182) => 'o', - chr(195).chr(182) => 'o', chr(195).chr(185) => 'u', - chr(195).chr(186) => 'u', chr(195).chr(187) => 'u', - chr(195).chr(188) => 'u', chr(195).chr(189) => 'y', - chr(195).chr(191) => 'y', + chr(195).chr(177) => 'n', + chr(195).chr(178) => 'o', chr(195).chr(179) => 'o', + chr(195).chr(180) => 'o', chr(195).chr(181) => 'o', + chr(195).chr(182) => 'o', chr(195).chr(182) => 'o', + chr(195).chr(185) => 'u', chr(195).chr(186) => 'u', + chr(195).chr(187) => 'u', chr(195).chr(188) => 'u', + chr(195).chr(189) => 'y', chr(195).chr(191) => 'y', // Decompositions for Latin Extended-A chr(196).chr(128) => 'A', chr(196).chr(129) => 'a', chr(196).chr(130) => 'A', chr(196).chr(131) => 'a', @@ -90,12 +93,12 @@ function stripSort( $str ) { chr(197).chr(142) => 'O', chr(197).chr(143) => 'o', chr(197).chr(144) => 'O', chr(197).chr(145) => 'o', chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe', - chr(197).chr(148) => 'R',chr(197).chr(149) => 'r', - chr(197).chr(150) => 'R',chr(197).chr(151) => 'r', - chr(197).chr(152) => 'R',chr(197).chr(153) => 'r', - chr(197).chr(154) => 'S',chr(197).chr(155) => 's', - chr(197).chr(156) => 'S',chr(197).chr(157) => 's', - chr(197).chr(158) => 'S',chr(197).chr(159) => 's', + chr(197).chr(148) => 'R', chr(197).chr(149) => 'r', + chr(197).chr(150) => 'R', chr(197).chr(151) => 'r', + chr(197).chr(152) => 'R', chr(197).chr(153) => 'r', + chr(197).chr(154) => 'S', chr(197).chr(155) => 's', + chr(197).chr(156) => 'S', chr(197).chr(157) => 's', + chr(197).chr(158) => 'S', chr(197).chr(159) => 's', chr(197).chr(160) => 'S', chr(197).chr(161) => 's', chr(197).chr(162) => 'T', chr(197).chr(163) => 't', chr(197).chr(164) => 'T', chr(197).chr(165) => 't', @@ -113,41 +116,53 @@ function stripSort( $str ) { chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z', chr(197).chr(190) => 'z', chr(197).chr(191) => 's' ); - return strtr( $string, $chars ); + $string = strtr($string, $chars); + + return $string; } if ( isset( $argv[ 1 ] ) ) { - $file = $argv[ 1 ]; + $file = $argv[ 1 ]; $lines = file( $file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES ); - $sort = []; - if ( $file === '/srv/http/data/mpd/album' ) { - $sort1 = []; + $sort = []; + if ( $file === '/srv/http/data/mpd/albumbyartist-year' ) { + $byalbumsort = []; + $byartistsort = []; foreach( $lines as $line ) { if ( substr( $line, -4 ) === '.cue' ) $line = dirname( $line ); - $sort[] = stripSort( $line ).'^x^'.$line; - $data1 = explode( '^^', $line ); - $line1 = $data1[ 1 ].'^^'.$data1[ 0 ].'^^'.$data1[ 2 ]; - $sort1[] = stripSort( $line1 ).'^x^'.$line1; + $sort[] = stripSort( $line ).'^x^'.$line; + $data = explode( '^^', $line ); // artist date album file + $byalbumline = $data[ 2 ].'^^'.$data[ 0 ].'^^'.$data[ 3 ]; + $byalbumsort[] = stripSort( $byalbumline ).'^x^'.$byalbumline; + $byartistline = $data[ 0 ].'^^'.$data[ 2 ].'^^'.$data[ 3 ]; + $byartistsort[] = stripSort( $byartistline ).'^x^'.$byartistline; } - usort( $sort1, function( $a, $b ) { + usort( $byalbumsort, function( $a, $b ) { return strnatcasecmp( $a, $b ); } ); - $array1 = []; - foreach( $sort1 as $line ) { - $index = mb_substr( $line, 0, 1, 'UTF-8' ); - $array1[] = $index.'^^'.explode( '^x^', $line )[ 1 ]; + $byalbum = []; + foreach( $byalbumsort as $line ) { + $index = mb_substr( $line, 0, 1, 'UTF-8' ); + $byalbum[] = $index.'^^'.explode( '^x^', $line )[ 1 ]; } - file_put_contents( $file.'byartist', implode( "\n", $array1 ) ); - } else { - foreach( $lines as $line ) { - $sort[] = stripSort( $line ).'^x^'.$line; + file_put_contents( '/srv/http/data/mpd/album', implode( "\n", $byalbum ) ); + usort( $byartistsort, function( $a, $b ) { + return strnatcasecmp( $a, $b ); + } ); + $byartist = []; + foreach( $byartistsort as $line ) { + $index = mb_substr( $line, 0, 1, 'UTF-8' ); + $byartist[] = $index.'^^'.explode( '^x^', $line )[ 1 ]; } + file_put_contents( '/srv/http/data/mpd/albumbyartist', implode( "\n", $byartist ) ); + } else { + foreach( $lines as $line ) $sort[] = stripSort( $line ).'^x^'.$line; } usort( $sort, function( $a, $b ) { return strnatcasecmp( $a, $b ); } ); $array = []; foreach( $sort as $line ) { - $index = mb_substr( $line, 0, 1, 'UTF-8' ); + $index = mb_substr( $line, 0, 1, 'UTF-8' ); $array[] = $index.'^^'.explode( '^x^', $line )[ 1 ]; } file_put_contents( $file, implode( "\n", $array ) ); diff --git a/srv/http/bash/cmd.sh b/srv/http/bash/cmd.sh index 9d1087d2e..a82523718 100644 --- a/srv/http/bash/cmd.sh +++ b/srv/http/bash/cmd.sh @@ -71,18 +71,12 @@ pushstreamVolume() { pushstream volume '{ "type": "'$1'", "val": '$2' }' } rotateSplash() { - local degree rotate + local rotate rotate=$( getVar rotate $dirsystem/localbrowser.conf ) - case $rotate in - NORMAL ) degree=0;; - CCW ) degree=-90;; - CW ) degree=90;; - UD ) degree=180;; - esac convert \ -density 48 \ -background none $dirimg/icon.svg \ - -rotate $degree \ + -rotate $rotate \ -gravity center \ -background '#000' \ -extent 1920x1080 \ @@ -331,6 +325,11 @@ dabscan ) ;; display ) pushstream display $( < $dirsystem/display.json ) + # temp + if grep -q albumyear.*true $dirsystem/display.json && [[ ! -e $dirmpd/albumbyartist-year ]]; then + pushstream mpdupdate '{ "type": "mpd" }' + $dirbash/cmd-list.sh &> /dev/null & + fi [[ -e $dirsystem/vumeter ]] && prevvumeter=1 grep -q -m1 vumeter.*true $dirsystem/display.json && touch $dirsystem/vumeter && vumeter=1 [[ $prevvumeter == $vumeter ]] && exit @@ -910,7 +909,7 @@ wrdirdelete ) wrdirnew ) [[ $DIR ]] && path="$dirwebradio/$DIR/$SUB" || path="$dirwebradio/$SUB" mkdir -p "$path" - chown http:http "$path" + chown -h http:http "$path" chmod 755 "$path" pushstreamRadioList ;; diff --git a/srv/http/bash/common.sh b/srv/http/bash/common.sh index 223cd6ee7..1827fa6a8 100644 --- a/srv/http/bash/common.sh +++ b/srv/http/bash/common.sh @@ -222,6 +222,18 @@ packageActive() { (( i++ )) done } +package() { + file=$( dialog --colors --no-shadow --no-collapse --output-fd 1 --nocancel --menu " +Package: +" 8 0 0 \ +1 Build \ +2 'Update repo' ) + case $file in + 1 ) file=pkgbuild;; + 2 ) file=repoupdate;; + esac + bash <( curl -L https://github.com/rern/rern.github.io/raw/main/$file.sh ) +} pushRefresh() { local page push [[ $1 ]] && page=$1 || page=$( basename $0 .sh ) diff --git a/srv/http/bash/settings/features-data.sh b/srv/http/bash/settings/features-data.sh index 309673a7b..472946333 100644 --- a/srv/http/bash/settings/features-data.sh +++ b/srv/http/bash/settings/features-data.sh @@ -65,9 +65,7 @@ fi , "upmpdcli" : '$upmpdcli' , "upmpdcliconf" : { "OWNQUEUE": '$( grep -q -m1 'ownqueue = 1' /etc/upmpdcli.conf && echo true || echo false )' }' if [[ -e /etc/systemd/system/localbrowser.service ]]; then - if [[ ! -e /tmp/localbrowser.conf ]]; then - [[ -e $dirsystem/localbrowser.conf ]] && cp $dirsystem/localbrowser.conf /tmp || touch /tmp/localbrowser.conf - fi + [[ ! -e /tmp/localbrowser.conf && -e $dirsystem/localbrowser.conf ]] && cp $dirsystem/localbrowser.conf /tmp data+=' , "brightness" : '$( getContent /sys/class/backlight/rpi_backlight/brightness )' , "localbrowser" : '$localbrowser' diff --git a/srv/http/bash/settings/features.sh b/srv/http/bash/settings/features.sh index 118716d7b..a347f4431 100644 --- a/srv/http/bash/settings/features.sh +++ b/srv/http/bash/settings/features.sh @@ -25,7 +25,7 @@ localbrowserXset() { local off . $dirsystem/localbrowser.conf export DISPLAY=:0 - off=$(( $SCREENOFF * 60 )) + off=$(( $screenoff * 60 )) xset s off xset dpms $off $off $off if [[ $off == 0 ]]; then @@ -139,14 +139,6 @@ lastfmkey ) ;; localbrowser ) if [[ $ON ]]; then - file=$dirsystem/localbrowser.conf - diff=$( grep -Fxvf $file /tmp/localbrowser.conf ) - if [[ $diff ]]; then - for k in cursor rotate screenoff zoom; do - grep -q -m1 ^$k <<< $diff && printf -v diff$k '%s' 1 - done - [[ $diffcursor || $diffzoom ]] && restart=1 - fi if ! grep -q console=tty3 /boot/cmdline.txt; then sed -i -E 's/(console=).*/\1tty3 quiet loglevel=0 logo.nologo vt.global_cursor_default=0/' /boot/cmdline.txt systemctl disable --now getty@tty1 @@ -164,31 +156,42 @@ localbrowser ) sed -i '/hdmi_force_hotplug=1/ d' /boot/config.txt pushstream refresh '{ "page": "system", "hdmi": false }' fi - if [[ $diffrotate ]]; then - case $ROTATE in - NORMAL ) degree=0;; - CCW ) degree=270 && matrix='0 1 0 -1 0 1 0 0 1';; - CW ) degree=90 && matrix='0 -1 1 1 0 0 0 0 1';; - UD ) degree=180 && matrix='-1 0 1 0 -1 1 0 0 1';; - esac - $dirbash/cmd.sh rotatesplash - if grep -E -q 'waveshare|tft35a' /boot/config.txt; then - sed -i -E '/waveshare|tft35a/ s/(rotate=).*/\1'$degree'/' /boot/config.txt - cp -f /etc/X11/{lcd$degree,xorg.conf.d/99-calibration.conf} - pushRefresh - if ! grep -q rotate=$ROTATE /tmp/localbrowser.conf; then - echo Rotate GPIO LCD screen >> $dirshm/reboot - notify lcd 'Rotate GPIO LCD screen' 'Reboot required.' 5000 - exit - fi + if [[ -e /tmp/localbrowser.conf ]]; then + diff=$( grep -Fxvf $dirsystem/localbrowser.conf /tmp/localbrowser.conf ) + if [[ $diff ]]; then + for k in cursor rotate screenoff zoom; do + grep -q -m1 ^$k <<< $diff && printf -v diff$k '%s' 1 + done + [[ $diffcursor || $diffzoom ]] && restart=1 fi - + else restart=1 + fi + if grep -E -q 'waveshare|tft35a' /boot/config.txt; then # tft + sed -i -E '/waveshare|tft35a/ s/(rotate=).*/\1'$ROTATE'/' /boot/config.txt + cp -f /etc/X11/{lcd$ROTATE,xorg.conf.d/99-calibration.conf} + if [[ ! -e /tmp/localbrowser.conf || $diffrotate ]]; then + echo Rotate GPIO LCD screen >> $dirshm/reboot + notify lcd 'Rotate GPIO LCD screen' 'Reboot required.' 5000 + exit + + fi + else # hdmi rotateconf=/etc/X11/xorg.conf.d/99-raspi-rotate.conf - if [[ $matrix ]]; then - sed 's/ROTATION_SETTING/'$ROTATE'/; s/MATRIX_SETTING/'$matrix'/' /etc/X11/xinit/rotateconf > $rotateconf - else - rm -f $rotateconf + [[ -e $rotateconf ]] && rotateprev=$( awk '/rotate/ {print $NF}' $rotateconf | tr -d '"' ) + case $ROTATE in + 0 ) rotate=NORMAL;; + 270 ) rotate=CCW && matrix='0 1 0 -1 0 1 0 0 1';; + 90) rotate=CW && matrix='0 -1 1 1 0 0 0 0 1';; + 180) rotate=UD && matrix='-1 0 1 0 -1 1 0 0 1';; + esac + if [[ $rotateprev != $rotate ]]; then + if [[ $ROTATE == 0 ]]; then + rm -f $rotateconf + else + sed "s/ROTATION_SETTING/$rotate/; s/MATRIX_SETTING/$matrix/" /etc/X11/xinit/rotateconf > $rotateconf + fi + $dirbash/cmd.sh rotatesplash fi fi if [[ $diffscreenoff ]]; then @@ -197,13 +200,13 @@ localbrowser ) fi if [[ $restart ]] || ! systemctl -q is-active localbrowser; then restartlocalbrowser=1 - systemctl restart bootsplash localbrowser + systemctl restart bootsplash localbrowser &> /dev/null fi else localbrowserDisable fi - pushRefresh if [[ $restartlocalbrowser ]]; then + sleep 2 if systemctl -q is-active localbrowser; then systemctl enable bootsplash localbrowser systemctl stop bluetoothbutton @@ -213,6 +216,7 @@ localbrowser ) localbrowserDisable fi fi + pushRefresh ;; localbrowserreload ) pushstream reload 1 diff --git a/srv/http/bash/settings/networks-data.sh b/srv/http/bash/settings/networks-data.sh index eeab0baa6..a2d0488fe 100644 --- a/srv/http/bash/settings/networks-data.sh +++ b/srv/http/bash/settings/networks-data.sh @@ -71,7 +71,7 @@ if [[ $1 == pushwl ]]; then fi # bluetooth -rfkill | grep -q -m1 bluetooth && systemctl -q is-active bluetooth && activebt=1 +rfkill | grep -q -m1 bluetooth && systemctl -q is-active bluetooth && activebt=true [[ $activebt ]] && listbt=$( listBluetooth ) # wlan @@ -81,11 +81,10 @@ rfkill | grep -q -m1 bluetooth && systemctl -q is-active bluetooth && activebt=1 ifconfiglan=$( ifconfig | grep -A1 ^e ) [[ $ifconfiglan ]] && ipeth=$( grep inet <<< $ifconfiglan | awk '{print $2}' ) if [[ $ipeth ]]; then - ipr=$( ip r | grep ^default.*$lan ) + landev=$( grep ^e <<< $ifconfiglan | cut -d: -f1 ) + ipr=$( ip r | grep ^default.*$landev ) static=$( [[ $ipr != *"dhcp src $ipeth "* ]] && echo true ) gateway=$( cut -d' ' -f3 <<< $ipr ) -# dns=$( sed -n '/^nameserver/ {s/.* //;p}' /etc/resolv.conf ) -# subnet=$( ifconfig $lan | awk '/netmask/ {print $4}' ) [[ ! $gateway ]] && gateway=$( ip r | awk '/^default/ {print $3;exit}' ) if [[ $ipeth ]]; then hostname=$( avahi-resolve -a4 $ipeth | awk '{print $NF}' ) diff --git a/srv/http/bash/settings/player-conf.sh b/srv/http/bash/settings/player-conf.sh index 76d008f64..8fe860ebf 100644 --- a/srv/http/bash/settings/player-conf.sh +++ b/srv/http/bash/settings/player-conf.sh @@ -147,9 +147,7 @@ if [[ -e $dirmpd/updating ]]; then [[ $path == rescan ]] && mpc rescan || mpc update "$path" fi -if [[ -e $dirshm/btreceiver && -e $dirsystem/autoplay ]]; then - grep -q bluetooth=true $dirsystem/autoplay.conf && mpc -q play -fi +[[ -e $dirshm/btreceiver ]] && grep -q bluetooth=true $dirsystem/autoplay.conf && mpc -q play [[ $outputswitch ]] && notify output 'Audio Output' "$outputswitch" diff --git a/srv/http/bash/settings/player-devices.sh b/srv/http/bash/settings/player-devices.sh index e3e0983e8..bfe4d88d5 100644 --- a/srv/http/bash/settings/player-devices.sh +++ b/srv/http/bash/settings/player-devices.sh @@ -51,7 +51,12 @@ for line in "${aplay[@]}"; do card=${cnd[0]} aplayname=${cnd[1]} device=${cnd[2]} - [[ ${aplayname:0:8} == snd_rpi_ ]] && aplayname=$( tr _ - <<< ${aplayname:8} ) # some snd_rpi_xxx_yyy > xxx-yyy + if [[ ${aplayname:0:8} == snd_rpi_ ]]; then + aplayname=$( tr _ - <<< ${aplayname:8} ) # some snd_rpi_xxx_yyy > xxx-yyy + elif grep -q "aplayname.*$aplayname" <<< $devices; then # rpi4: hdmi1 + hdmi1 > hdmi1 + hdmi2 + lastchar=${aplayname: -1} + [[ $lastchar =~ [0-9] ]] && aplayname=${aplayname:0:-1}$(( $lastchar + 1 )) + fi if [[ $aplayname == Loopback ]]; then device=; hwmixer=; mixers=; mixerdevices=; mixertype=; name=; devices+=',{ diff --git a/srv/http/bash/settings/player.sh b/srv/http/bash/settings/player.sh index 11d1b1b14..dc394609d 100644 --- a/srv/http/bash/settings/player.sh +++ b/srv/http/bash/settings/player.sh @@ -165,11 +165,10 @@ statusalbumignore ) statusbtreceiver ) mac=$( cut -d' ' -f1 $dirshm/btconnected ) echo "\ -# bluealsa-aplay -L -$( bluealsa-aplay -L | grep -A2 $mac ) +$( pacman -Q bluealsa ) -# bluetoothctl info $mac -$( bluetoothctl info $mac )" +# bluealsa-aplay -L +$( bluealsa-aplay -L | grep -A2 $mac )" ;; statusmpdignore ) file=$dirmpd/mpdignorelist diff --git a/srv/http/bash/settings/system-data.sh b/srv/http/bash/settings/system-data.sh index 5e352342b..c573fc67e 100644 --- a/srv/http/bash/settings/system-data.sh +++ b/srv/http/bash/settings/system-data.sh @@ -57,6 +57,7 @@ else if [[ $rpimodel == *BeagleBone* ]]; then soc=AM3358 else + . $dirshm/cpuinfo soc=BCM case $C in 0 ) soc+=2835;; # 0, 1 @@ -242,7 +243,7 @@ data+=' , "rotaryencoder" : '$rotaryencoder' , "rotaryencoderconf" : '$( conf2json rotaryencoder.conf )' , "rpi01" : '$( exists /boot/kernel.img )' -, "shareddata" : '$( [[ -L $dirmpd && ! $nfsserver ]] && echo true )' +, "shareddata" : '$( [[ -L $dirmpd && $nfsserver == false ]] && echo true )' , "soundprofile" : '$( exists $dirsystem/soundprofile )' , "soundprofileconf" : '$soundprofileconf' , "status" : "'$status'" @@ -271,7 +272,7 @@ if [[ -e $dirshm/onboardwlan ]]; then , "wlanconf" : '$wlanconf' , "wlanconnected" : '$( ip r | grep -q -m1 "^default.*wlan0" && echo true ) discoverable=true - if grep -q -m1 ^dtparam=krnbt=on /boot/config.txt; then + if ! grep -q ^dtoverlay=disable-bt /boot/config.txt; then bluetoothon=true bluetoothactive=$bluetooth if [[ $bluetoothactive == true ]]; then diff --git a/srv/http/bash/settings/system-datareset.sh b/srv/http/bash/settings/system-datareset.sh index 6b328c2e6..f6e2749f8 100644 --- a/srv/http/bash/settings/system-datareset.sh +++ b/srv/http/bash/settings/system-datareset.sh @@ -49,8 +49,6 @@ initramfs initramfs-linux.img followkernel disable_overscan=1 disable_splash=1 dtparam=audio=on" - [[ $onboardwireless ]] && config+=" -dtparam=krnbt=on" [[ -e /boot/kernel7.img && -e /usr/bin/firefox ]] && config+=" hdmi_force_hotplug=1" [[ $rpi0 ]] && config+=" diff --git a/srv/http/bash/settings/system.sh b/srv/http/bash/settings/system.sh index a25aa5856..8ab06748a 100644 --- a/srv/http/bash/settings/system.sh +++ b/srv/http/bash/settings/system.sh @@ -102,15 +102,11 @@ dtparam=audio=on" configTxt ;; bluetooth ) - config=$( grep -v dtparam=krnbt=on /boot/config.txt ) + grep -q 'krnbt.*off' /boot/overlays/README && newkernel=1 # temp + config=$( grep -E -v 'disable-bt|krnbt=on' /boot/config.txt ) if [[ $ON ]]; then - config+=" + [[ ! $newkernel ]] && config+=" dtparam=krnbt=on" - if ls -l /sys/class/bluetooth | grep -q -m1 serial; then - systemctl start bluetooth - ! grep -q 'device.*bluealsa' $dirmpdconf/output.conf && $dirsettings/player-conf.sh - rfkill | grep -q -m1 bluetooth && pushstream refresh '{ "page": "networks", "activebt": true }' - fi if [[ $DISCOVERABLE ]]; then yesno=yes touch $dirsystem/btdiscoverable @@ -118,11 +114,18 @@ dtparam=krnbt=on" yesno=no rm $dirsystem/btdiscoverable fi - bluetoothctl discoverable $yesno &> /dev/null - [[ -e $dirsystem/btformat ]] && prevbtformat=true || prevbtformat= - [[ $FORMAT ]] && touch $dirsystem/btformat || rm $dirsystem/btformat + if ls -l /sys/class/bluetooth 2> /dev/null | grep -q -m1 serial; then + systemctl start bluetooth + bluetoothctl discoverable $yesno &> /dev/null + ! grep -q 'device.*bluealsa' $dirmpdconf/output.conf && $dirsettings/player-conf.sh + rfkill | grep -q -m1 bluetooth && pushstream refresh '{ "page": "networks", "activebt": true }' + fi + [[ -e $dirsystem/btformat ]] && prevbtformat=true + [[ $FORMAT ]] && touch $dirsystem/btformat || rm -f $dirsystem/btformat [[ $FORMAT != $prevbtformat ]] && $dirsettings/player-conf.sh else + [[ $newkernel ]] && config+=' +dtoverlay=disable-bt' if ! rfkill | grep -q -m1 bluetooth; then systemctl stop bluetooth rm -f $dirshm/{btdevice,btreceiver,btsender} @@ -138,6 +141,18 @@ bluetoothstart ) bluetoothctl discoverable-timeout 0 &> /dev/null bluetoothctl pairable yes &> /dev/null ;; +cpuinfo ) + hwrevision=$( grep ^Revision /proc/cpuinfo ) + BB=${hwrevision: -3:2} + C=${hwrevision: -4:1} + data=BB=$BB$'\n' + data+=C=$C$'\n' + [[ $BB =~ ^(09|0c|12)$ ]] || data+=onboardsound=true$'\n' # not zero, zero w, zero 2w + [[ $BB =~ ^(00|01|02|03|04|09)$ ]] || data+=onboardwireless=true$'\n' # not zero, 1, 2 + [[ $BB =~ ^(09|0c)$ ]] && data+=rpi0=true$'\n' # zero + [[ $BB == 0d ]] && data+=rpi3bplus=true$'\n' # 3B+ + echo "$data" > $dirshm/cpuinfo + ;; hddinfo ) echo -n "\ # hdparm -I $DEV @@ -546,9 +561,10 @@ tft ) if [[ $ON ]]; then [[ $MODEL != tft35a ]] && echo $MODEL > $dirsystem/lcdmodel || rm $dirsystem/lcdmodel sed -i '1 s/$/ fbcon=map:10 fbcon=font:ProFont6x11/' /boot/cmdline.txt + rotate=$( getVar rotate $dirsystem/localbrowser.conf ) config+=" hdmi_force_hotplug=1 -dtoverlay=$MODEL:rotate=0" +dtoverlay=$MODEL:rotate=$rotate" calibrationconf=/etc/X11/xorg.conf.d/99-calibration.conf [[ ! -e $calibrationconf ]] && cp /etc/X11/lcd0 $calibrationconf sed -i 's/fb0/fb1/' /etc/X11/xorg.conf.d/99-fbturbo.conf @@ -560,8 +576,8 @@ dtoverlay=$MODEL:rotate=0" configTxt ;; tftcalibrate ) - degree=$( grep rotate /boot/config.txt | cut -d= -f3 ) - cp -f /etc/X11/{lcd$degree,xorg.conf.d/99-calibration.conf} + rotate=$( grep rotate /boot/config.txt | cut -d= -f3 ) + cp -f /etc/X11/{lcd$rotate,xorg.conf.d/99-calibration.conf} systemctl stop localbrowser value=$( DISPLAY=:0 xinput_calibrator | grep Calibration | cut -d'"' -f4 ) if [[ $value ]]; then diff --git a/srv/http/bash/startup.sh b/srv/http/bash/startup.sh index 5aadeef55..9d8df845d 100644 --- a/srv/http/bash/startup.sh +++ b/srv/http/bash/startup.sh @@ -2,16 +2,7 @@ . /srv/http/bash/common.sh -hwrevision=$( grep ^Revision /proc/cpuinfo ) -BB=${hwrevision: -3:2} -C=${hwrevision: -4:1} - data=BB=$BB$'\n' - data+=C=$C$'\n' -[[ $BB =~ ^(09|0c|12)$ ]] || data+=onboardsound=true$'\n' # not zero, zero w, zero 2w -[[ $BB =~ ^(00|01|02|03|04|09)$ ]] || data+=onboardwireless=true$'\n' # not zero, 1, 2 -[[ $BB =~ ^(09|0c)$ ]] && data+=rpi0=true$'\n' # zero -[[ $BB == 0d ]] && data+=rpi3bplus=true$'\n' # 3B+ -echo "$data" > $dirshm/cpuinfo +$dirsettings/system.sh cpuinfo # wifi - on-board or usb wlandev=$( $dirsettings/networks.sh wlandevice ) @@ -26,7 +17,6 @@ if [[ -e /boot/expand ]]; then # run once partprobe $dev resize2fs $partition fi - ! grep -q onboardwireless=true $dirshm/cpuinfo && sed -i '/dtparam=krnbt=on/ d' /boot/config.txt fi if [[ -e /boot/backup.gz ]]; then diff --git a/srv/http/bash/xinitrc b/srv/http/bash/xinitrc index 7e46a1712..ef9a00246 100644 --- a/srv/http/bash/xinitrc +++ b/srv/http/bash/xinitrc @@ -22,10 +22,10 @@ matchbox-window-manager -use_cursor $cursor & scale=$( awk 'BEGIN { printf "%.2f", '$zoom/100' }' ) if [[ -e /usr/bin/firefox ]]; then - dirfirefox=/root/.mozilla/firefox - [[ ! -e $dirfirefox ]] && timeout 1 firefox --headless &> dev/null - profile=$( grep -m1 ^Default $dirfirefox/profiles.ini | cut -d= -f2 ) - fileuserjs=$dirfirefox/$profile/user.js + rm -rf /root/.mozilla + timeout 1 firefox --headless &> dev/null + profile=$( grep -m1 ^Default /root/.mozilla/firefox/profiles.ini | cut -d= -f2 ) + fileuserjs=/root/.mozilla/firefox/$profile/user.js if [[ $scale == 1.00 ]]; then rm -f $fileuserjs else diff --git a/srv/http/mpdlibrary.php b/srv/http/mpdlibrary.php index 1f2b13073..174b3101f 100644 --- a/srv/http/mpdlibrary.php +++ b/srv/http/mpdlibrary.php @@ -3,8 +3,8 @@ find, list, ls, search, track, webradio Album - /srv/http/data/mpd/album: album-artist^-file - /srv/http/data/mpd/albumbyartist: artist-album-file + /srv/http/data/mpd/album: album-artist-file + /srv/http/data/mpd/albumbyartist: artist-date-album-file track list: mpc ls -f %*% $path Artist mpc list artist > /srv/http/data/mpd/artist @@ -141,9 +141,13 @@ break; case 'list': $filemode = '/srv/http/data/mpd/'.$mode; - if ( $mode === 'album' && exec( 'grep "albumbyartist.*true" /srv/http/data/system/display.json' ) ) $filemode.= 'byartist'; - $lists = file( $filemode, FILE_IGNORE_NEW_LINES ); - htmlList( $lists ); + if ( $mode === 'album' ) { + $display = json_decode( file_get_contents( '/srv/http/data/system/display.json' ) ); + if ( $display->albumbyartist ) $filemode.= 'byartist'; + if ( $display->albumyear ) $filemode.= '-year'; + } + $lists = file( $filemode, FILE_IGNORE_NEW_LINES ); + if ( count( $lists ) ) htmlList( $lists ); break; case 'ls': if ( $mode !== 'album' ) { @@ -201,11 +205,9 @@ $files = []; $indexes = []; if ( $mode === 'search' ) { - $searchmode = 1; exec( "grep -ril --exclude-dir=img '".$string."' ".$dir." | sed 's|^".$dir."||'" , $files ); } else { - $searchmode = 0; $dir.= $string; exec( 'ls -1 "'.$dir.'" | grep -E -v "^img|\.jpg$|\.gif$"' , $lists ); @@ -273,8 +275,7 @@ function escape( $string ) { // for passing bash arguments return preg_replace( '/(["`])/', '\\\\\1', $string ); } function htmlDirectory( $lists ) { - global $gmode; - global $html; + global $gmode, $html; foreach( $lists as $list ) { $dir = basename( $list ); $each = ( object )[]; @@ -314,9 +315,7 @@ function htmlDirectory( $lists ) { function htmlFind( $lists, $f ) { // non-file 'find' command if ( ! count( $lists ) ) exit; - global $mode; - global $gmode; - global $html; + global $mode, $gmode, $html; $fL = count( $f ); foreach( $lists as $list ) { if ( $list === '' ) continue; @@ -368,13 +367,8 @@ function htmlFind( $lists, $f ) { // non-file 'find' command echo $html; } function htmlList( $lists ) { // non-file 'list' command - if ( ! count( $lists ) ) exit; - - global $mode; - global $gmode; - global $html; - if ( $mode === 'latest' ) $mode = 'album'; - if ( $mode !== 'album' ) { + global $mode, $gmode, $html; + if ( $mode !== 'album' && $mode !== 'latest' ) { foreach( $lists as $list ) { $data = explode( '^^', $list ); $index = strtoupper( $data[ 0 ] ); @@ -387,19 +381,31 @@ function htmlList( $lists ) { // non-file 'list' command '; } } else { + global $display; foreach( $lists as $list ) { $data = explode( '^^', $list ); $index = strtoupper( $data[ 0 ] ); $indexes[] = $index; - $path = $data[ 3 ]; + $path = end( $data ); if ( substr( $path, -4 ) === '.cue' ) $path = dirname( $path ); $coverfile = rawurlencode( '/mnt/MPD/'.$path.'/coverart.jpg' ); // replaced with icon on load error(faster than existing check) + $l1 = $data[ 1 ]; + $l2 = $data[ 2 ]; + $name = $l1; + if ( $display->albumyear ) { + $name = $data[ 3 ]; + $l2 = $l2 ? ( strlen( $l2 ) < 5 ? $l2 : date( 'Y', strtotime( $l2 ) ) ) : '...'; + $l2 .= '
'.$name; + } else if ( $display->albumbyartist ) { + $name = $l2; + } $html .= ''; } } @@ -411,9 +417,8 @@ function htmlList( $lists ) { // non-file 'list' command echo $html; } function htmlRadio( $subdirs, $files, $dir ) { - global $mode; - global $gmode; - global $html; + global $mode, $gmode, $html; + $searchmode = $mode === 'search'; if ( count( $subdirs ) ) { foreach( $subdirs as $subdir ) { $each = ( object )[]; @@ -496,9 +501,7 @@ function htmlRadio( $subdirs, $files, $dir ) { function htmlTrack( $lists, $f, $filemode = '', $string = '', $dirs = '' ) { // track list - no sort ($string: cuefile or search) if ( ! count( $lists ) ) exit; - global $mode; - global $gmode; - global $html; + global $mode, $gmode, $html; $fL = count( $f ); foreach( $lists as $list ) { if ( $list === '' ) continue; diff --git a/srv/http/mpdplaylist.php b/srv/http/mpdplaylist.php index 169447b09..502ad355e 100644 --- a/srv/http/mpdplaylist.php +++ b/srv/http/mpdplaylist.php @@ -134,8 +134,7 @@ function htmlSavedPlaylist() { ], JSON_NUMERIC_CHECK ); } function htmlTrack( $lists, $plname = '' ) { - global $headers; - global $add; + global $headers, $add; $count = count( $lists ); if ( ! $count ) exit( '-1' ); diff --git a/srv/http/settings.php b/srv/http/settings.php index 945e45603..40672bcda 100644 --- a/srv/http/settings.php +++ b/srv/http/settings.php @@ -124,8 +124,7 @@ function htmlSetting( $data ) { return; } - global $page; - global $id_data; + global $page, $id_data; $id = $data[ 'id' ]; $iddata = $id_data[ $id ]; $name = $iddata[ 'name' ]; diff --git a/srv/http/settings/player.php b/srv/http/settings/player.php index 74fbedb0c..3c0c736b5 100644 --- a/srv/http/settings/player.php +++ b/srv/http/settings/player.php @@ -3,7 +3,7 @@ $id_data = [ 'audiooutput' => [ 'name' => 'Device', 'setting' => 'none' ] , 'autoupdate' => [ 'name' => 'Library Auto Update', 'sub' => 'auto_update', 'setting' => false ] - , 'btreceiver' => [ 'name' => 'Bluetooth', 'sub' => 'bluetoothctl', 'setting' => 'custom', 'status' => true ] + , 'btreceiver' => [ 'name' => 'Bluetooth', 'sub' => 'bluealsa', 'setting' => 'custom', 'status' => true ] , 'buffer' => [ 'name' => 'Buffer - Audio', 'sub' => 'audio_buffer' ] , 'crossfade' => [ 'name' => 'Cross-Fading', 'sub' => 'crossfade' ] , 'custom' => [ 'name' => "User's Configurations", 'sub' => 'custom' ] diff --git a/srv/http/settings/system.php b/srv/http/settings/system.php index b083f8f31..2a2f60ac0 100644 --- a/srv/http/settings/system.php +++ b/srv/http/settings/system.php @@ -8,7 +8,7 @@ , 'backup' => [ 'name' => 'Backup', 'setting' => 'none' ] , 'bluetooth' => [ 'name' => 'Bluetooth', 'sub' => 'bluez', 'status' => true ] , 'hddsleep' => [ 'name' => 'Hard Drive Sleep' ] - , 'hdmi' => [ 'name' => 'HDMI', 'setting' => false ] + , 'hdmi' => [ 'name' => 'HDMI', 'sub' => 'hot plug', 'setting' => false ] , 'hostname' => [ 'name' => 'Player Name', 'setting' => 'none' ] , 'lcdchar' => [ 'name' => 'Character LCD', 'sub' => 'HD44780' ] , 'mpdoled' => [ 'name' => 'Spectrum OLED' ]