#!/bin/ash
# Rox desktop drive icon handler
# (C) James Budiono 2012, 2013, 2015, 2016
# License: GNU GPL Version 3 or later
#
# called by Rox, parameter $1 comes either from Args parameter from PinboardAdd,
# or from "option" attribute from AppInfo.xml
# Please see fatdog-drive-icon-udev-handler.sh for details.
#
# Supported parameters:
# - click $DEVNAME		- standard left-click, mount/umount device
# - umount $DEVNAME		- umount device
# - pmount				- launch drive mounter
# - explore $DEVNAME	- mount and open Rox folder (optical disc)
# - eject $DEVNAME		- close rox, unmount and eject (optical disc)
# - safe-remove $DEVNAME - prepare device for safe removal
# - defaultmediaplayer $DEVNAME - start defaultmediaplayer on the device
# - fsck $DEVNAME       - run fsck (or ntfscheck or dosfsck) on the device
# - usage				- launch disk usage utility
# - redraw				- redraw all icons
#
# $DEVNAME is the complete device name including /dev
#
# Note: this is a simple mount/unmount handler, no support for autorun etc.

### configurations
. $BOOTSTATE_PATH
PINBOARD_FILE=$HOME/.config/rox.sourceforge.net/ROX-Filer/PuppyPin
export PATH=$PATH:/lib64/udev:/lib/udev:/libexec
EVENTMANAGER_CONFIG=/etc/eventmanager
. $EVENTMANAGER_CONFIG # hotspot dimentions, UNPATCHED_ROX

################# non-root helpers ###############

# $1-devname
get_mount_point() {
	dmdev=$(ls -l /dev/mapper/* 2> /dev/null | awk -v dmdev=${1##*-} '$6 == dmdev {print $10; exit; }')
	[ "$dmdev" ] || dmdev=$(ls -l /dev/mapper/* 2> /dev/null | awk -v dmdev="/${1##*/}$" '$NF ~ dmdev { print $(NF-2); exit; }')	
	awk -v dev=$1 -v dmdev=$dmdev '$1 == dev || $1 == dmdev { print $2; exit; }' /proc/mounts	
}

# $1-mountpoint
open_rox_folder() {
	rox -d "$1" -x "$1"
}

### if mounted, check if click happens on the "x" sign, means user wants to unmount
# returns true - "x" clicked
check_for_umount() {
	set --  $ROX_PINBOARD_CLICK # $1-x, $2-y, $3-dx, $-dy
	# click in icon coordinates x,y; icon dimensions w,h (not used)
	local x=$1 y=$2 wi=$3 hi=$4
	local xh yh   wh hh ph   wb hb   xc yc
	
	[ -z $x ] && return 1 # no parameter, not pinboard, leave immediately	
	#Xdialog --msgbox "$x $y $wi $hi" 0 0	
	# pass in click coordinates, hotspot coordinates & hotspot dimensions
	awk -v x=$x -v y=$y \
	    -v xh=${HOTSPOT_X:-0} -v yh=${HOTSPOT_Y:-0} \
		-v wh=${HOTSPOT_W:-12} -v hh=${HOTSPOT_H:-12} -v ph=${HOTSPOT_P:-2} \
	'BEGIN {
		# hotspot semi-dimensions a.k.a. bulls-eye
		wb = (wh + ph) /2; hb = (hh + ph) /2;
		# click in hotspot-center coordinates
		xc = x - xh - wb; yc = y - yh - hb;
		# return 0 if hotspot-centered click is inside bulls-eye
		exit !( (xc < 0 ? -(xc) : xc) <= wb && (yc < 0 ? -(yc) : yc) <= hb )
	}'
	return # exit code from awk above
}

### override these functions with unpatched-ROX version when asked
if [ "$UNPATCHED_ROX" ]; then
### if mounted, check if click happens on the "x" sign, means user wants to unmount
# true - "x" clicked
check_for_umount() {
	local xy x y 
	
	# find the location of the click, relative to our "x" sign
	xy=$(grep $(dirname $0) $PINBOARD_FILE | xml2 2> /dev/null | sed -n '/@x/ {s/.*=//; s/$/-/; p}; /@y/ {s/.*=//; p}')
	set -- $(getcurpos)
	x=$(($1 - ${xy%%-*} + 24)) y=$(($2 - ${xy##*-} + 30)) # empirical based on 48x48 drive icons
	
	# if within our "x" range, unmount (checks based 12x12 "close" grid - see fatdog-mount-wrapper.sh)
	[ $x -le 14 -a $y -le 14 ] && return 0
	return 1
}
fi

################# root helpers ###############

### close Rox and un-mount
# $1-devname, $2-mount point
do_umount() {
	case "$2" in 
		$AUFS_ROOT*)
			Xdialog --title "Error" --infobox "${1##*/} is used by system, it cannot be un-mounted." 0 0 10000 
			return ;;
	esac

	# close all rox folders
	rox -D "$2"
	
	# umount - escalate to root if we are not root
	if [ $(id -u) -ne 0 ]; then	
		gtksu "Unmounting ${1##*/}" umount "$2"
	else 
		umount "$2"
	fi
	
	# prompt user if fails
	if [ $? -ne 0 ]; then
		if Xdialog --title "Error" --yesno "Unable to unmount ${1##*/}, it is currently used by the following process:
$(fuser -m $2 | xargs ps -o cmd -p | sed 's/CMD//')\n\n
Do you want me to stop them and try again?" 0 0; then
			fuser -m -k $2
			do_umount $1 "$2"
		fi
	fi
}

### mount (if not already mounted), and open Rox
# $1-devname, $2-mount point
do_mount() {
	mountpoint=/mnt/${1##*/} 
	if /usr/sbin/fatdog-drive-icon-mount-helper.sh $1 $mountpoint; then open_rox_folder $mountpoint
	else Xdialog --title "Error" --infobox "Cannot mount ${1##*/}." 0 0 10000
	fi
}

### play media, if possible. Does not return unless it can't play the media.
# $1-devname $2-mounted (blank if not mounted)
play_media() {
	local mountpoint=${2:-/mnt/${1##*/}}
	echo $mountpoint
	case $(disktype $1) in 
		*"Audio track"*) 
			if [ -x /usr/local/bin/defaultcdplayer ];then 
				exec defaultcdplayer $1
			else
				exec defaultmediaplayer cdda://$1
			fi
			;;
		
		*"CDI_VCD"*) 
			defaultmediaplayer vcd://$1
			;;
		
		*)  # could be dvd, bluray, or data - mount to check
			if [ "$2" ] || /usr/sbin/fatdog-drive-icon-mount-helper.sh $1 $mountpoint; then
				if [ -d $mountpoint/BDMV -o -d $mountpoint/bdmv ]; then				# bluray
					grep -q 'vlc' /etc/defaultprograms && exec defaultmediaplayer --fullscreen --disc-caching=1000 bluray:///$mountpoint
					grep -q 'xine' /etc/defaultprograms && exec defaultmediaplayer bluray:///$mountpoint
					
				elif [ -d $mountpoint/VIDEO_TS -o -d $mountpoint/AUDIO_TS ] ||
				     [ -d $mountpoint/video_ts -o -d $mountpoint/audio_ts ]; then	# video dvd
					[ -x /usr/local/bin/defaultdvdplayer ] && exec defaultdvdplayer $1
					grep -q 'mplayer' /etc/defaultprograms && exec defaultmediaplayer dvdnav://$1
					grep -q 'vlc' /etc/defaultprograms && exec defaultmediaplayer --disc-caching=1000 dvd://$1 
					grep -q 'xine' /etc/defaultprograms && exec defaultmediaplayer dvd://$1 
				else
					open_rox_folder $mountpoint		# everything else - data
				fi
			fi
	esac
}


################# main ##################
#Xdialog --infobox "$# $@" 0 0 10000
[ $# -eq 1 ] && set -- $1	# rox combines all params into one string, split it
if [ $# -eq 0 ]; then		# no param, assumed clicked outside pinboard
	p=${0%/AppRun}
	set -- click /dev/${p##*/}
fi

# $1 - action, $2-devname
[ $2 ] && mountpoint=$(get_mount_point $2)
case $1 in
	click) 
		if [ "$mountpoint" ]; then	# already mounted
			if check_for_umount; then do_umount $2 "$mountpoint"
			else
				case $2 in
					/dev/sr[0-9]*) play_media $2 "$mountpoint" ;;
					*) open_rox_folder "$mountpoint" ;;
				esac
			fi
		else
			case $2 in
				/dev/sr[0-9]*) play_media $2 ;;
				*) do_mount $2 ;;
			esac
		fi
		;;
		
	umount) 
		[ "$mountpoint" ] && do_umount $2 "$mountpoint"
		;;

	pmount)
		exec /usr/sbin/pmount
		;;
	
	### extra options for optical disk
	explore) 
		if [ "$mountpoint" ]; then open_rox_folder "$mountpoint"
		else do_mount $2 
		fi
		;;
		
	eject)
		[ "$mountpoint" ] && do_umount $2 "$mountpoint"
		[ $(id -u) -ne 0 ] && exec gtksu "Ejecting ${2##*/}" cdrom_id --eject-media $2
		cdrom_id --eject-media $2 > /dev/null
		;;
	
	defaultmediaplayer)
		play_media $2
		Xdialog --title "Error" --infobox "Not a playable media." 0 0 10000
		;;
		
	safe-remove)
		[ "$mountpoint" ] && do_umount $2 "$mountpoint"
		if case ${2##*/} in
			*mmc*) mmc-safe-remove ${2##*/} ;;
			*) usb-safe-remove ${2##*/} ;;
		esac; then 
			Xdialog --title "Success!" --infobox "${2##*/} is now safe for removal." 0 0 10000
		else
			Xdialog --title "Problem"  --infobox "${2##*/} cannot be removed because it is still in use." 0 0 10000
		fi
		;;
		
	fsck)
		if [ "$mountpoint" ]; then
			Xdialog --title "Problem" --infobox "Cannot check integrity when ${2##*/} is mounted. Please un-mount it first." 0 0 10000
		else
			[ $(id -u) -ne 0 ] && exec gtksu "Check ${2##*/} integrity" "$0" $1 $2
			tmpfifo=$(mktemp -p /tmp fatdog-drive-icon-fsck.XXXXXXXX)
			#mkfifo $tmpfifo/fifo # doesn't work, will buffer
					
			fstype=$(guess_fstype $2)
			case "$fstype" in
				ext*) fsck -y $2 1>$tmpfifo 2>&1 & ;;
				vfat*) dosfsck -a $2 1>$tmpfifo 2>&1 & ;;
				ntfs) ntfsfix $2 1>$tmpfifo 2>&1 & ;;
				f2fs) fsck.f2fs -a $2 1>$tmpfifo 2>&1 & ;;
				exfat) fsck.exfat $2 1>$tmpfifo 2>&1 & ;;
				*) echo "I don't know how to handle filesystem $fstype on ${2##*/}, sorry." > $tmpfifo & ;;
			esac
			XPID=$!
			Xdialog --title "Checking ${2##*/}" --backtitle "Click OK when finished." --no-cancel --tailbox $tmpfifo 20 80
			kill $XPID
			rm -rf $tmpfifo
		fi
		;;
		
	usage)
		exec /usr/sbin/fatdog-disk-usage.sh
		;;
		
	redraw)
		exec /usr/sbin/fatdog-drive-icon-redraw-icons.sh
		;;
esac
