#!/bin/sh

### BEGIN INIT INFO
# Provides:          	lms
# Required-Start:    	$all
# Required-Stop:     	$all
# Should-Start:      	$all
# Should-Stop:       	$all
# Default-Start:     	2 3 4 5
# Default-Stop:      	0 1 6
# Short-Description:	Startup script for the LMS Media Server git code
# Description:		LMS Media Server git code powers the Squeezebox, Transporter and SLIMP3 network music
#				players and is the best software to stream your music to any software MP3
#				player. It supports MP3, AAC, WMA, FLAC, Ogg Vorbis, WAV and more!
#				As of version 7.7 it also supports UPnP clients, serving pictures and movies too!
### END INIT INFO


#
# $Id$
#
# lms initscript for slimserver.pl
# This file should be placed in /etc/init.d.
#
# Original Author: Mattias Holmlund
# Updated By: Dan Sully, Michael Herger
#
# Rewrite 20120515 by Gordon Harris to make conforming with:
# http://refspecs.linuxbase.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
# and based on http://www.thegeekstuff.com/2012/03/lsbinit-script/
#

# Using the lsb functions to perform the operations.
. /lib/lsb/init-functions

SLIMSRVC='lms'
# Read config file if it is present.
if [ -r /etc/default/${SLIMSRVC} ]; then
	. /etc/default/${SLIMSRVC}
else
	SLIMUSER='lms'
	SLIMGROUP=$(id -ng $SLIMUSER)
	SLIMBRANCH="7.8"
	SLIMDESC="LMS branch ${SLIMBRANCH} git code"
fi

SLIMREPO='https://github.com/Logitech/slimserver.git'
LOCALREPO="/usr/share/${SLIMSRVC}/server"
SLIMBRANCHES=
DAEMON="${LOCALREPO}/slimserver.pl"
DAEMON_SAFE="/usr/sbin/${SLIMSRVC}_safe"
PIDFILE="/var/run/${SLIMSRVC}.pid"
SCRIPTNAME="$(basename $0)"
PREFSDIR="/var/lib/${SLIMSRVC}/prefs"
LOGDIR="/var/log/${SLIMSRVC}/"
VCLOG="${LOGDIR}/git.log"
CACHEDIR="/var/lib/${SLIMSRVC}/cache"
CHARSET='utf8'
SLIMOPTIONS=

if [ -d "${LOCALREPO}/.git" ]; then
	VCUTIL='git'
elif [ -d "${LOCALREPO}/.svn" ]; then
	VCUTIL='svn'
fi

SLIMDESC="LMS branch ${SLIMBRANCH} ${VCUTIL} code"
VCLOG="${LOGDIR}/${VCUTIL}.log"


############################################################################
# Service control functions
############################################################################

d_check_running() {
	if [ -e $PIDFILE ]; then
		pidofproc -p "$PIDFILE" "$DAEMON" > /dev/null 2>&1 && status=0 || status=$?
		if [ $status = 0 ]; then
			log_daemon_msg "${SLIMDESC} is already running"
			log_end_msg 0
			exit 0
		fi
	fi
}

d_start() {
	d_check_running
	log_daemon_msg "Starting" "$SLIMDESC"

	# Use lms_safe to restart the daemon when
	# it dies. This must be done to handle mysql restarts.
	if start-stop-daemon --start --quiet \
		--chuid $SLIMUSER \
		--pidfile $PIDFILE \
		--exec $DAEMON_SAFE \
		--background \
		--make-pidfile \
		-- \
		$DAEMON \
		--prefsdir $PREFSDIR \
		--logdir $LOGDIR \
		--cachedir $CACHEDIR \
		--charset=$CHARSET \
		$SLIMOPTIONS ; then
		log_end_msg 0
	else
		log_end_msg 1
	fi
}

# This starts lms without the safe script..
d_start_direct() {
	d_check_running
	log_daemon_msg "Starting" "$SLIMDESC"

	# Make the pid file writeable by lms
	touch $PIDFILE
	chown "${SLIMUSER}:${SLIMGROUP}" $PIDFILE

	if start-stop-daemon --start --quiet \
		--chuid $SLIMUSER \
		--pidfile $PIDFILE \
		--exec $DAEMON \
		--background \
		--make-pidfile \
		-- \
		--pidfile $PIDFILE \
		--prefsdir $PREFSDIR \
		--logdir $LOGDIR \
		--cachedir $CACHEDIR \
		--charset=$CHARSET \
		$SLIMOPTIONS ; then
		log_end_msg 0
	else
		log_end_msg 1
	fi
}

d_stop() {
	if [ -e $PIDFILE ]; then
		status_of_proc -p "$PIDFILE" "$DAEMON" "$SLIMDESC" > /dev/null 2>&1 && status=0 || status=$?
		if [ $status -eq 0 ]; then
			log_daemon_msg "Stopping" "$SLIMDESC"
			if start-stop-daemon --oknodo --stop --quiet --pidfile "$PIDFILE" --retry=TERM/30/KILL/5 ; then
				/bin/rm -rf $PIDFILE
				log_end_msg 0
			else
				log_end_msg 1
			fi
		fi
	else
		# status 3: program is not running, pid file not found..
		status=3
	fi

	if [ $status -gt 0 ]; then
		# status 1: /var/run pid file exists but program is not running..
		log_daemon_msg "${SLIMDESC} is not running"
	fi
	return $status
}

d_reload() {
#	Send a SIGHUP signal to the daemon/service.
	start-stop-daemon --stop --quiet --pidfile $PIDFILE --signal 1
}

############################################################################
# git & svn repository support functions
############################################################################

date_msg(){
	DATE=$(date '+%F %H:%M:%S.%N')
	DATE=${DATE#??}
	DATE=${DATE%?????}
	echo "[${DATE}] $(basename $0) ($$)" $@
}


#---------------------------------------------------------------------------
# Check to see we are where we are supposed to be..
git_in_repo(){
	if [ $(pwd) != "$LOCALREPO" ]; then
		log_daemon_msg "Error: ${LOCALREPO} not found."
		log_end_msg 3
		exit 128
	fi
}

#---------------------------------------------------------------------------
# Show the current status and avilable branches of the repo..
git_show_status(){
	cd "$LOCALREPO" && git_in_repo
	if [ -d './.git' ]; then
		git remote show origin
		git status
	elif [ -d './.svn' ]; then
		svn status  --show-updates
	fi

}

#---------------------------------------------------------------------------
# Discard any local changes from the repo..
git_clean(){
	cd "$LOCALREPO" && git_in_repo
	if [ -d './.git' ]; then
		git reset --hard
		git clean -fd
	elif [ -d './.svn' ]; then
		svn revert -R .
	fi

}

#---------------------------------------------------------------------------
# Update the repo..
git_update(){
	cd "$LOCALREPO" && git_in_repo
	date_msg >>"$VCLOG"
	if [ -d './.git' ]; then
		git pull | tee -a "$VCLOG"
	elif [ -d './.svn' ]; then
		svn up | tee -a "$VCLOG"
	fi 
	return $?
}

#---------------------------------------------------------------------------
# Get a list of the available branches..
git_get_branches(){
	cd "$LOCALREPO" && git_in_repo
	SLIMBRANCHES=`git branch -r | sed -n -e 's#^.*origin/\(.*\)$#\1#p'`
}

#---------------------------------------------------------------------------
# Display the available branches..
git_disp_branches(){
	if [ -z "$SLIMBRANCHES" ]; then
		git_get_branches
	fi
	echo ' '
	for BRANCH in $SLIMBRANCHES
	do
		printf "\t${BRANCH}\n"
	done
}

#---------------------------------------------------------------------------
# Check to see that the new branch is a branch..
git_is_branch(){
	ISGOODBRANCH=0

	if [ -z "$SLIMBRANCHES" ]; then
		git_get_branches
	fi

	for BRANCH in $SLIMBRANCHES
	do
		if [ "$SLIMBRANCH" = "$BRANCH" ]; then
			ISGOODBRANCH=1
		fi
	done

	if [ $ISGOODBRANCH -lt 1 ]; then
		echo "Error: ${SLIMBRANCH} is not a branch of ${SLIMREPO}"
		git_disp_branches
		echo "${SCRIPT} must exit."
		exit 1
	fi
}

git_create_dirs(){
	
	INSTPATH="/var/lib/${SLIMSRVC}_data/${SLIMBRANCH}"
	if [ ! -d "$INSTPATH" ]; then
		echo "Preparing the lib dir ${INSTPATH}"
		mkdir -p "$INSTPATH"
	fi
	
	# Create a home for static plugins..this won't change when switching branches,
	# so the same plugin can be easily tested against different branches without
	# needing to reinstall.
	
	INSTPATH="/var/lib/${SLIMSRVC}_data/Plugins"
	if [ ! -d "$INSTPATH" ]; then
		echo "Preparing the lib dir ${INSTPATH}"
		mkdir -p "$INSTPATH"
	fi
	
	chown -R "${SLIMUSER}:${SLIMGROUP}" "/var/lib/${SLIMSRVC}_data"
	
	INSTPATH="/var/log/${SLIMSRVC}_log/${SLIMBRANCH}"
	if [ ! -d "$INSTPATH" ]; then
		echo "Preparing the log dir ${INSTPATH}"
		mkdir -p "$INSTPATH"
	fi
	chown -R "${SLIMUSER}:${SLIMGROUP}" "/var/log/${SLIMSRVC}_log"
}

#------------------------------------------------------------------------------
# create_links() -- Link the data, Plugins and log directories..
#------------------------------------------------------------------------------
git_create_links(){
	# Create new data & log links
	LIBDIR="/var/lib/${SLIMSRVC}_data/${SLIMBRANCH}"
	LIBDIRLINK="/var/lib/${SLIMSRVC}"

	LOGDIR="/var/log/${SLIMSRVC}_log/${SLIMBRANCH}"
	LOGDIRLINK="/var/log/${SLIMSRVC}"

	#static plugin dir...doesn't change when switching branches..
	PLUGINDIR="/var/lib/${SLIMSRVC}_data/Plugins"
	PLUGINDIRLINK="${LOCALREPO}/Plugins"
	
	if [ -L "$LIBDIRLINK" ]; then
		rm "$LIBDIRLINK"
	fi
	
	if [ ! -d "$LIBDIRLINK" ]; then
		echo "Linking ${LIBDIRLINK} to ${LIBDIR}.."
		ln -s "$LIBDIR" "$LIBDIRLINK"
	fi
	
	if [ -L "$LOGDIRLINK" ]; then
		rm "$LOGDIRLINK"
	fi
	
	if [ ! -d "$LOGDIRLINK" ]; then
		echo "Linking ${LOGDIRLINK} to ${LOGDIR}.."
		ln -s "$LOGDIR" "$LOGDIRLINK"
	fi
	
	if [ -L "$PLUGINDIRLINK" ]; then
		rm "$PLUGINDIRLINK"
	fi
	
	if [ ! -d "$PLUGINDIRLINK" ]; then
		echo "Linking ${PLUGINDIRLINK} to ${PLUGINDIR}.."
		ln -s "$PLUGINDIR" "$PLUGINDIRLINK"
	fi
}

git_switch_branch(){
	cd "$LOCALREPO" && git_in_repo

	# Discard any local changes
	git_clean

	#check out the new branch..
	git checkout "$SLIMBRANCH"
	
	if [ $? -gt 0 ]; then
		log_daemon_msg "Error checking out branch ${SLIMBRANCH}."
		log_end_msg 1
		exit 1
	fi
	
	# Update the default file with the name of the new branch
	UCSLIMSRVC=`echo "$SLIMSRVC" | tr '[:lower:]' '[:upper:]'`
	SLIMDESC="${UCSLIMSRVC} branch ${SLIMBRANCH} git code"

	# Escape SLIMDESC..
	#SLIMDESC="$(echo "$SLIMDESC" | sed -e 's/\//\\\//g')"
	#SLIMDESC="$(echo "$SLIMDESC" | sed -e 's/\./\\\./g')"

	RE="s#^SLIMDESC=.*\$#SLIMDESC=\"${SLIMDESC}\"#"
	sed -i -e "$RE" "/etc/default/${SLIMSRVC}"
	
	RE="s#^SLIMBRANCH=.*\$#SLIMBRANCH=\"${SLIMBRANCH}\"#"
	sed -i -e "$RE" "/etc/default/${SLIMSRVC}"
	
	#create new data & log dirs..
	git_create_dirs
	#create new data & log links..
	git_create_links
}

############################################################################
# More service control functions
############################################################################

d_update() {
	log_daemon_msg "Updating $SLIMDESC"
	git_update && status=0 || status=$?
	if [ $status -eq 0 ]; then
		log_daemon_msg "${SLIMDESC} has ben updated."
	else
		log_daemon_msg "Error updating ${SLIMDESC}."
	fi
}

d_git_update() {
	log_daemon_msg "Git Updating ${SLIMDESC}"
	git_clean
	git_update && status=0 || status=$?
	if [ $status -eq 0 ]; then
		log_daemon_msg "${SLIMDESC} has been updated."
	else
		log_daemon_msg "Error updating ${SLIMDESC}."
	fi
	if [ -x /usr/local/sbin/config-lms-customize.sh ]; then
		log_daemon_msg "Customizing ${SLIMDESC} code.."
		/usr/local/sbin/config-lms-customize.sh "$SLIMSRVC"
	fi
}

d_show_branches() {
	log_daemon_msg "Available branches in ${LOCALREPO}:"
	git_disp_branches
}

d_switch_branch() {
	if [ ! -z "$SLIMBRANCH" ]; then
		log_daemon_msg "Switching ${SLIMDESC} to ${SLIMBRANCH}"
		git_switch_branch
	else
		log_action_msg "Error: branch name required."
		git_disp_branches
		exit 2
	fi

}


d_is_scanning() {
	if [ ! -z "$(pgrep -fn "perl.*/$SLIMSRVC/.*scanner\.pl")" ]; then
		log_daemon_msg "${SLIMDESC} is scanning"
		return 1
	fi
}

d_dbwipe() {
	if [ -d "$CACHEDIR" ]; then
		log_daemon_msg "Deleting *.db files from $(readlink -f ${CACHEDIR}).."
		log_end_msg 0
		/usr/bin/find "$(readlink -f $CACHEDIR)" -maxdepth 1 -type f -name "*.db" -delete

		log_daemon_msg "Deleting __db.* files from $(readlink -f ${CACHEDIR}).."
		log_end_msg 0
		/usr/bin/find "$(readlink -f $CACHEDIR)" -maxdepth 1 -type f -name '__db.*' -delete

		log_daemon_msg "Library rescan will automatically initiate with next start.."
		log_end_msg 0
	fi
}

d_status() {
	d_is_scanning

	if [ -e $PIDFILE ]; then
		status_of_proc -p "$PIDFILE" "$DAEMON" "$SLIMDESC" && exit 0 || exit $?
	else
		log_daemon_msg "${SLIMDESC} is not running"
		log_daemon_msg "Getting ${LOCALREPO} repository status.."
		git_show_status
		log_end_msg 3
	fi
}

############################################################################
# Process service control requests..
############################################################################

if [ ! -x "$DAEMON" ]; then
	log_daemon_msg "${DAEMON} not found."
	log_end_msg 5
	exit 5
fi

if [ ! -x "$DAEMON_SAFE" ]; then
	log_daemon_msg "${DAEMON_SAFE} not found."
	log_end_msg 5
	exit 5
fi


case "$1" in
	start)
		d_start
		;;
	start-direct)
		d_start_direct
		;;
	stop)
		d_stop
		;;
		#  reload)
		#	d_reload
		#	;;
	restart|force-reload)
		d_stop
		sleep 3
		d_start
		;;
	rescan|wipe|wipedb)
		# Don't wipe the db if we're scanning..
		d_is_scanning
		if [ $? -gt 0 ]; then
			log_daemon_msg "Cannot wipe *.db files while scanning"
			log_end_msg 1
			exit 1
		fi
		d_stop
		sleep 3
		d_dbwipe
		sleep 3
		d_start
		;;
	clean|git-clean)
		d_stop
		sleep 3
		git_clean
		d_start
		;;
	update|git-update|svn-update)
		d_stop
		sleep 3
		d_git_update
		sleep 3
		d_start
		;;
	show-branches|list-branches|branches)
		d_show_branches
		;;
	branch|switch-branch)
		if [ ! -z "$2" ]; then
			SLIMBRANCH="$2"
			#echo "New Branch: ${SLIMBRANCH}"
			d_stop
			sleep 3
			d_switch_branch
			sleep 3
			d_start
		else
			log_action_msg "Error: branch name required."
			d_show_branches
			exit 2
		fi
		;;
	status)
		d_status
		;;
	*)
		log_action_msg "Usage: $(which service) $(basename $0) {start|stop|restart|rescan|git-clean|git-update|list-branches|switch-branch [branchname]|status}"
		exit 2
		;;
esac

exit $?
