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 ) {
` ).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?' - +' *
Various values in tracks *
Various values in tracksRotation | |
'+ list +'
"
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' => '"
in Wi-Fi name and password.
-
-(Access points with 1 bar icon I^wifi1^I might be unstable.)' ) )?>"
in Wi-Fi name and password.
+ · Access points with 1 bar icon I^wifi1^I might be unstable.' ) )?>| 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 intompd.conf .' + 'label' => "User's Configurations" + , 'sublabel' => 'custom' + , 'id' => 'custom' + , 'help' => 'Insert custom configurations intompd.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 @@ =( i( 'power red' ) )?> Off Sequence
- =( i( 'undo' ) )?>Undo=( i( 'save' ) )?>Save + =( i( 'undo' ) )?>Undo=( i( 'save' ) )?>Save
+mkdir -p "/mnt/MPD/NAS/NAME " mount -t cifs "//SERVER_IP /SHARENAME " "/mnt/MPD/NAS/NAME " \ -o noauto,username=USER ,password=PASSWORD ,uid==( exec( 'id -u mpd' ) )?>,gid==( exec( 'id -g mpd' ) )?>,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