#!/bin/sh
#
# Swf2Avi-0.4
# A script to convert a Flash media file to AVI
# Author: Rick Harris	rickfharris@yahoo.com.au
#
# Tools required:	Flashplayer	-> http://www.macromedia.com/
#			X11		-> http://xorg.freedesktop.org/
#			Wmctrl		-> http://sweb.cz/tripie/utils/wmctrl/
#			Xautomation	-> http://hoopajoo.net/projects/xautomation.html
#			Xvidcap		-> http://xvidcap.sourceforge.net/
#			Swftools	-> http://www.quiss.org/swftools/
#			Esound		-> http://www.tux.org/~ricdude/EsounD.html
#			FFmpeg		-> http://ffmpeg.sourceforge.net/
#			Wavsplit	-> http://sourceforge.net/projects/wavsplit/
#
# NOTE: * Esound breaks with compiled alsa support in later 2.6.x kernels, compile Esound with './configure --disable-alsa'
#	  To have it then work with alsa, ensure the kernel module 'snd_pcm_oss' is modprobed
#	* It captures flash video pictures directly from the desktop & audio from the
#	  soundcard, so avoid moving the flashplayer window, clicking in the desktop, or
#	  playing any other audio through the sound card while the conversion is taking place
#	* For audio capture to work, adjust your mixer settings & set 'capture' & 'mixer' channels to record/capture
#	* For the script to operate at it's optimum, it needs access to the 'nice'
#	  command. Unfortunately this means running the script as root :|
#	* It also requires a fairly modern system to be able to capture at full
#	  frame-rate.
#	  A slow or busy CPU will result in dropped frames & so bad A/V sync will result.
#	  For this reason it is recommended that it be run in a minimalist Window Manager such
#	  as TWM or Fluxbox etc. (not Gnome or KDE)
#
##############################################################################################

TOOLKIT="esd ffmpeg gflashplayer swfdump wmctrl Xvfb xte xvidcap"

if [ `/usr/bin/whoami` != "root" ]; then
echo "This script requires super-user privileges to set process priority"
echo "Therefore, you must be root to run this script"
exit
fi

help_text () {
echo "swf2avi-0.4"
echo "Usage: $0 [options] -i input_file(s).swf"
echo "--width		Set resolution width, height is calculated using original's aspect ratio	(Default: 352)"
echo "--croptop	Set value to crop from top							(Default: 15)"
echo "--autoplay	Set flash file to autoplay on execution (workaround for mouse click to start)	(Default: Disabled)"
echo "--delay_video	Set video delay in seconds							(Default: 0.8)"
exit 0
}

until [ -z "$1" ] ; do
 case "$1" in
--width) shift; USER_WIDTH=$1;;
--croptop) shift; USER_CROP=$1;;
--autoplay) shift; AUTO_PLAY=1;;
--delay_video) shift; DELAY_VIDEO=$1;;
-i) shift; input_files="$@" ;;
-h) help_text ;;
*) shift ;;
 esac
done

errmsg () {
 echo "$*" > /dev/stderr
}

testprog () {
 for p in $(echo $PATH | sed "s/:/\ /g"); do
  if [ -x "$p/$1" ]; then
   return 0
  fi
 done
 errmsg "Program '$1' is missing, please install it first."
 errmsg "A full list of tools needed can be found inside this script."
 return 1
}

check_tools () {
 for prog in $TOOLKIT; do
  testprog $prog || exit 0;
 done
 return 0
}

######################################################################################################



vars () {
trap "echo Interrupted; exit 2" 2
NAME=`echo $1 | sed 's/.\{4\}$//'`

DURATION=`swfdump $1 | tail -n2 | grep SHOWFRAME | cut -d"(" -f2 | cut -d, -f1`
HOUR=`echo $DURATION | cut -d: -f1`
MIN=`echo $DURATION | cut -d: -f2`
SECS=`echo $DURATION | cut -d: -f3`
SECS_PHOUR=`perl -le "print ( ($HOUR *60) * 60 )"`
SECS_PMIN=`perl -le "print ( $MIN * 60 )"`
TIME=`perl -le "print ( $SECS_PHOUR + $SECS_PMIN + $SECS )"`
}



video_capture () {
if [ ! -z $USER_CROP ]; then
echo "Using croptop value: $USER_CROP"
CROP_TOP=$USER_CROP
else
CROP_TOP=15
fi

SWF_HEIGHT=`swfdump $1 | grep "Movie height" | awk '{print $4}' | cut -d. -f1`

DISPLAY_CHECK=`echo $DISPLAY`
if [ -z $DISPLAY_CHECK ]; then
/usr/X11R6/bin/Xvfb :1 -screen 0 1024x768x16 &> /dev/null &
export DISPLAY=":1.0"
fi

nice -n -10 gflashplayer $1 &
sleep 0.5s

WIN_STAT=`/usr/X11R6/bin/xwininfo -int -root -tree | grep "Macromedia Flash" | sed 's/^[ \t]*//'`
WIN_ID=`echo $WIN_STAT | awk '{print $1}'`
WIDTH=`echo $WIN_STAT | cut -d")" -f2 | awk '{print $1}' | cut -d+ -f1 | cut -dx -f1`
WIN_HEIGHT=`echo $WIN_STAT | cut -d")" -f2 | awk '{print $1}' | cut -d+ -f1 | cut -dx -f2`
POS_HORZ=300
POS_VERT=300

wmctrl -i -r $WIN_ID -b toggle,above

echo "Window Geometry: "$WIDTH"x"$WIN_HEIGHT""
echo "SWF Geometry: "$WIDTH"x"$SWF_HEIGHT""
HEIGHT_DIFF=`perl -le "print ( $WIN_HEIGHT - $SWF_HEIGHT )"`

### Get SWF Aspect Ratio ###
REV_ASPECT=`perl -le "print ( $SWF_HEIGHT / $WIDTH )"`
############################

### Set NEW SWF_HEIGHT based on reverse aspect ratio ###
if [ ! -z $USER_WIDTH ]; then
echo "Using width value: $USER_WIDTH"
WIDTH=$USER_WIDTH
else
WIDTH=352
fi
SWF_HEIGHT=`perl -le "print int( $WIDTH * $REV_ASPECT )"`
########################################################

let WIN_HEIGHT=$SWF_HEIGHT+$HEIGHT_DIFF+20       

### Even up capture width/height to even integers ###
WIDTH=`perl -le "print int( $WIDTH / 2 )"`
let WIDTH=$WIDTH*2
SWF_HEIGHT=`perl -le "print int( $SWF_HEIGHT / 2 )"`
let SWF_HEIGHT=$SWF_HEIGHT*2
#####################################################

echo "Revised resolution is: "$WIDTH"x"$SWF_HEIGHT""
wmctrl -i -r $WIN_ID -e 0,+300,+300,"$WIDTH","$WIN_HEIGHT"

if [ ! -z $AUTO_PLAY ]; then
xte 'mousemove 300 300' 'keydown Control_L' 'key p' 'keyup Control_L'
fi
xte 'mousemove 0 0'

## Cropping section ##
CROP_RHS=8
CROP_LHS=6
let WIDTH=$WIDTH-$CROP_RHS
let POS_HORZ=$POS_HORZ+$CROP_LHS
let POS_VERT=$POS_VERT+$CROP_TOP+$HEIGHT_DIFF

echo "Running: nice -n -15 xvidcap --time $TIME --gui no --file "$NAME".avi --cap_geometry "$WIDTH"x"$SWF_HEIGHT"+"$POS_HORZ"+"$POS_VERT""
nice -n -15 xvidcap --time $TIME --gui no --file "$NAME".avi --cap_geometry "$WIDTH"x"$SWF_HEIGHT"+"$POS_HORZ"+"$POS_VERT"
xte 'mousemove 300 300' && \
xte 'keydown Control_L' 'key q' 'keyup Control_L'
}



audio_capture () {
if [ -f "$NAME".wav ]; then
rm -f "$NAME".wav
fi
if [ -z `pidof esd` ]; then
esd -d /dev/dsp &
sleep 2s
fi
nice -n -18 gflashplayer $1 &
sleep 0.5s
WIN_STAT=`/usr/X11R6/bin/xwininfo -int -root -tree | grep "Macromedia Flash" | sed 's/^[ \t]*//'`
WIN_ID=`echo $WIN_STAT | awk '{print $1}'`
echo "Running: wmctrl -i -r $WIN_ID -e 0,+300,+300,"$WIDTH","$WIN_HEIGHT""
wmctrl -i -r $WIN_ID -e 0,+300,+300,"$WIDTH","$WIN_HEIGHT"
if [ ! -z $AUTO_PLAY ]; then
xte 'mousemove 300 300' 'keydown Control_L' 'key p' 'keyup Control_L'
fi
echo "Running: nice -n -15 ffmpeg -ad /dev/dsp -ar 44100 -ab 224 -ac 2 -t $TIME "$NAME".wav"
nice -n 18 ffmpeg -ad /dev/dsp -ar 44100 -ab 224 -ac 2 -t $TIME "$NAME".wav
xte 'mousemove 300 300' && \
xte 'keydown Control_L' 'key q' 'keyup Control_L'
if [ -z $DELAY_VIDEO ]; then
DELAY_VIDEO=0.8
else
echo "Using video_delay value: $DELAY_VIDEO"
fi
wavsplit -s "$NAME".wav $DELAY_VIDEO
}



mux () {
echo "Running: avidemux2 --load "$NAME".avi --external-wav "$NAME"/02.wav --save "$NAME"_final.avi --quit"
avidemux2 --load "$NAME".avi --external-wav "$NAME"/02.wav --save "$NAME"_final.avi --quit 2>&1 > /dev/null
mv -f "$NAME"_final.avi "$NAME".avi
rm -rf "$NAME".wav $NAME
killall -9 Xvfb &> /dev/null
}



main () {
for file in $input_files ; do
if [ ! -f "$file" ]; then
errmsg "'$file' does not exist"
exit 1
fi
check_tools
vars $file
echo ""
echo "**    HANDS AWAY FROM KEYBOARD & MOUSE     **"
echo "** Do nothing until conversion is finished **"
echo ""
echo "First of two passes, capturing video..."
echo ""

video_capture $file

echo ""
echo "Second pass, capturing audio..."
echo ""

audio_capture $file

mux

echo "Done!"
echo "New file is "$NAME".avi"
done
}


main
