[How-To] MPD-cloudshell and MPD extras

Hello to everyone,

I’m new to this forum and also new to DietPi (it’s absolutely fantastic) but would like to post a little “How-To” about how to modify “dietpi-cloudshell” for MPD (Music Player Daemon Internet Radio).

First of all I modified Scene 4 to show the following MPD information on my LCD display:
(sorry I’m too lazy to create a new scene :roll_eyes: )

MPD current Volume %
MPD current Channel / total available Channels
MPD current Station - Artist - Song

example on [scene: 4]:

Sat 29/09/18 - 17:37
MPD Internet Radio:
Volume : 76%
Channel: 59/59
Current Station - Song:
ANTENNE VORARLBERG - Lounge: Milan Euringer and Tube & Berger - Lovebreak

Note: “MPD current Station - Artist - Song” might take more than one line to show, this is why I left the last three lines empty

I also modified another scene (5) to have just a single page for essential system information (wifi SSID added):

example on [scene 5]

Sat 29/09/18 - 17:40
System information:
IP : 192.168.1.76
Signal : -67%
SSID : default
Cpu : 35.6929%
Temp : 48’c
SD space: 23%
Memory Usage: 46/433MB

All the remaining scenes could be deactivated.

First of all, you should backup the original cloudshell file, just in case you may want to go back to the original version:

sudo cp /DietPi/dietpi/dietpi-cloudshell /DietPi/dietpi/dietpi-cloudshell.back

This is my “/DietPi/dietpi/dietpi-cloudshell” file modified:

#!/bin/bash
{
	#////////////////////////////////////
	# DietPi Cloudshell MPD mod - Scenes 4 & 5 (disable all the others)
	#
	#////////////////////////////////////
	# Created by Daniel Knight / daniel.knight@dietpi.com / dietpi.com
	# Modifies by pilovis - Italy
	#////////////////////////////////////
	#
	# Info:
	# - System Stats for Cloudshell (or monitor/terminal)
	#
	# Usage:
	# dietpi-cloudshell				= Config Menu
	# dietpi-cloudshell 1			= Run
	# dietpi-cloudshell 2			= Run + Skip intro
	#////////////////////////////////////

	#Import DietPi-Globals ---------------------------------------------------------------
	. /DietPi/dietpi/func/dietpi-globals
	G_CHECK_ROOT_USER
	export G_PROGRAM_NAME='DietPi-Cloudshell'
	G_INIT
	#Import DietPi-Globals ---------------------------------------------------------------

	#Grab Input (valid interger)
	INPUT=0
	disable_error=1 G_CHECK_VALIDINT $1 && INPUT=$1

	#Version
	DIETPI_CLOUDSHELL_VERSION=MPD_1.0

	#/tmp/.* files used throughout this script.
	FP_TEMP="/tmp/$G_PROGRAM_NAME/.tmp"

	BLANK_SCREEN_ACTIVE=0
	BLANK_SCREEN_AT_SPECIFIC_TIME_ENABLED=0
	BLANK_SCREEN_TIME_HOUR_START=0
	BLANK_SCREEN_TIME_HOUR_END=0

	#This will only work if dietpi-cloudshell was started by autostart (login script), as the setterm power options can only be applied when the command originates from the same terminal (no redirects).
	RUN_BLANK_SCREEN_AT_SPECIFIC_TIME(){

		local current_hour=$(date +%-H)

		#Turn screen off
		if (( ! $BLANK_SCREEN_ACTIVE )); then

			if (( $BLANK_SCREEN_TIME_HOUR_START == $current_hour )); then

				clear
				echo -e '\n\nScreen will be powered down in under 1 minute\n'
				setterm --blank 1 --powersave on &> /dev/tty1 #blank after 1 minute as force requires a poke to bring it back up.
				BLANK_SCREEN_ACTIVE=1

			fi

		#Turn screen on
		elif (( $BLANK_SCREEN_TIME_HOUR_END == $current_hour )); then

			Disable_Screen_Blanking

		fi

	}

	Disable_Screen_Blanking(){

		setterm --blank poke &> /dev/tty1
		setterm --reset &> /dev/tty1
		setterm --blank 0 --powersave off &> /dev/tty1
		BLANK_SCREEN_ACTIVE=0

	}

	#BC does not allow for printing leading zeros.
	BC_ADD_LEADING_ZERO(){

		#$1 = string input
		local return_value=$1

		#BC - Add leading zero to start of .* string.
		# +0
		if [[ ${return_value:0:1} == '.' ]]; then

			return_value="0$return_value"


		# -0
		elif [[ ${return_value:0:2} == '-.' ]]; then

			return_value=$(sed 's/^-./-0./' <<< "$return_value")

		fi

		echo "$return_value"

	}

	#Converts a byte int to string, in human readable byte format.
	BYTE_PRINT_CONVERSION(){

		local return_value=0
		local decimal_count=1

		#$1=byte value

		# - KB
		if (( $1 < 1048576 )); then

			return_value="$(echo "scale=$decimal_count; $1 / 1024" | bc -l ) KB"

		# - MB
		elif (( $1 < 1073741824 )); then

			return_value="$(echo "scale=$decimal_count; $1 / 1024 / 1024" | bc -l ) MB"

		# - GB
		else

			return_value="$(echo "scale=$decimal_count; $1 / 1024 / 1024 / 1024" | bc -l ) GB"

		fi

		#BC - Add leading zero to start of .* string.
		return_value=$(BC_ADD_LEADING_ZERO "$return_value")

		echo "$return_value"

	}

	#Converts a byte int to string, in human readable bit format.
    # - for network data transmission rate (LAN, WLAN, ...)
	# - 1MB = 8Mbit | 1Mbit = 0.125MB
    BIT_PRINT_CONVERSION(){

		local return_value=0
		local decimal_count=1

		#$1=byte value

		# - Kbit
		if (( $1 < 1000000 )); then

			return_value="$(echo "scale=$decimal_count; $1 * 8 / 1000" | bc -l) Kbit"

		# - MBit
		elif (( $1 < 1000000000 )); then

			return_value="$(echo "scale=$decimal_count; $1  * 8 / 1000 / 1000" | bc -l) Mbit"

		# - GBit
		else

			return_value="$(echo "scale=$decimal_count; $1 * 8 / 1000 / 1000 / 1000" | bc -l) Gbit"

		fi

		#BC - Add leading zero to start of .* string.
		return_value=$(BC_ADD_LEADING_ZERO "$return_value")

		echo "$return_value"

    }

	Init_Term_Options(){

		# - Set large font 1st (480x320+)
		setfont /usr/share/consolefonts/Uni3-TerminusBold32x16

		# - set small font if insufficent number of lines (320x240)
		if (( $(tput lines) < 10 )); then

			setfont /usr/share/consolefonts/Uni3-TerminusBold24x12.psf

		fi

		#Disable screen blanking on tty1 initially
		Disable_Screen_Blanking

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# Colours
	#/////////////////////////////////////////////////////////////////////////////////////
	C_RESET='\e[0m'
	C_REVERSE='\e[7m'

	#C_BOLD makes normal text "brighter"
	C_BOLD='\e[1m'

	#Colour array
	#0 WHITE
	#1 RED
	#2 GREEN
	#3 YELLOW
	#4 BLUE
	#5 PURPLE
	#6 CYAN
	#7 TEST
	aCOLOUR=(

		'\e[39m'
		'\e[31m'
		'\e[32m'
		'\e[33m'
		'\e[34m'
		'\e[35m'
		'\e[36m'
		'\e[93m'

	)

	#user colour
	USER_COLOUR_INDEX=3

	C_PERCENT_GRAPH=0
	Percent_To_Graph(){

		#$1 = int/float 0-100
		#$C_PERCENT_GRAPH = return text

		#Convert to int
		local input_value=$(echo $1 | cut -d. -f1)

		#Cap input value
		if (( $input_value > 100 )); then

			input_value=100

		elif (( $input_value < 0 )); then

			input_value=0

		fi

		#Work out a percentage based graph
		#18 step split (18 / 100)
		if (( $input_value >= 95 )); then

			C_PERCENT_GRAPH=" $input_value% [$C_REVERSE${aCOLOUR[1]}------WARNING-----$C_RESET]"

		elif (( $input_value >= 90 )); then

			C_PERCENT_GRAPH=" $input_value% [$C_REVERSE${aCOLOUR[1]}-----------------$C_RESET-]"

		elif (( $input_value >= 88 )); then

			C_PERCENT_GRAPH=" $input_value% [$C_REVERSE${aCOLOUR[1]}----------------$C_RESET--]"

		elif (( $input_value >= 82 )); then

			C_PERCENT_GRAPH=" $input_value% [$C_REVERSE${aCOLOUR[1]}---------------$C_RESET---]"

		elif (( $input_value >= 76 )); then

			C_PERCENT_GRAPH=" $input_value% [$C_REVERSE${aCOLOUR[3]}--------------$C_RESET----]"

		elif (( $input_value >= 70 )); then

			C_PERCENT_GRAPH=" $input_value% [$C_REVERSE${aCOLOUR[3]}-------------$C_RESET-----]"

		elif (( $input_value >= 64 )); then

			C_PERCENT_GRAPH=" $input_value% [$C_REVERSE${aCOLOUR[3]}------------$C_RESET------]"

		elif (( $input_value >= 56 )); then

			C_PERCENT_GRAPH=" $input_value% [$C_REVERSE${aCOLOUR[3]}-----------$C_RESET-------]"

		elif (( $input_value >= 50 )); then

			C_PERCENT_GRAPH=" $input_value% [$C_REVERSE${aCOLOUR[3]}----------$C_RESET--------]"

		elif (( $input_value >= 44 )); then

			C_PERCENT_GRAPH=" $input_value% [$C_REVERSE${aCOLOUR[3]}---------$C_RESET---------]"

		elif (( $input_value >= 38 )); then

			C_PERCENT_GRAPH=" $input_value% [$C_REVERSE${aCOLOUR[2]}--------$C_RESET----------]"

		elif (( $input_value >= 32 )); then

			C_PERCENT_GRAPH=" $input_value% [$C_REVERSE${aCOLOUR[2]}-------$C_RESET-----------]"

		elif (( $input_value >= 26 )); then

			C_PERCENT_GRAPH=" $input_value% [$C_REVERSE${aCOLOUR[2]}------$C_RESET------------]"

		elif (( $input_value >= 20 )); then

			C_PERCENT_GRAPH=" $input_value% [$C_REVERSE${aCOLOUR[2]}-----$C_RESET-------------]"

		elif (( $input_value >= 15 )); then

			C_PERCENT_GRAPH=" $input_value% [$C_REVERSE${aCOLOUR[2]}----$C_RESET--------------]"

		elif (( $input_value >= 10 )); then

			C_PERCENT_GRAPH=" $input_value% [$C_REVERSE${aCOLOUR[2]}---$C_RESET---------------]"

		elif (( $input_value >= 5 )); then

			C_PERCENT_GRAPH=" $input_value%  [$C_REVERSE${aCOLOUR[2]}--$C_RESET----------------]"

		else

			C_PERCENT_GRAPH=" $input_value%  [$C_REVERSE${aCOLOUR[2]}-$C_RESET-----------------]"

		fi

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# Obtain Stat Data
	#/////////////////////////////////////////////////////////////////////////////////////
	TEMPERATURE_CONVERSION_VALUE=0
	Obtain_Temperature_Conversion(){

		if (( $TEMPERATURE_OUTPUT_TYPE == 0 )); then

			TEMPERATURE_CONVERSION_VALUE=$(awk "BEGIN {printf \"%.0f\",$TEMPERATURE_CONVERSION_VALUE * 1.8 + 32"})
			TEMPERATURE_CONVERSION_VALUE+="'f"

		else

			TEMPERATURE_CONVERSION_VALUE+="'c"

		fi

	}

	DATE_TIME=0
	Obtain_DATE_TIME(){

		DATE_TIME=$(date +"%a %x - %R")

	}

	UPTIME=0
	Obtain_UPTIME(){

		local fSeconds=$(awk '{print $1}' <<< $(</proc/uptime))

		local seconds=${fSeconds%.*}
		local minutes=0
		local hours=0
		local days=0

		while (( $seconds >= 60 )); do

			((minutes++))
			seconds=$(( $seconds - 60 ))

		done

		while (( $minutes >= 60 )); do

			((hours++))
			minutes=$(( $minutes - 60 ))

		done

		while (( $hours >= 24 )); do

			((days++))
			hours=$(( $hours - 24 ))

		done

		UPTIME="Uptime: $days Day, $hours Hour"

	}

	#CPU
	CPU_GOV=0
	CPU_TEMP=0
	C_CPUTEMP=0
	CPU_FREQ_1=0
	CPU_FREQ_2=0
	CPU_USAGE=0
	CPU_TOTALPROCESSES=0
	Obtain_CPU(){

		CPU_TOTALPROCESSES=$(( $(ps --ppid 2 -p 2 --deselect | wc -l) - 2 )) # - ps process and descriptions.
		CPU_GOV=$(</sys/devices/system/cpu/cpu0/cpufreq/scaling_governor)
		CPU_TEMP=$(G_OBTAIN_CPU_TEMP)

		if disable_error=1 G_CHECK_VALIDINT $CPU_TEMP; then

			#Obtain colour for temps
			if (( $CPU_TEMP >= 65 )); then

				C_CPUTEMP=${aCOLOUR[1]}

			elif (( $CPU_TEMP >= 50 )); then

				C_CPUTEMP=${aCOLOUR[3]}

			elif (( $CPU_TEMP >= 35 )); then

				C_CPUTEMP=${aCOLOUR[2]}

			else

				C_CPUTEMP=${aCOLOUR[4]}

			fi

			#Set 'c or 'f output
			TEMPERATURE_CONVERSION_VALUE=$CPU_TEMP
			Obtain_Temperature_Conversion
			CPU_TEMP=$TEMPERATURE_CONVERSION_VALUE

		fi

		CPU_FREQ_1=$(( $(</sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq) / 1000 ))
		CPU_FREQ_2='N/A'

		#Unique additional freq readout for Odroid XU4 (octo, 2nd quad set)
		if (( $G_HW_MODEL == 11 )); then

			CPU_FREQ_2=$(( $(</sys/devices/system/cpu/cpu4/cpufreq/scaling_cur_freq) / 1000 ))

		fi

		CPU_USAGE=0

		# PS (inaccurate)
		while read -r line
		do

			CPU_USAGE=$( echo "scale=1;$CPU_USAGE + $line" | bc -l )

		done <<< "$(ps -axo %cpu | sed '1d' | sed 's/ //')"

		#ps returns usage of each core, so we devide the total by #n cores
		CPU_USAGE=$(echo "scale=0;$CPU_USAGE / $G_HW_CPU_CORES" | bc -l )

		# TOP (accurate)
		# Fails to output in low screen res (https://github.com/Fourdee/DietPi/issues/203#issuecomment-189711968)
		# CPU_USAGE=$(BC_ADD_LEADING_ZERO "$(echo "scale=1; 100 - $(top -b -n 1 | grep '%Cpu(s):' | awk '{print $8}')" | bc -l)")

		#convert to interger and graph it
		Percent_To_Graph $CPU_USAGE
		CPU_USAGE=$C_PERCENT_GRAPH

	}

	#Storage
	# - array
	MAX_STORAGE=6
	STORAGE_TOTAL=()
	STORAGE_USED=()
	STORAGE_FREE=()
	STORAGE_PERCENT=()
	STORAGE_PATH=()
	STORAGE_NAME=()

	Init_STORAGE(){

		for ((i=0; i<$MAX_STORAGE; i++))
		do

			STORAGE_TOTAL[$i]='N/A'
			STORAGE_USED[$i]='N/A'
			STORAGE_FREE[$i]='N/A'
			STORAGE_PERCENT[$i]=' Not installed'
			STORAGE_NAME[$i]=0

			# 0 reserved for flash storage
			if (( $i == 0 )); then

				STORAGE_PATH[$i]='/'
				STORAGE_NAME[$i]='Flash/RootFS Storage:    '

			else

				STORAGE_PATH[$i]="/mnt/usb_$i"
				STORAGE_NAME[$i]="Storage $i:               "

			fi

		done

	}

	Destroy_STORAGE(){

		unset STORAGE_TOTAL
		unset STORAGE_USED
		unset STORAGE_FREE
		unset STORAGE_PERCENT
		unset STORAGE_PATH
		unset STORAGE_NAME

	}

	# $1 $2 = Range of indexs to update (eg: 0-1)
	Obtain_STORAGE(){

		local index_start=$1
		local index_end=$2


		#df will endless hang when NFS server is down: https://github.com/Fourdee/DietPi/issues/395
		# - So lets run it as another thread so we can kill it if it hangs.
		local df_failed=0
		rm $FP_TEMP
		df -Ph > $FP_TEMP &

		# - Wait X seconds before terminating the df thread
		local max_seconds=4
		local current_seconds=0
		while [[ ! -f $FP_TEMP ]]
		do

			#kill
			if (( $current_seconds >= $max_seconds )); then

				G_DIETPI-NOTIFY 1 'DF failed, unable to obtain drive data'
				sleep 2

				killall -w df

				df_failed=1

				echo -e "$(date) | df failed to respond" >> /var/log/dietpi-cloudshell.log

				break

			else

				sleep 1
				((current_seconds++))

			fi

		done

		if (( $df_failed )); then

			for ((i=$index_start; i<=$index_end; i++))
			do

				STORAGE_PERCENT[$i]="${STORAGE_PATH[$i]}"
				STORAGE_FREE[$i]='DF failed'

			done

		else

			for ((i=$index_start; i<=$index_end; i++))
			do

				if grep -q "${STORAGE_PATH[$i]}\$" $FP_TEMP; then

					STORAGE_TOTAL[$i]=$(grep -m1 "${STORAGE_PATH[$i]}\$" $FP_TEMP | awk '{print $2}'); STORAGE_TOTAL[$i]+='B'
					STORAGE_USED[$i]=$(grep -m1 "${STORAGE_PATH[$i]}\$" $FP_TEMP | awk '{print $3}'); STORAGE_USED[$i]+='B'
					STORAGE_FREE[$i]=$(grep -m1 "${STORAGE_PATH[$i]}\$" $FP_TEMP | awk '{print $4}'); STORAGE_FREE[$i]+='B'
					STORAGE_PERCENT[$i]=$(grep -m1 "${STORAGE_PATH[$i]}\$" $FP_TEMP | awk '{print $5}' | sed 's/%//g')

					Percent_To_Graph ${STORAGE_PERCENT[$i]}
					STORAGE_PERCENT[$i]=$C_PERCENT_GRAPH

				else

					STORAGE_PERCENT[$i]="${STORAGE_PATH[$i]}"
					STORAGE_FREE[$i]='Mount not active'

				fi

			done

		fi

	}

	#MPD - Scene 4 modified for MPD-Cloudshell
	MPD_CURRENT_SONG=0
	MPD_STATION=0
	MPD_VOLUME=0
	Obtain_MPDINFO(){

		#MPD current song
		MPD_CURRENT_SONG=$(mpc current)

		#MPD current audio volume
		MPD_VOLUME=$(mpc status | sed -n '/volume/p' | cut -c8-11 | sed 's/^[ \t]*//')

		#MPD current station
		MPD_STATION=$(mpc | /bin/grep "#" | /usr/bin/awk '{print $2}' | sed s/#//)

	}

	#System Information - Scene 5 modified for MPD-Cloudshell
	NETWORK_DETAILS_ADAPTER='eth0'
	NETWORK_DETAILS_IP_INT=0
	NETWORK_DETAILS_SSID=0
	NETWORK_DETAILS_SIGNAL_STRENGTH=0
	RAM=0
	CPU_USAGE=0
	FREE_SD_SPACE=0

	Obtain_NETWORK_DETAILS(){

		#Cpu usage
		CPU_USAGE=$(grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {print usage "%"}')

		#Active network adapater.
		NETWORK_DETAILS_ADAPTER=$(sed -n 3p /DietPi/dietpi/.network)

		#Free SD space %
		FREE_SD_SPACE=$(df -lh | awk '{if ($6 == "/") { print $5 }}' | head -1)

		#IP & wifi SSID
		NETWORK_DETAILS_IP_INT=$(sed -n 4p /DietPi/dietpi/.network)
		NETWORK_DETAILS_SSID=$(iwgetid -r)

		# Wifi Signal
		NETWORK_DETAILS_SIGNAL_STRENGTH="$(iwconfig $NETWORK_DETAILS_ADAPTER | grep -m1 'Signal level=' | awk '{ print $4 }' | sed 's/level=//g' | cut -f1 -d "/")%"

		#RAM usage
		RAM="$(free -m | awk 'NR==2{printf "Memory Usage: %s/%sMB \n", $3,$2,$3 }')"

}

	#Network Usage (all values are in bytes)
	NETWORK_USAGE_TOTAL_CURRENT_SENT=0
	NETWORK_USAGE_TOTAL_CURRENT_RECIEVED=0

	NETWORK_USAGE_NOW_CURRENT_SENT=0
	NETWORK_USAGE_NOW_CURRENT_RECIEVED=0
	NETWORK_USAGE_NOW_INIT=0
	NETWORK_USAGE_SECONDS_SINCE_LAST_UPDATE=0

	NETWORK_USAGE_DAY_CURRENT_SENT=0
	NETWORK_USAGE_DAY_CURRENT_RECIEVED=0
	NETWORK_USAGE_DAY_PREVIOUS_SENT=0
	NETWORK_USAGE_DAY_PREVIOUS_RECIEVED=0
	NETWORK_USAGE_DAY_OF_MONTH=-1

	Obtain_NETWORK_USAGE(){

		local network_usage_current_recieved=$(</sys/class/net/$NETWORK_DETAILS_ADAPTER/statistics/rx_bytes)
		local network_usage_current_sent=$(</sys/class/net/$NETWORK_DETAILS_ADAPTER/statistics/tx_bytes)

		#Check for valid integer scrapes, before running calculations: https://dietpi.com/forum/t/dietpi-cloudshell-syntax-error-help/368/5 | https://github.com/Fourdee/DietPi/issues/355
		if disable_error=1 G_CHECK_VALIDINT $network_usage_current_recieved && disable_error=1 G_CHECK_VALIDINT $network_usage_current_sent; then

			#Store previous totals
			local total_previous_sent=$NETWORK_USAGE_TOTAL_CURRENT_SENT
			local total_previous_recieved=$NETWORK_USAGE_TOTAL_CURRENT_RECIEVED

			#Update current totals
			NETWORK_USAGE_TOTAL_CURRENT_RECIEVED=$network_usage_current_recieved
			NETWORK_USAGE_TOTAL_CURRENT_SENT=$network_usage_current_sent

			#Current usage
			# - Work out seconds since last update
			local seconds_since_last_update=$(( $(date +%s) - $NETWORK_USAGE_SECONDS_SINCE_LAST_UPDATE ))

			# - Init - Override current usage to 0, on first run of scene.
			if (( $NETWORK_USAGE_NOW_INIT == 0 )); then

				NETWORK_USAGE_NOW_CURRENT_SENT=0
				NETWORK_USAGE_NOW_CURRENT_RECIEVED=0

				NETWORK_USAGE_NOW_INIT=1

			# - Obtain current usage
			else

				NETWORK_USAGE_NOW_CURRENT_SENT=$(( ( $NETWORK_USAGE_TOTAL_CURRENT_SENT - $total_previous_sent ) / $seconds_since_last_update ))
				NETWORK_USAGE_NOW_CURRENT_RECIEVED=$(( ( $NETWORK_USAGE_TOTAL_CURRENT_RECIEVED - $total_previous_recieved ) / $seconds_since_last_update ))

			fi

			# - Update timestamp
			NETWORK_USAGE_SECONDS_SINCE_LAST_UPDATE=$(date +%s)

			#Usage today
			# - Has the day changed? Also runs on init.
			#	String if statement, to prevent "leading zero integer error" from $(date): https://github.com/Fourdee/DietPi/issues/272
			local dayofmonth=$(date +"%d")
			if [[ $NETWORK_USAGE_DAY_OF_MONTH != $dayofmonth ]]; then

				#Update previous day values to current
				NETWORK_USAGE_DAY_PREVIOUS_SENT=$NETWORK_USAGE_TOTAL_CURRENT_SENT
				NETWORK_USAGE_DAY_PREVIOUS_RECIEVED=$NETWORK_USAGE_TOTAL_CURRENT_RECIEVED
				NETWORK_USAGE_DAY_OF_MONTH=$dayofmonth

			fi

			# - Work out todays usage
			NETWORK_USAGE_DAY_CURRENT_SENT=$(( $NETWORK_USAGE_TOTAL_CURRENT_SENT - $NETWORK_USAGE_DAY_PREVIOUS_SENT ))
			NETWORK_USAGE_DAY_CURRENT_RECIEVED=$(( $NETWORK_USAGE_TOTAL_CURRENT_RECIEVED - $NETWORK_USAGE_DAY_PREVIOUS_RECIEVED ))

		fi

	}

	#Memory
	MEMORY_TOTAL=0
	MEMORY_FREE=0
	MEMORY_USED=0
	MEMORY_CACHED=0
	MEMORY_PERCENT=0
	MEMORY_SWAPTOTAL=0
	MEMORY_SWAPUSED=0
	MEMORY_SWAPFREE=0
	MEMORY_SWAPERCENT=0
	Obtain_MEMORY(){

		#Write to temp
		free -m > $FP_TEMP

		#RAM MB
		MEMORY_TOTAL=$(grep -m1 'Mem: ' $FP_TEMP | awk '{print $2}')
		#MEMORY_CACHED=$(grep -m1 'Mem: ' $FP_TEMP | awk '{print $6}')
		MEMORY_USED=$(( $(grep -m1 'Mem: ' $FP_TEMP | awk '{print $3}') ))
		MEMORY_FREE=$(( $(grep -m1 'Mem: ' $FP_TEMP | awk '{print $7}') ))
		MEMORY_PERCENT=$(echo | awk "{print $MEMORY_USED / $MEMORY_TOTAL * 100}")

		#convert to interger and graph it
		Percent_To_Graph $MEMORY_PERCENT
		MEMORY_PERCENT=$C_PERCENT_GRAPH

		#SWAP MB
		MEMORY_SWAPTOTAL=$(grep -m1 'Swap: ' $FP_TEMP | awk '{print $2}')
		# - Swap available and active
		if (( $MEMORY_SWAPTOTAL > 0 )); then

			MEMORY_SWAPUSED=$(grep -m1 'Swap: ' $FP_TEMP | awk '{print $3}')
			MEMORY_SWAPFREE=$(grep -m1 'Swap: ' $FP_TEMP | awk '{print $4}')
			MEMORY_SWAPERCENT=$( echo | awk "{print $MEMORY_SWAPUSED / $MEMORY_SWAPTOTAL * 100}")

			#convert to interger and graph it
			Percent_To_Graph $MEMORY_SWAPERCENT
			MEMORY_SWAPERCENT=$C_PERCENT_GRAPH

		else

			MEMORY_SWAPERCENT=' Disabled'

		fi

	}

	#PI-HOLE STATS!
	PIHOLE_QUERY_COUNT=0
	PIHOLE_TOTAL_ADS=0
	PIHOLE_PERCENT_ADS=0
	PIHOLE_TOTAL_DOMAINS=0
	PIHOLE_LAST_DOMAIN_BLOCKED=0
	Obtain_PIHOLE(){

		local pihole_log_file='/var/log/pihole.log'

		#Lets pull the total number of blocked domains only once during 1st run, its quite cpu intensive.
		if (( $PIHOLE_TOTAL_DOMAINS == 0 )); then

			if [[ -f /etc/pihole/gravity.list ]]; then

				PIHOLE_TOTAL_DOMAINS=$(wc -l /etc/pihole/gravity.list | awk '{print $1}')

			else

				PIHOLE_TOTAL_DOMAINS='Not Installed'

			fi

		fi

		local today=$(date +'%b %e')

		PIHOLE_QUERY_COUNT=$(grep "$today" $pihole_log_file | awk '/query/ {print $7}' | wc -l)
		#Prevent / 0 on percentage
		if (( $PIHOLE_QUERY_COUNT <= 0 )); then

			PIHOLE_QUERY_COUNT=1

		fi

		PIHOLE_TOTAL_ADS=$(grep "$today" $pihole_log_file | awk '/\/etc\/pihole\/gravity.list/ {print $7}' | wc -l)
		PIHOLE_PERCENT_ADS=$(echo | awk "{print $PIHOLE_TOTAL_ADS / $PIHOLE_QUERY_COUNT * 100}")

		#convert to interger and graph it
		Percent_To_Graph $PIHOLE_PERCENT_ADS
		PIHOLE_PERCENT_ADS=$C_PERCENT_GRAPH

		#Get last blocked domain
		if (( $PIHOLE_TOTAL_ADS == 0 )); then

			PIHOLE_LAST_DOMAIN_BLOCKED='None'

		else

			PIHOLE_LAST_DOMAIN_BLOCKED=$(tac /var/log/pihole.log | grep -m1 'gravity.list' | awk '{print $6}' | cut -c 1-24 )

		fi

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# Scene Settings
	#/////////////////////////////////////////////////////////////////////////////////////
	RUN_INTRO=0
	if (( $INPUT == 1 )); then

		RUN_INTRO=1

	fi

	#SCENE INDEXS
	SCENE_CURRENT=2
	MAX_SCENES=9

	#Refresh rate (every X seconds)
	REFRESH_RATE=5

	#0='f | 1='c
	TEMPERATURE_OUTPUT_TYPE=1

	#0=bit (Mbit) | 1=byte (MB)
	NETWORK_USAGE_CURRENT_OUTPUT_TYPE=0

	#Enabled Scenes
	aEnabledScenes=()
	for ((i=0; i<$MAX_SCENES; i++))
	do

		aEnabledScenes[$i]=1

	done

	#/////////////////////////////////////////////////////////////////////////////////////
	# Scene Print / Update
	#/////////////////////////////////////////////////////////////////////////////////////

	Run_Intro(){

	   #'--------------------------'
		clear

		local aAnimation=(

			'                          '
			'i         -              c'
			'P  i      -            c l'
			't  P  i   -          c l o'
			'e  t  P  i-        c l o u'
			'i  e  t Pi-    c l o u d s'
			'D  i  etPi-  c l o u d s h'
			'  D  ietPi-c l o u d s h e'
			'    DietPi-cl o u d s h e '
			'    DietPi-clou d s h e l '
			'    DietPi-clouds h e l l '
			'    DietPi-cloudshe l l   '
			'    DietPi-cloudshell     '

		)

		local aBar=(

			' '
			'  '
			'    '
			'       '
			'         '
			'            '
			'               '
			'                 '
			'                    '
			'                      '
			'                        '
			'                         '
			'                          '

		)

		for ((i=0; i<${#aAnimation[@]}; i++))
		do

			clear
			echo -e "$C_RESET"
			echo -e '\n\n'
			echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}${aAnimation[$i]}"
			echo -e "$C_RESET          v$DIETPI_CLOUDSHELL_VERSION"
			echo -e '\n       Loading...'
			echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}$C_REVERSE${aBar[$i]}"

			sleep 0.2

		done

		#delete[] array
		unset aAnimation
		unset aBar

		sleep 0.1

	}

	#Top banner
	BANNER_PRINT=0
	BANNER_MODE=0
	Update_Banner(){

		#Banner Modes
		if (( $BANNER_MODE == 0 )); then

		#BANNER_PRINT="Lovisolo P.M. -  2018"
			Obtain_DATE_TIME
			BANNER_PRINT=$DATE_TIME

		elif (( $BANNER_MODE == 1 )); then

			Obtain_DATE_TIME
			BANNER_PRINT=$DATE_TIME

		elif (( $BANNER_MODE == 2 )); then

			Obtain_UPTIME
			BANNER_PRINT=$UPTIME

		fi

		#Set next index
		((BANNER_MODE++))

		#Cap
		if (( $BANNER_MODE >= 3 )); then

			#BANNER_MODE=0
			Obtain_DATE_TIME
			BANNER_PRINT=$DATE_TIME
		fi

	}

	#CPU
	Update_Scene_0(){

		#Update data
		Obtain_CPU

		#Clear screen
		clear

		#Banner
		echo -e "$C_RESET $BANNER_PRINT"
		#
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}$C_REVERSE CPU Usage:               "
		echo -e "$C_RESET$CPU_USAGE"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}$C_REVERSE CPU Stats:               "
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Temp      ${aCOLOUR[$USER_COLOUR_INDEX]}:$C_RESET  $C_CPUTEMP$CPU_TEMP"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Processes ${aCOLOUR[$USER_COLOUR_INDEX]}:$C_RESET  $CPU_TOTALPROCESSES"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Governor  ${aCOLOUR[$USER_COLOUR_INDEX]}:$C_RESET  $CPU_GOV"

		#XU3/4 unique octo quad sets
		if (( $G_HW_MODEL == 11 )); then

			echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Freq 0-3  ${aCOLOUR[$USER_COLOUR_INDEX]}:$C_RESET  $CPU_FREQ_1 mhz"
			echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Freq 4-7  ${aCOLOUR[$USER_COLOUR_INDEX]}:$C_RESET  $CPU_FREQ_2 mhz"

		#Generic CPU hardware
		else

			echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Freq      ${aCOLOUR[$USER_COLOUR_INDEX]}:$C_RESET  $CPU_FREQ_1 mhz"

		fi

	}

	#$1 $2 = Storage index's to update and display (must be a range of 1 , eg: 0-1 1-2 3-4)
	Update_Scene_1(){

		local index_1=$1
		local index_2=$2

		#Update data
		Obtain_STORAGE $index_1 $index_2

		#Clear screen
		clear

		#Banner
		echo -e "$C_RESET $BANNER_PRINT"
		#
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}$C_REVERSE ${STORAGE_NAME[$index_1]}"
		echo -e "$C_RESET${STORAGE_PERCENT[$index_1]}"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Used: $C_RESET${STORAGE_USED[$index_1]} / ${STORAGE_TOTAL[$index_1]}"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Free: $C_RESET${STORAGE_FREE[$index_1]}"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}$C_REVERSE ${STORAGE_NAME[$index_2]}"
		echo -e "$C_RESET${STORAGE_PERCENT[$index_2]}"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Used: $C_RESET${STORAGE_USED[$index_2]} / ${STORAGE_TOTAL[$index_2]}"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Free: $C_RESET${STORAGE_FREE[$index_2]}"

	}

	#MPD  - modified for MPD-Cloushell
	Update_Scene_4(){

		#Update data
		Obtain_MPDINFO
		Obtain_CPU

		#Clear screen
		clear

		#banner (date-hour)
		echo -e "$C_RESET$C_BOLD $BANNER_PRINT"
		#MPD info
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}$C_REVERSE MPD Internet Radio:      "
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}Volume ${aCOLOUR[$USER_COLOUR_INDEX]}:$C_RESET  $MPD_VOLUME"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}Channel${aCOLOUR[$USER_COLOUR_INDEX]}:$C_RESET  $MPD_STATION"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}$C_REVERSE Current Station - Song:  "
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}${aCOLOUR[$USER_COLOUR_INDEX]}$C_RESET$MPD_CURRENT_SONG"

	}

	#System Information - modified for MPD-Cloushell
	Update_Scene_5(){

		#Update data
		Obtain_NETWORK_DETAILS

		#Clear screen
		clear

		#Banner
		echo -e "$C_RESET$C_BOLD $BANNER_PRINT"
		#
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}$C_REVERSE System information:      "
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} IP      : $C_RESET$NETWORK_DETAILS_IP_INT"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Signal  : $C_RESET$NETWORK_DETAILS_SIGNAL_STRENGTH"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} SSID    : $C_RESET$NETWORK_DETAILS_SSID"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Cpu     : $C_RESET$CPU_USAGE"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Temp    : $C_RESET$C_CPUTEMP$CPU_TEMP"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} SD space: $C_RESET$FREE_SD_SPACE"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}$C_RESET $RAM"
	}

	#NETWORK USAGE
	Update_Scene_6(){

		#Update data
		Obtain_NETWORK_USAGE

		# - Convert usage values into human readable format. Run before clearing screen due to additional processing (delay)
		local total_sent_output=$( BYTE_PRINT_CONVERSION $NETWORK_USAGE_TOTAL_CURRENT_SENT )
		local total_recieved_output=$( BYTE_PRINT_CONVERSION $NETWORK_USAGE_TOTAL_CURRENT_RECIEVED )

		local today_sent_output=$( BYTE_PRINT_CONVERSION $NETWORK_USAGE_DAY_CURRENT_SENT )
		local today_recieved_output=$( BYTE_PRINT_CONVERSION $NETWORK_USAGE_DAY_CURRENT_RECIEVED )

		local now_sent_output=0
		local now_recieved_output0
		if (( $NETWORK_USAGE_CURRENT_OUTPUT_TYPE == 0 )); then

			now_sent_output=$( BIT_PRINT_CONVERSION $NETWORK_USAGE_NOW_CURRENT_SENT )
			now_recieved_output=$( BIT_PRINT_CONVERSION $NETWORK_USAGE_NOW_CURRENT_RECIEVED )

		else

			now_sent_output=$( BYTE_PRINT_CONVERSION $NETWORK_USAGE_NOW_CURRENT_SENT )
			now_recieved_output=$( BYTE_PRINT_CONVERSION $NETWORK_USAGE_NOW_CURRENT_RECIEVED )

		fi

		#Clear screen
		clear

		#Banner
		# - Banner does not fit this scene (>= 9 lines)
		#echo -e "$C_RESET $BANNER_PRINT"

		#
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}$C_REVERSE Network Usage (TOTAL):   "
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Sent     : $C_RESET$total_sent_output"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Recieved : $C_RESET$total_recieved_output"

		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}$C_REVERSE Network Usage (TODAY):   "
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Sent     : $C_RESET$today_sent_output"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Recieved : $C_RESET$today_recieved_output"

		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}$C_REVERSE Network Usage (CURRENT): "
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Sent     : $C_RESET$now_sent_output/s"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Recieved : $C_RESET$now_recieved_output/s"

	}

	#Memory
	Update_Scene_7(){

		#Update data
		Obtain_MEMORY

		#Clear screen
		clear

		#Banner
		echo -e "$C_RESET $BANNER_PRINT"
		#
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}$C_REVERSE Memory Usage (RAM):      "
		echo -e "$C_RESET$MEMORY_PERCENT"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Used: $C_RESET$MEMORY_USED MB / $MEMORY_TOTAL MB"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Free: $C_RESET$MEMORY_FREE MB"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}$C_REVERSE Memory Usage (SWAP):     "
		echo -e "$C_RESET$MEMORY_SWAPERCENT"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Used: $C_RESET$MEMORY_SWAPUSED MB / $MEMORY_SWAPTOTAL MB"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Free: $C_RESET$MEMORY_SWAPFREE MB"

	}

	#Pi-hole
	Update_Scene_8(){

		#Update data
		Obtain_PIHOLE

		#Clear screen
		clear

		#Banner
		echo -e "$C_RESET $BANNER_PRINT"
		#
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}$C_REVERSE Pi-hole stats (TODAY):   "
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Ads Blocked: $C_RESET$PIHOLE_TOTAL_ADS"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} DNS Queries: $C_RESET$PIHOLE_QUERY_COUNT"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]} Blocked Domains: $C_RESET$PIHOLE_TOTAL_DOMAINS"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}$C_REVERSE % of traffic = Ads:      "
		echo -e "$C_RESET$PIHOLE_PERCENT_ADS"
		echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}$C_REVERSE Last domain blocked:     "
		echo -e "$C_RESET $PIHOLE_LAST_DOMAIN_BLOCKED"

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# Settings File
	#/////////////////////////////////////////////////////////////////////////////////////
	#Define Location
	FILEPATH_SETTINGS='/DietPi/dietpi/.dietpi-cloudshell'

	Read_Settings_File(){

		if [[ -f $FILEPATH_SETTINGS ]]; then

			. $FILEPATH_SETTINGS

		fi

	}

	Write_Settings_File(){

		cat << _EOF_ > $FILEPATH_SETTINGS
REFRESH_RATE=$REFRESH_RATE
USER_COLOUR_INDEX=$USER_COLOUR_INDEX
TEMPERATURE_OUTPUT_TYPE=$TEMPERATURE_OUTPUT_TYPE
OUTPUT_DISPLAY_INDEX=$OUTPUT_DISPLAY_INDEX

NETWORK_USAGE_CURRENT_OUTPUT_TYPE=$NETWORK_USAGE_CURRENT_OUTPUT_TYPE

BLANK_SCREEN_AT_SPECIFIC_TIME_ENABLED=$BLANK_SCREEN_AT_SPECIFIC_TIME_ENABLED
BLANK_SCREEN_TIME_HOUR_START=$BLANK_SCREEN_TIME_HOUR_START
BLANK_SCREEN_TIME_HOUR_END=$BLANK_SCREEN_TIME_HOUR_END

_EOF_

		#Add enabled scenes
		for ((i=0; i<$MAX_SCENES; i++))
		do

			echo -e "aEnabledScenes[$i]=${aEnabledScenes[$i]}" >> $FILEPATH_SETTINGS

		done

		#Add Drive Paths and Names
		for ((i=0; i<$MAX_STORAGE; i++))
		do

			echo -e "STORAGE_PATH[$i]='${STORAGE_PATH[$i]}'" >> $FILEPATH_SETTINGS
			echo -e "STORAGE_NAME[$i]='${STORAGE_NAME[$i]}'" >> $FILEPATH_SETTINGS

		done

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# Init
	#/////////////////////////////////////////////////////////////////////////////////////
	Init(){

		#--------------------------------------------------------------------------------
		#Storage array
		Init_STORAGE

		#--------------------------------------------------------------------------------
		#Load Settings file.
		Read_Settings_File

		#--------------------------------------------------------------------------------
		#VM disable CPU scene
		if (( $G_HW_MODEL == 20 )); then

			aEnabledScenes[0]=0

		fi

		#--------------------------------------------------------------------------------
		#Check and disable scenes if software is not installed:
		# 6 Pi-hole
		if [[ ! -f /etc/pihole/gravity.list ]]; then

			aEnabledScenes[8]=0

		fi

		#--------------------------------------------------------------------------------
		#Ensure we have at least 1 Scene enabled in the settings file.
		local enabled_scene=0
		for ((i=0; i<$MAX_SCENES; i++))
		do

			if (( ${aEnabledScenes[$i]} )); then

				enabled_scene=1
				break

			fi

		done

		#No Scenes selected! Override user setting and enable at least 1 scene (dietpi)
		if (( $enabled_scene == 0 )); then

			aEnabledScenes[4]=1
			SCENE_CURRENT=4

		fi
		#--------------------------------------------------------------------------------
		#Update DietPi network shared data: https://github.com/Fourdee/DietPi/issues/359
		/DietPi/dietpi/func/obtain_network_details

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# Start/Stop Control for Menu
	#/////////////////////////////////////////////////////////////////////////////////////
	#0=tty1 1=current
	OUTPUT_DISPLAY_INDEX=0

	Menu_Stop(){

		#Service if started.
		systemctl stop dietpi-cloudshell

		#Kill all , excluding Menu.
		ps ax | grep '[d]ietpi-cloudshell [1-9]' | awk '{print $1}' > $FP_TEMP
		while read -r line
		do

			kill $line &> /dev/null

		done < $FP_TEMP

	}

	Menu_Start(){

		#Are we starting on the current screen? (eg: from tty1)
		local output_current_screen=0
		if [[ $(tty) == '/dev/tty1' ]]; then

			output_current_screen=1

		elif (( $OUTPUT_DISPLAY_INDEX == 1 )); then

			output_current_screen=1

		fi

		#Inform user to press CTRL+C to exit
		if (( $output_current_screen == 1 )); then

			clear
			echo -e "$C_RESET"
			read -p "Use CTRL+C to exit. Press any key to launch $G_PROGRAM_NAME..."

		fi

		#Launch in blocking mode
		if (( $output_current_screen == 1 )); then

			Run_Cloudshell

		#Launch as service on main screen
		else

			systemctl start dietpi-cloudshell

		fi

		sleep 0.1

	}

	Run_Cloudshell(){

		Init_Term_Options

		#Start Intro
		if (( $RUN_INTRO )); then

			Run_Intro

		fi

		#Set Nice to +10 (not critical)
		renice -n 10 $$ &> /dev/null

		#Start display updates
		while true
		do

			if (( $BLANK_SCREEN_AT_SPECIFIC_TIME_ENABLED )); then

				RUN_BLANK_SCREEN_AT_SPECIFIC_TIME

			fi

			#Disable updates when screen is blanked
			if (( $BLANK_SCREEN_ACTIVE )); then

				sleep 60

			#Update enabled scenes
			else

				if (( ${aEnabledScenes[$SCENE_CURRENT]} )); then

					Update_Banner

					# - Input mode scene update (storage array)
					if (( $SCENE_CURRENT == 1 )); then

						Update_Scene_1 0 1

					# - Input mode scene update (storage array)
					elif (( $SCENE_CURRENT == 2 )); then

						Update_Scene_1 2 3

					# - Input mode scene update (storage array)
					elif (( $SCENE_CURRENT == 3 )); then

						Update_Scene_1 4 5

					# - Normal scene update
					else

						Update_Scene_$SCENE_CURRENT

					fi

					#Apply refresh rate delay
					sleep $REFRESH_RATE

				fi

				#Scene Switcher
				((SCENE_CURRENT++))

				#Cap
				if (( $SCENE_CURRENT >= $MAX_SCENES )); then

					SCENE_CURRENT=0

				fi


			fi
		done

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# Menu System
	#/////////////////////////////////////////////////////////////////////////////////////
	TARGETMENUID=0
	LASTSELECTED_ITEM=''

	Menu_Exit(){

		G_WHIP_SIZE_X_MAX=50
		G_WHIP_YESNO "Exit $G_PROGRAM_NAME?"
		if (( $? == 0 )); then

			#Save changes
			Write_Settings_File

			#exit
			TARGETMENUID=-1

		else

			#Return to Main Menu
			TARGETMENUID=0

		fi

	}

	#TARGETMENUID=0
	Menu_Main(){

		TARGETMENUID=0

		local temp_output_text='Fahrenheit'
		if (( $TEMPERATURE_OUTPUT_TYPE == 1 )); then

			temp_output_text='Celsius'

		fi

		local target_output_text='Main Screen (tty1)'
		if (( $OUTPUT_DISPLAY_INDEX == 1 )); then

			target_output_text='Current screen or terminal'

		fi

		local bitbyte_output_text='Bit (Kbit, Mbit, Gbit)'
		if (( $NETWORK_USAGE_CURRENT_OUTPUT_TYPE == 1 )); then

			bitbyte_output_text='Byte (KB, MB, GB)'

		fi

		local autoscreenoff='Disabled'
		if (( $BLANK_SCREEN_AT_SPECIFIC_TIME_ENABLED )); then

			autoscreenoff='Enabled'

		fi

		G_WHIP_MENU_ARRAY=(

			'Colour' 'Setting: Change the colour scheme.'
			'Update Rate' 'Setting: Control the time between screen updates.'
			'Scenes' 'Setting: Toggle which scenes are shown.'
			'Storage' 'Setting: Set mount locations used for storage stats'
			'Temperature' "Setting: Output = $temp_output_text"
			'Net Usage Current' "Setting: Output = $bitbyte_output_text"
			'Output Display' "Setting: $target_output_text."
			'Auto screen off' "Setting: $autoscreenoff | Start $BLANK_SCREEN_TIME_HOUR_START h | End $BLANK_SCREEN_TIME_HOUR_END h"
			'Start / Restart' "Apply settings. Launch on $target_output_text."
			'Stop' "Stops $G_PROGRAM_NAME."

		)

		G_WHIP_DEFAULT_ITEM="$LASTSELECTED_ITEM"
		G_WHIP_BUTTON_CANCEL_TEXT='Exit'
		G_WHIP_MENU
		if (( $? == 0 )); then

			LASTSELECTED_ITEM="$G_WHIP_RETURNED_VALUE"

			case "$G_WHIP_RETURNED_VALUE" in

				'Storage')

					TARGETMENUID=5

				;;

				'Auto screen off')

					TARGETMENUID=4

				;;

				'Net Usage Current')

					((NETWORK_USAGE_CURRENT_OUTPUT_TYPE++))
					if (( $NETWORK_USAGE_CURRENT_OUTPUT_TYPE > 1 )); then

						NETWORK_USAGE_CURRENT_OUTPUT_TYPE=0

					fi

				;;

				'Temperature')

					((TEMPERATURE_OUTPUT_TYPE++))
					if (( $TEMPERATURE_OUTPUT_TYPE > 1 )); then

						TEMPERATURE_OUTPUT_TYPE=0

					fi

				;;

				'Output Display')

					((OUTPUT_DISPLAY_INDEX++))
					if (( $OUTPUT_DISPLAY_INDEX > 1 )); then

						OUTPUT_DISPLAY_INDEX=0

					fi

				;;

				'Start / Restart')

					Write_Settings_File
					Menu_Stop
					Menu_Start

				;;

				'Stop')

					Menu_Stop

				;;

				'Colour')

					TARGETMENUID=1

				;;

				'Update Rate')

					TARGETMENUID=2

				;;

				'Scenes')

					TARGETMENUID=3

				;;

			esac

		else

			Menu_Exit

		fi

	}

	#TARGETMENUID=1
	Menu_Colour(){

		#Return to main menu
		TARGETMENUID=0

		G_WHIP_MENU_ARRAY=(

			'0' 'White'
			'1' 'Red'
			'2' 'Green'
			'3' 'Yellow (Default)'
			'4' 'Blue'
			'5' 'Purple'
			'6' 'Cyan'

		)

		G_WHIP_DEFAULT_ITEM="$USER_COLOUR_INDEX"
		G_WHIP_MENU 'Please select a colour scheme.'
		if (( $? == 0 )); then

			USER_COLOUR_INDEX=$G_WHIP_RETURNED_VALUE

		fi

	}

	#TARGETMENUID=2
	Menu_UpdateRate(){

		#Return to main menu
		TARGETMENUID=0

		G_WHIP_MENU_ARRAY=(

			'1' 'Second'
			'3' 'Seconds'
			'5' 'Seconds (Default)'
			'10' 'Seconds'
			'15' 'Seconds'
			'20' 'Seconds'
			'30' 'Seconds'
			'45' 'Seconds'
			'60' 'Seconds'

		)

		G_WHIP_DEFAULT_ITEM=$REFRESH_RATE
		G_WHIP_MENU 'Please select the desired delay, between scene changes and updates.'
		if (( $? == 0 )); then

			REFRESH_RATE=$G_WHIP_RETURNED_VALUE

		fi

	}

	#TARGETMENUID=3
	Menu_SceneSelection(){

		#Return to main menu
		TARGETMENUID=0

		#Get on/off whilptail status
		local aWhip_OnOff_Status=()
		for ((i=0; i<$MAX_SCENES; i++))
		do
			#On/Off status
			aWhip_OnOff_Status[$i]='on'
			if (( ! ${aEnabledScenes[$i]} )); then

				aWhip_OnOff_Status[$i]='off'

			fi

		done

		#Define options
		local index=0
		G_WHIP_CHECKLIST_ARRAY=()
		index=0;G_WHIP_CHECKLIST_ARRAY+=($index 'CPU: Temperatures, Usage, frequency and more.' "${aWhip_OnOff_Status[$index]}")
		index=1;G_WHIP_CHECKLIST_ARRAY+=($index 'Storage: Usage information for Flash and USB drives' "${aWhip_OnOff_Status[$index]}")
		index=2;G_WHIP_CHECKLIST_ARRAY+=($index ' - Additional Storage (USB_2/3)' "${aWhip_OnOff_Status[$index]}")
		index=3;G_WHIP_CHECKLIST_ARRAY+=($index ' - Additional Storage (USB_4/5)' "${aWhip_OnOff_Status[$index]}")
		index=4;G_WHIP_CHECKLIST_ARRAY+=($index 'DietPi: Information, stats and updates for DietPi.' "${aWhip_OnOff_Status[$index]}")
		index=5;G_WHIP_CHECKLIST_ARRAY+=($index 'Network Details: Ip address, Speeds, Signal and more.' "${aWhip_OnOff_Status[$index]}")
		index=6;G_WHIP_CHECKLIST_ARRAY+=($index 'Network Usage: Bandwidth usage (sent / recieved).' "${aWhip_OnOff_Status[$index]}")
		index=7;G_WHIP_CHECKLIST_ARRAY+=($index 'Memory: Stats for RAM and Swapfile usage.' "${aWhip_OnOff_Status[$index]}")
		index=8;G_WHIP_CHECKLIST_ARRAY+=($index 'Pi-hole: Stats for Pi-hole. Total Ads blocked etc.' "${aWhip_OnOff_Status[$index]}")

		G_WHIP_CHECKLIST 'Please use the spacebar to toggle which scenes are active.'
		if (( $? == 0 )); then

			# - Reset all scenes to 0
			for ((i=0; i<$MAX_SCENES; i++))
			do
				aEnabledScenes[$i]=0

			done

		fi

		#Delete[] array
		unset aWhip_OnOff_Status

		# - Enable required scenes
		for i in ${G_WHIP_RETURNED_VALUE[@]}
		do

			aEnabledScenes[$i]=1

		done

	}

	#TARGETMENUID=4
	Menu_BlankScreenAtTime(){

		#Return to main menu
		TARGETMENUID=0

		local blank_screen_at_specific_time_enabled_text='Disabled'
		if (( $BLANK_SCREEN_AT_SPECIFIC_TIME_ENABLED )); then

			blank_screen_at_specific_time_enabled_text='Enabled'

		fi

		G_WHIP_MENU_ARRAY=(

			'Toggle' "$blank_screen_at_specific_time_enabled_text"
			'Start time' "Set which hour to power off screen ($BLANK_SCREEN_TIME_HOUR_START)."
			'End time' "Set which hour to power on screen ($BLANK_SCREEN_TIME_HOUR_END)."

		)

		G_WHIP_BUTTON_CANCEL_TEXT='Back'
		G_WHIP_MENU 'Automatically power down the screen and disable DietPi-Cloudshell processing during a specific time.\n\nNB: This feature will only work if DietPi-Cloudshell was launched with the DietPi-Autostart option, or, launched from the main screen (tty1).'
		if (( $? == 0 )); then

			if [[ $G_WHIP_RETURNED_VALUE == 'Toggle' ]];then

				((BLANK_SCREEN_AT_SPECIFIC_TIME_ENABLED++))
				if (( $BLANK_SCREEN_AT_SPECIFIC_TIME_ENABLED > 1 )); then

					BLANK_SCREEN_AT_SPECIFIC_TIME_ENABLED=0

				fi

			elif [[ $G_WHIP_RETURNED_VALUE == 'Start time' ]];then

				G_WHIP_MENU_ARRAY=()
				for ((i=0; i<24; i++))
				do

					G_WHIP_MENU_ARRAY+=($i "Hour")

				done

				G_WHIP_DEFAULT_ITEM=$BLANK_SCREEN_TIME_HOUR_START
				G_WHIP_MENU 'Please select which hour (24h) you would like the screen to power off.'
				if (( $? == 0 )); then

					BLANK_SCREEN_TIME_HOUR_START=$G_WHIP_RETURNED_VALUE

				fi

			elif [[ $G_WHIP_RETURNED_VALUE == 'End time' ]];then

				G_WHIP_MENU_ARRAY=()
				for ((i=0; i<24; i++))
				do

					G_WHIP_MENU_ARRAY+=($i 'Hour')

				done

				G_WHIP_DEFAULT_ITEM=$BLANK_SCREEN_TIME_HOUR_END
				G_WHIP_MENU 'Please select which hour (24h) you would like the screen to power on.'
				if (( $? == 0 )); then

					BLANK_SCREEN_TIME_HOUR_END=$G_WHIP_RETURNED_VALUE

				fi

			fi

			TARGETMENUID=4

		fi

	}

	#TARGETMENUID=5
	Menu_Storage(){

		#Return to main menu
		TARGETMENUID=0

		G_WHIP_MENU_ARRAY=()

		for ((i=1; i<$MAX_STORAGE; i++))
		do

			G_WHIP_MENU_ARRAY+=( $i ": Drive $i | ${STORAGE_PATH[$i]}" )

		done

		G_WHIP_BUTTON_CANCEL_TEXT='Back'
		G_WHIP_MENU 'Storage Device Mount Location:\n\nDietPi-Cloudshell pulls the storage stats from the drive mount location. If you have custom drives/mounts, please set them here to be displayed during storage scene updates.\n\n - Drive 1 = Displayed during main storage scene\n - Drive 2/3 = Displayed during additional storage scene\n - Drive 4/5 = Displayed during additional storage scene'
		if (( $? == 0 )); then

			local index=$G_WHIP_RETURNED_VALUE

			/DietPi/dietpi/dietpi-drive_manager 1
			local return_string="$(</tmp/dietpi-drive_manager_selmnt)"
			if [[ $return_string ]]; then

				STORAGE_PATH[$index]="$return_string"

			fi

			TARGETMENUID=5

		fi

	}


	#/////////////////////////////////////////////////////////////////////////////////////
	# MAIN
	#/////////////////////////////////////////////////////////////////////////////////////
	#-----------------------------------------------------------------------------------
	#Init
	Init
	#-----------------------------------------------------------------------------------
	#Run menu
	if (( $INPUT == 0 )); then

		#Start Menu
		while (( $TARGETMENUID >= 0 )); do

			clear

			if (( $TARGETMENUID == 0 )); then

				Menu_Main

			elif (( $TARGETMENUID == 1 )); then

				Menu_Colour

			elif (( $TARGETMENUID == 2 )); then

				Menu_UpdateRate

			elif (( $TARGETMENUID == 3 )); then

				Menu_SceneSelection

			elif (( $TARGETMENUID == 4 )); then

				Menu_BlankScreenAtTime

			elif (( $TARGETMENUID == 5 )); then

				Menu_Storage

			fi

		done

	#-----------------------------------------------------------------------------------
	#Run DietPi-Cloudshell
	elif (( $INPUT >= 1 )); then

		Run_Cloudshell

	fi

	#-----------------------------------------------------------------------------------
	#Clean up temp files
	rm $FP_TEMP &> /dev/null
	#-----------------------------------------------------------------------------------
	#Delete[] Global arrays
	unset aCOLOUR
	unset aEnabledScenes
	Destroy_STORAGE
	#-----------------------------------------------------------------------------------
	exit
	#-----------------------------------------------------------------------------------
}

@DietPI coders:
feel free to modify the original code to include my MPD scene :smiley:

If you want to use the three buttons on 3.2 LCD display with Raspberry, you can use this python script to control the “start/stop”, “next” and “prev” functions (or whatever else) of MPD:

sudo nano /root/buttons.py



#!/usr/bin/env python2
# by pilovis - Italy
import RPi.GPIO as GPIO # Import Raspberry Pi GPIO library
import time
import os
GPIO.setwarnings(False) # Ignore warning for now
GPIO.setmode(GPIO.BOARD) # Use physical pin numbering
GPIO.setup(12, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Set pin 12 to be an input pin and set initial value to be pulled up (on)
GPIO.setup(16, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(12, GPIO.BOTH, bouncetime=20) # The buttons have a little bounce, 20ms seems to be a good threshold
GPIO.add_event_detect(16, GPIO.BOTH, bouncetime=20)
GPIO.add_event_detect(18, GPIO.BOTH, bouncetime=20)

while True: # Run forever

        if GPIO.input(12) == GPIO.LOW:
            os.system("mpc next")
        if GPIO.input(16) == GPIO.LOW:
            os.system("mpc prev")
        if GPIO.input(18) == GPIO.LOW:
            os.system("mpc toggle")
        time.sleep(1.0) # Polling is a bad thing, let the CPU rest

put the following command in “/etc/rc.local” file, just before the “exit 0” line, to lauch the python script at startup:

/usr/bin/python /root/buttons.py &

If you prefere using Triggerhappy (USB keyboard or USB numeric keypad) to control MPD, this is a sample of the configuration file.

Something I did in the past with MPD and Triggerhappy:
https://www.youtube.com/watch?v=cg18hvhIn4E

Info about Triggerhappy:
https://github.com/wertarbyte/triggerhappy

Triggerhappy installation:

sudo apt-get install triggerhappy

edit Triggerhappy config file:

sudo nano /etc/triggerhappy/triggers.d/example.conf



# Triggerhappy basic configuration file for MPD
# By pilovis - Italy
#
# to edit this file:
#> sudo nano /etc/triggerhappy/triggers.d/example.conf
#
# to determine the buttons name use the following command:
#> sudo thd --dump /dev/input/event*
#example:
#EV_KEY BTN_5   1 #(the name is BTN_5)
#EV_KEY BTN_1   1 #(the name is BTN_1)
#EV_KEY BTN_0   1 #(the name is BTN_0)
#
# to restart triggerhappy
#> sudo /etc/init.d/triggerhappy restart
#
####################################################################
# This is an example configuration for the triggerhappy daemon (thd)
# please note that every file to be processed must end in ".conf"
#
# To view a list of supported event codes, use "thd --listevents" or
# "thd --dump /dev/input/event*"
#
# Format:
# <eventcode> <value> <command>
#
# values for key events are 1 (pressed), 0 (released) or 2 (held)
#
####################################################################
#
## - MPD controls:
#
## decrease volume:
BTN_1 1 /usr/bin/mpc volume -2
#
##  increase volume:
BTN_0 1 /usr/bin/mpc volume +2
#
##  play - stop MPD
BTN_5 1 /usr/bin/mpc toggle
#
# eof

This is a more comprehensive example with two different keypads support:

# Triggerhappy configuration file for MPD - USB numeric Keypad
# By pilovis - Italy
#
# To view a list of supported event codes, use "thd --listevents" or
# "thd --dump /dev/input/event*"
# Format:
# <eventcode> <value> <command>
# values for key events are 1 (pressed), 0 (released) or 2 (held)
#
## control mpd
#
# start playing
KEY_KPENTER 1 /usr/bin/mpc play
KEY_PLAYPAUSE 1 /usr/bin/mpc play
# next station
KEY_KPSLASH 1 /usr/bin/mpc next
KEY_PAGEUP 1 /usr/bin/mpc next
# prev station
KEY_KPASTERISK 1 /usr/bin/mpc prev
KEY_PAGEDOWN 1 /usr/bin/mpc prev
# stop playing
KEY_KPDOT 1 /usr/bin/mpc stop
KEY_STOPCD 1 /usr/bin/mpc stop
#                                               
## control audio volume                                                                                                       
#  increase volume +1%:                                             
KEY_KPPLUS 1 /usr/bin/mpc volume +1
KEY_VOLUMEUP 1 /usr/bin/mpc volume +1
#  set the volume at the minimum audible level (MUTE mode)
KEY_BACKSPACE 1 /usr/bin/mpc volume 80
KEY_MIN_INTERESTING 1 /usr/bin/mpc volume 80   
# decrease volume -1%:                           
KEY_KPMINUS 1 /usr/bin/mpc volume -1
KEY_VOLUMEDOWN 1 /usr/bin/mpc volume -1
#
# eof

I will soon post here instructions and code about an easy and cheap InfraRed remote control for MPD by using Lirc, an IR diode receiver and an IR remote (any is OK).

and maybe someday in the future also a MPD Mind Control :stuck_out_tongue: :stuck_out_tongue: :stuck_out_tongue: :stuck_out_tongue: :stuck_out_tongue:

Just an add-on :smiley:

a script to load 59 Internet Radio Stations to MPD with just one click:

create the script:

sudo nano /root/add-station.sh

insert the code:

/usr/bin/mpc add http://144.76.106.52:7000/chillout.mp3
/usr/bin/mpc add http://205.164.62.15:9010/
/usr/bin/mpc add http://streaming.radionomy.com/PassionLoveRadio
/usr/bin/mpc add http://176.31.240.87:8025
/usr/bin/mpc add http://stream.srg-ssr.ch/m/rsj/mp3_128
/usr/bin/mpc add http://stream.srg-ssr.ch/m/rsc_it/mp3_128
/usr/bin/mpc add http://stream.srg-ssr.ch/m/rsp/mp3_128
/usr/bin/mpc add http://streaming.radionomy.com/CristalRelax
/usr/bin/mpc add http://streaming.radionomy.com/Radio-Quelit
/usr/bin/mpc add http://streaming.radionomy.com/R-E-T-R-OF-M
/usr/bin/mpc add http://streaming.radionomy.com/radio-accordeon
/usr/bin/mpc add http://streaming.radionomy.com/100-HIT-ra
/usr/bin/mpc add http://streaming.radionomy.com/colombiaromantica
/usr/bin/mpc add http://streaming.radionomy.com/GOLDEN-SIXTIES-SEVENTIES-EIGHTIES-RADIO
/usr/bin/mpc add http://streaming.radionomy.com/radio-oldies-and-rock--n--roll
/usr/bin/mpc add http://hr-mp3-m-h3.akacast.akamaistream.net/7/785/142133/v1/gnl.akacast.akamaistream.net/hr-mp3-m-h3
/usr/bin/mpc add http://streaming.hotmix-radio.net/hotmixradio-lounge-128.mp3
/usr/bin/mpc add http://streaming.radionomy.com/Ambiance-Reggae
/usr/bin/mpc add http://streaming.radionomy.com/always-80s
/usr/bin/mpc add http://streaming.radionomy.com/Hit-s-My-Music-Pop-Rock
/usr/bin/mpc add http://streaming.radionomy.com/Cafe-Romantico-Radio
/usr/bin/mpc add http://streaming.radionomy.com/1000-HITS-Sweet-Radio
/usr/bin/mpc add http://46.37.20.205:8000/rdsmp3
/usr/bin/mpc add http://89.16.185.174:8003/stream
/usr/bin/mpc add http://89.16.185.174:8000/stream
/usr/bin/mpc add http://89.16.185.174:8004/stream
/usr/bin/mpc add http://streaming.radionomy.com/Fm-Tropical-Shad-972
/usr/bin/mpc add http://streaming.radionomy.com/NashvilleEdge
/usr/bin/mpc add http://streaming.radionomy.com/Abacusfm-Nature
/usr/bin/mpc add http://streaming.radionomy.com/chd--radio-country
/usr/bin/mpc add http://streaming.radionomy.com/1-Radio-Dance
/usr/bin/mpc add http://streaming.radionomy.com/Acoustic-FM
/usr/bin/mpc add http://streaming.radionomy.com/ABC-Love
/usr/bin/mpc add http://streaming.radionomy.com/Radio-Nostalgia
/usr/bin/mpc add http://andromeda.shoutca.st:8634/stream
/usr/bin/mpc add http://streaming.radionomy.com/Tsjechische-Blaasmuziek
/usr/bin/mpc add http://streaming.radionomy.com/DanceRO
/usr/bin/mpc add http://streaming.radionomy.com/BobFamilyandfriends
/usr/bin/mpc add http://streaming.radionomy.com/The-Buffalo
/usr/bin/mpc add http://streaming.radionomy.com/VWClassicRock
/usr/bin/mpc add http://icecast2.rte.ie/ieradio1
/usr/bin/mpc add http://listen.radionomy.com/the-smooth-lounge
/usr/bin/mpc add http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio1_mf_p
/usr/bin/mpc add http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio1xtra_mf_p
/usr/bin/mpc add http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio2_mf_p
/usr/bin/mpc add http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio3_mf_p
/usr/bin/mpc add http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio4fm_mf_p
/usr/bin/mpc add http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio4lw_mf_p
/usr/bin/mpc add http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio4extra_mf_p
/usr/bin/mpc add http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio5live_mf_p
/usr/bin/mpc add http://bbcmedia.ic.llnwd.net/stream/bbcmedia_6music_mf_p
/usr/bin/mpc add http://bbcmedia.ic.llnwd.net/stream/bbcmedia_asianet_mf_p
/usr/bin/mpc add http://bbcmedia.ic.llnwd.net/stream/bbcmedia_nangaidheal_mf_p
/usr/bin/mpc add http://webradio.antennevorarlberg.at:80/lovesongs
/usr/bin/mpc add http://webradio.antennevorarlberg.at:80/hits
/usr/bin/mpc add http://webradio.antennevorarlberg.at:80/live
/usr/bin/mpc add http://webradio.antennevorarlberg.at:80/disco
/usr/bin/mpc add http://webradio.antennevorarlberg.at:80/partymix
/usr/bin/mpc add http://webradio.antennevorarlberg.at:80/lounge

give the right permissions to the script:

sudo chmod 755 /root/add-station.sh

launch the script:

sudo /bin/sh /root/add-station.sh

That’s all :wink:

If you like MPD you’ll find here a lot of tips and code I developped for another Linux system (OpenWRT):
https://forum.archive.openwrt.org/viewtopic.php?id=49013&p=1


My D.I.Y. Stereo Hi-Fi MPD Vacuum Tube Internet Radio (the digital part is inside):

Another one (vintage look, old tubes still perfectly fuctional, but recent build: 2013)

Hi,

Many thanks for posting this excellent guide for audiophiles :smiley:

Very nice setup as well, even if I am a little jealous :wink:

Raspberry Pi 1 B+ & 3.2 LCD

If I have enough time I will also post an How-to about a D.I.Y. Raspberry MPD i2c 20x4 LCD scrolling display.

My prototype:

Sleep and Wakeup MPD radio

A crontab to automatically reduce audio volume at night (gradually) till stopping audio at late night

edit crontab:

sudo crontab -e

insert the following lines at the end:

0 22 * * * /usr/bin/mpc volume 93   #reduce volume 93% at 22:00
30 22 * * * /usr/bin/mpc volume 90  #reduce volume 90% at 22:30
0 23 * * * /usr/bin/mpc volume 88   #reduce volume 88% at 23:00
30 23 * * * /usr/bin/mpc volume 86  #reduce volume 86% at 23:30
0 0 * * * /usr/bin/mpc volume 84    #reduce volume 84% at 00:00
30 0 * * * /usr/bin/mpc stop        #stop audio at 00:30

note: change time and volume level as you wish

to apply crontab changes without reloading:

sudo service cron reload

You might want to Wake Up at the morning, eg. at 7:00 AM from Monday to Friday, with the MPD Internet Radio playing your favourite station and stop music after half an hour (dead line to get out of the bed :smiley: ),
simply add the following lines:

59 6 * * 1-5 /usr/bin/mpc volume 93 # wakeup volume - adjust for your needs
0 7 * * 1-5 /usr/bin/mpc play # MPD starts playing at 7:00 - Mon-Fri
30 7 * * 1-5  /usr/bin/mpc stop # MPD stops at 7:30 - Mon-Fri

If you want to have an audible beep every exact hour from 08:00 AM to 09:00 PM even if the radio is playing music:

00 08-21 * * * speaker-test -c1 -t sine -f 800 -P 2 -p 0.4 -S 10 -l 1;

I’m also trying to get the touchscreen working even if my raspberry hasn’t got any desktop, just in console mode.
I would like to control the MPD_Cloudshell to switch scene, from “MPD” (default) to “System Information” and so on, every time the screen is touched.

Up to now I can grab the touch event in this way:

sudo apt-get install evtest



sudo evtest /dev/input/event1 | grep -o '(BTN_TOUCH), value 1'

Every time I touch the screen I get this:

(BTN_TOUCH), value 1

I am preparing a 8Gbytes, Raspberry Pi1/2/3, “ready to go” dietpi “MDP Internet Radio” image, with the following features, preinstalled and fully configured:

  • MPD and MyMPD (client web interface)
  • Alsa Equalizer (10 bands graphic equalizer)
  • MPD-Cloudshell (see above)
  • Raspi 3.2 Graphic LCD + 3 buttons, support
  • i2c 20x4 text LCD, support
  • Triggerhappy for USB numeric keypad support
  • Infrared integrated remote control (Lirc)
  • Mjpg-Streamer with both, USB webcam and Raspicam support, for live cam streaming
  • Motion with both, USB webcam and Raspicam support, for triggering an action on a cam motion detected
  • Battery RTC (real time clock) module support
  • Sleep and Wakeup MPD internet radio
  • Text2Speech (svox US,GB,DE,ES,FR,IT languages) Talking Clock (to speak the time) & Talking Reminder
  • Automatic GPIO control for relay board to switch on/off the External Audio Amplifier on MPD start/stop (or anything else)
    … and much more.

Everything is optimized for Raspberry Pi1B with 512 Mbytes RAM @ 1Ghz (overclock),

Stay tuned! :wink: