blob: e8259abcd206625402a8ed39f446b37e9806a490 [file] [log] [blame]
#!/bin/bash
#
# Try to download a flash movie from current ff window.
#
# Downloads are kept in a cache directory of fixed size, oldest
# files are removed as required. Last download is kept with a
# fixed name such as 'svtplay.flv' or 'youtube.flv'. Older downloads
# are stored with names retrieved from source.
#
# Prerequisites:
# - One firefox window with a page containing a flash video on
# current DISPLAY.
#
# - The CACHE_DIR directory should exist or be possible to create.
#
# Multiple invocations:
# - A running instance initially blocks other instances from
# running to not mess with the ff state. Invocations during
# this time are logged but otherwise silently ignored.
#
# - Later attempts to start downloading to same location will kill
# running process and overwrite dl location.
#
# - Later attempts to start downloading to other locations runs in
# parallel.
#
# Dependencies:
# xdotool, xsel, get_flash_videos, zenity, xorg-x11-utils
#
# Bugs:
# Fragile, does not use stable API:s, just happens to work
# occasionally.
readonly FF_WINDOW_NAME='Mozilla Firefox'
readonly DEFAULTS_FILE='/etc/sysconfig/ff-get-flash-video'
readonly DEFAULT_CACHE_SIZE=5
function get_cachedir()
{
local xdg_setup_dirs="${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs"
test -r "$xdg_setup_dirs" && source "$xdg_setup_dirs"
dir=${XDG_DOWNLOAD_DIR:-$HOME}/flash
test -d $dir || mkdir $dir || echo "Cannot create $dir" >&2
echo $dir
}
[ -r $DEFAULTS_FILE ] && source $DEFAULTS_FILE
CACHE_DIR=${CACHE_DIR:-$( get_cachedir )}
CACHE_SIZE=${CACHE_SIZE:-$DEFAULT_CACHE_SIZE}
function usage()
{
cat <<EOF
Find out what flash video Firefox is running and download it.
Usage: $(basename $0) [options]
Options
-d <dir> Download directory, defaults to $CACHE_DIR.
-s <size> Cache size i.e., number of downloaded files kept.
Defaults to $CACHE_SIZE.
Assumes a single firefox window opened with a flash movie running.
EOF
}
function get_options()
{
while getopts 'd:s:h' opt; do
case $opt in
s) CACHE_SIZE=$OPTARG;;
d) CACHE_DIR=$OPTARG;;
h) usage; exit 0;;
*) usage; exit 1;;
esac
done
LOGFILE="$CACHE_DIR/flash-download.trace"
LOCK_FILE="$CACHE_DIR/.lock"
readonly CACHE_SIZE CACHE_DIR LOGFILE LOCK_FILE
}
function error_msg() { zenity --error --timeout=4 --text="$1"; }
function warning_msg() { zenity --warning --timeout=4 --text="$1"; }
function info_msg() { zenity --info --timeout=4 --text="$1"; }
function get_size()
# Return size of single file argument on stdout, no file returns "0".
{
if [ -f $1 ]; then
ls -l $1 | awk '{print $5}'
else
echo "0"
fi
}
function get_ff_window()
# Return current ff window id, bailing out on missing or multiple
# ff window(s).
{
local win
win=$( xdotool search --name "$FF_WINDOW_NAME" ) || win=""
if [ -z "$win" ]; then
error_msg "No Firefox window!"
exit 1
fi
if [ "$win" != "${win%% *}" ]; then
error_msg "Two (or more) Firefox windows"
exit 1
fi
echo $win
}
function get_ff_window_width_height()
# Echo shell line like 'width=xxx height=yyy' for window argument.
{
local win=$1
xwininfo -id "$win" |
awk '/Width:/ { w = $2 }
/Height:/ { h = $2 }
END { printf "width=%s height=%s\n", w, h }'
}
function get_fullscreen()
# Echo 'yes' or 'no' reflecting whether ff is running in fullscreen.
{
local win=$1
local width height
eval $( get_ff_window_width_height $win )
local window_dim="${width}x${height}"
screen_dim=$( xdpyinfo | awk ' /dimensions:/ { print $2}')
if [ "$window_dim" = "$screen_dim" ]; then
echo "yes"
else
echo "no"
fi
}
function get_ff_url()
# Select and copy url from ff (current window) to X clipboard.
{
fullscreen=$1
if [[ $fullscreen == *n* ]]; then
xdotool key alt+d ctrl+c
else
xdotool key F11 alt+d ctrl+c F11
fi
}
function get_ff_location()
# Get location from current ff window
# Arg: ff window id.
{
local win="$1"
local fullscreen="$2"
local width height
eval $( get_ff_window_width_height $win )
local X Y SCREEN WINDOW
eval $(xdotool getmouselocation --shell)
echo "No-url" | xsel -ib
xdotool windowactivate "$win"
# Try to click outside video widget, it doesn't pass alt-d,ctrl-c.
# alt+d, ctrl+c = "select location bar", "copy" keyboard shortcuts.
xdotool mousemove --sync $(( $width/2 )) $(( $height - 1 ))
get_ff_url $fullscreen
for delay in 0.1 0.2 0.3 0.5 0.8; do
sleep $delay
url=$( xsel -ob )
[[ "$url" != *No-url* ]] && break
get_ff_url $fullscreen
done
if [[ "$url" == *No-url* ]]; then
error_msg "Can\'t copy url from firefox (!)"
exit 2
fi
xdotool mousemove $X $Y
echo $url
}
function rotate_cache()
# Ensure there are at most CACHE_SIZE - 1 downloads in cache,
# remove old log files. Rename newest file to it's "native"
# name as hinted by flash-download.
{
(
cd $CACHE_DIR
[ -f ".rename-head" ] && \
eval "$( cat .rename-head)" && rm ".rename-head"
rm $( ls -t --hide '*.log' | awk "NR > $((CACHE_SIZE - 1))" ) \
&>/dev/null || :
rm $( find . -mtime +1 -name '*.log' ) &>/dev/null || :
)
}
function check_running_process()
# Exit if there is a running process messing w ff, else accquire lock.
{
if [ -f $LOCK_FILE ]; then
local pid=$( cat $LOCK_FILE )
if [ "$( ps --pid "$pid" -o uid --no-headers )" = '' ]; then
logger "$0: Removing stale lock file, pid: $pid"
echo "Removing stale lock file" >&2
rm -f $LOCK_FILE
fi
fi
local tmp_pid=$( mktemp )
echo $$ > $tmp_pid
mv --no-clobber $tmp_pid $LOCK_FILE
local lock_pid=$(cat $LOCK_FILE)
rm -f "$tmp_pid"
if [ "$lock_pid" != "$$" ]; then
logger "$0: Another instance is messing with FF, exiting"
exit 3
fi
}
function get_dl_path
{
local location=$1
local key value
get_flash_videos --info $location | while read key value; do
[ "$key" = 'Filename:' ] && echo "$value"
done
}
function setup_nickname()
{
local location=$1
local dl_path=$( get_dl_path $location )
if [ "$dl_path" = "" ] ; then
error_msg "Can't download from Firefox"
exit 1
fi
local nickname=${location%.*}
nickname=${nickname#*://}
nickname=${nickname#www.}.flv
echo "mv '$nickname' '$dl_path'" > "$CACHE_DIR/.rename-head"
echo $nickname
}
get_options $@
exec 1>$LOGFILE 2>&1
set -x
check_running_process
wid=$( get_ff_window )
fullscreen=$( get_fullscreen $wid )
location=$( get_ff_location $wid $fullscreen ) || exit 1
nickname=$( setup_nickname $location ) || exit 2
dl_file="$CACHE_DIR/$nickname"
logfile=${dl_file/.flv/.log}
rotate_cache
pkill -f "get_flash_videos.*$dl_file" && sleep 1
get_flash_videos -q -f $dl_file $location &>$logfile &
dl_pid=$!
rm -f $LOCK_FILE
info_msg "Download started" &
sleep 1; size_1=$( get_size $dl_file)
sleep 10; size_2=$( get_size $dl_file)
if (( "$size_1" == "$size_2" || "$size_2" == '0' )); then
msg="Warning: Download seem to have stalled, $size_2 bytes downloaded"
warning_msg "$msg" &
fi
if wait $dl_pid; then
info_msg "Download complete"
else
result=$?
test $result -gt 127 && echo "Interrupted!" >> $logfile
echo "Result: $result" >> $logfile
fi
exit 0