#!/bin/bash

# Written by Bob Igo from the MythTV Store at http://MythiC.TV
# with contributions from TJC and Sarah Hayes
# Email: bob@stormlogic.com
#
# If you run into problems with this script, please send me email
#
# Maintained by Michael Hanson <mihanson@linhes.org>
#

# This is alpha code to auto-generate thumbnails for previews in MythVideo.
# It won't currently work on some filenames that have spaces in them.
# It's surely just a matter of escaping or quoting, but I have yet to find
# the right incantation.

# example usage:
# find -L /myth/video -wholename '*.covers' -prune -o -name '*.resume' -o -type f -exec screenshooter.sh -v {} \;

# limitations:
# --
# In an MBE/SBE/FE setup this might get the settings for the wrong machine...
# The script has no AI to know if a grabbed frame is useful to identify the video, only that it was able to grab it.
# Doesn't clean up after itself if videos are deleted, though MythTV may do this on its own.
# Minimum theoretical compatible video length is 4 seconds.  Shorter videos will not work with this version.
# Surely more limitations I can't think of because it's my baby :)

Usage() {
    echo "USAGE:"
    echo `basename $0` "-f FILENAME [-s SECONDS] [-c] [-b HOSTNAME] [-u USERNAME] [-p PASSWORD] [-v]"
    echo "-f: video filename"
    echo "-s: number of Seconds to skip before capturing (270 by default)"
    echo "-c: Clobber any previous screenshot found for this video (off by default)"
    echo "-b: mysql server (Backend) hostname (default: dbhost in /etc/systemconfig)"
    echo "-u: mysql Username (mythtv by default)"
    echo "-p: mysql Password (mythtv by default)"
    echo "-v: verbose mode (off by default)"
    echo "-x: check for valid video eXtension (off by default)"
    echo
    echo "EXAMPLE: $0 -f shuttle.mpg -c -s 30"
    exit 3
}

. /etc/systemconfig

if [ -z $1 ]; then
    Usage
fi

F_MISSING=1

while getopts "f:sbupvcx" FLAG ; do
    case "$FLAG" in
	f) FILENAME="$OPTARG"
	    F_MISSING=0;;
	s) SKIPAHEAD="$OPTARG";;
	c) CLOBBER=1;;
	b) BACKEND_HOSTNAME="$OPTARG";;
	u) DBUSERNAME="$OPTARG";;
	p) DBPASSWORD="$OPTARG";;
	v) VERBOSE=1;;
	x) EXTENSION_CHECK=1;;
	*) Usage;;
    esac
done

if [ $F_MISSING == 1 ]; then
    Usage
fi

# Declaring Variables here and assigning sensible defaults.

# SKIPAHEAD is the number of seconds to skip ahead before starting the frame capture.
# Set it to an arbitrary value if none is specified.
SKIPAHEAD=${SKIPAHEAD:-"270"}
BACKEND_HOSTNAME=${BACKEND_HOSTNAME:-${dbhost}}
DBUSERNAME=${DBUSERNAME:-"mythtv"}
DBPASSWORD=${DBPASSWORD:-"mythtv"}
# Defaults to quiet.
VERBOSE=${VERBOSE:-0}
# Unless otherwise told, do not clobber existing cover files.
CLOBBER=${CLOBBER:-0}
# Unless otherwise told, do not check the file extension against
# MythTV's list of registered video file types.
EXTENSION_CHECK=${EXTENSION_CHECK:-0}

SG_VIDEOS=$(mysql -u $DBUSERNAME -p$DBPASSWORD -h $BACKEND_HOSTNAME -D mythconverg -sNBe \
            "SELECT dirname FROM storagegroup WHERE groupname='Videos'")
if [ ! -d "${SG_VIDEOS}" ] ; then
    echo "Directory $SG_VIDEOS does not exist, nowhere to put the screen shot!"
    echo "Have you configured Storage Groups yet?"
    exit 1
fi

SG_SCREEN=$(mysql -u $DBUSERNAME -p$DBPASSWORD -h $BACKEND_HOSTNAME -D mythconverg -sNBe \
            "SELECT dirname FROM storagegroup WHERE groupname='Screenshots'")
if [ ! -d "${SG_SCREEN}" ] ; then
    echo "Directory $SG_SCREEN does not exist, nowhere to put the screen shot!"
    echo "Have you configured Storage Groups yet?"
    exit 1
fi

VIDEO_EXTENSION=${FILENAME##*.}
# Since we cron'd lets first make sure the validity of the file
if [ "$EXTENSION_CHECK" == "1" ]; then
    EXCHECK=$(mysql -u $DBUSERNAME -p$DBPASSWORD -h $BACKEND_HOSTNAME -D mythconverg -sNBe "select f_ignore from videotypes where extension='${VIDEO_EXTENSION}';")
    #excheck returns blank, it found nothing.
    if [ "$EXCHECK" == "" ]; then
	if [ "$VERBOSE" == "1" ]; then
	    echo "$VIDEO_EXTENSION does not appear to be a valid media file, skipping."
	fi
	exit 1
    else
	# It is valid, but should we ignore it.  If so then excheck will equal 1.
	if [ "EXCHECK" == "1" ]; then
	    if [ "$VERBOSE" == "1" ]; then
		echo "$VIDEO_EXTENSION is set to ignore."
	    fi
	    exit 1
	fi
	# It is valid, it's not set to ignore.
	if [ "$VERBOSE" == "1" ]; then
	    echo "$VIDEO_EXTENSION appears in the Database, checking further."
	fi
	EXCHECK=$(mysql -u $DBUSERNAME -p$DBPASSWORD -h $BACKEND_HOSTNAME -D mythconverg -sNBe "select title from videometadata where filename LIKE '%${FILENAME}';")
	#Right, the file is supposed to be playable.  Has it been imported to the Db yet?
	if [ "$EXCHECK" == "" ] ; then
	    if [ "$VERBOSE" == "1" ]; then
		echo "$VIDEO_FILENAME does not exist in the database."
	    fi
	    exit 1
	fi
    fi
fi

if [ "$CLOBBER" -eq 0 ]; then
      # Since we're not clobbering, first check to see if this video already has a coverfile entry in MySQL:
    SQL_CMD="SELECT coverfile FROM videometadata WHERE filename LIKE '%${FILENAME}';"
    CURRENT_COVERFILE=`mysql -u $DBUSERNAME -p$DBPASSWORD -h $BACKEND_HOSTNAME -D mythconverg -B -e "$SQL_CMD" | tail -1`

    if [[ "$CURRENT_COVERFILE" != "" ]] && [[ "$CURRENT_COVERFILE" != " " ]] && [[ "$CURRENT_COVERFILE" != "No Cover" ]]; then
  	  # there's already a cover file for this video
  	if [ "$VERBOSE" == "1" ]; then
	    echo "$FILENAME has cover file, skipping."
	fi
	exit 2
    fi
fi


# Swap the video file extension for png.  Should work assuming the extension only appears ONCE!
VIDEO_CAPTURE_PATHNAME="$SG_SCREEN/${FILENAME%.*}.png"

# How many frames of video to capture.  We'll grab the last frame as our screenshot.
if [ "$VIDEO_EXTENSION" == "m4v" ]; then
    FRAMES_TO_CAPTURE="90"
else
    FRAMES_TO_CAPTURE="05"
fi

SHOTFILE="000000"$FRAMES_TO_CAPTURE".png"
VIDEO_STATS="/tmp/screenshooter_video_stats.txt"

# Get the full path of the video file, less the storage group prefix
FULL_PATH=$(mysql -u $DBUSERNAME -p$DBPASSWORD -h $BACKEND_HOSTNAME -D mythconverg -sNBe \
            "SELECT filename FROM videometadata WHERE filename LIKE '%${FILENAME}';")

cd /tmp

# The video we're processing may be shorter than SKIPAHEAD seconds.
# Keep trying to capture until we find a SKIPAHEAD value within the length of the video.
# Give up if we reach 0 seconds.
while [ ! -f "$SHOTFILE" ]; do
    /usr/bin/mplayer -ss $SKIPAHEAD -vf scale=640:-2 -ao null -vo png -quiet -frames $FRAMES_TO_CAPTURE -identify "$SG_VIDEOS/$FULL_PATH" &> $VIDEO_STATS &
    TIMEOUT=9

    # Some video formats will play audio only. This loop gives the above command 20 seconds to
    # finish, otherwise it gets killed.
    while [ -n "`ps -p $! --no-heading`" ]; do
	TIMEOUT=$(expr $TIMEOUT - 1)
	if [ "$TIMEOUT" -le 0 ]; then
	    kill -9 $!
	    break
	fi
	sleep 1
    done

    SKIPAHEAD=$(expr $SKIPAHEAD / 2)
    if [ "$SKIPAHEAD" -le 0 ]; then
	break
    fi
done

if [ -f "$SHOTFILE" ]; then
    # Now, the video_capture is taken, and the name of the shot is in $SHOTFILE
    # Rename it and move it to the place where video_captures live.
    /bin/mv -f "$SHOTFILE" "$VIDEO_CAPTURE_PATHNAME"
    /bin/rm -f 000000*png
    chown mythtv: "$VIDEO_CAPTURE_PATHNAME"

    # We've got the shotfile nailed, now calculate video run length.
    VIDEO_LENGTH_IN_SECONDS=`grep ID_LENGTH $VIDEO_STATS | awk -F'=' '{print $2}'`
    VIDEO_LENGTH_IN_INTEGER_SECONDS=${VIDEO_LENGTH_IN_SECONDS/%.*/}
    if [ $VIDEO_LENGTH_IN_INTEGER_SECONDS -lt 60 ]; then
	VIDEO_LENGTH_IN_MINUTES="1"
    else
	VIDEO_LENGTH_IN_MINUTES=$(expr $VIDEO_LENGTH_IN_INTEGER_SECONDS / 60)
    fi

    SQL_CMD="UPDATE videometadata SET length = '${MIN_LENGTH}' WHERE filename LIKE '%$FILENAME';"
    mysql -u $DBUSERNAME -p$DBPASSWORD -h $BACKEND_HOSTNAME -D mythconverg -e "$SQL_CMD"

    # put the screenshot pathname and any runlength info into videometadatatable
    # Pre-escape any single or double quotes for the SQL command.

    VIDEO_CAPTURE_PATHNAME=`echo $VIDEO_CAPTURE_PATHNAME | sed -e "s/'/\\\'/g" -e 's/"/\\\"/g' `
    FILENAME=`echo $FILENAME | sed -e "s/'/\\\'/g" -e 's/"/\\\"/g' `
    SQL_CMD="UPDATE videometadata SET coverfile = '${VIDEO_CAPTURE_PATHNAME}', length = '${VIDEO_LENGTH_IN_MINUTES}' WHERE filename LIKE '%${FILENAME}';"

    mysql -u $DBUSERNAME -p$DBPASSWORD -h $BACKEND_HOSTNAME -D mythconverg -e "$SQL_CMD"
else
    echo "No image could be captured from $FILENAME"
    exit 1
fi