You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

391 lines
11 KiB

#!/bin/bash
saveourship(){
cat << EOF
Nougat - screenshot wrapper created to help organize screenshots
-h - Saves our ship.
-i - Output image to stdout. This implies -s (silent).
-s - Silent. By default, nougat will output the path to the file to STDOUT.
This is to make it easier to implement into other file uploaders.
-t - Places screenshot into /tmp
(useful if you only need a quick screenshot to send to a friend)
-f - Takes a full screen screenshot (default is select area)
-m - Takes a full screen screenshot of the currently focused monitor.
\`xdotool\` is required (\`nougat\` fallsback to a regular fullscreen screenshot without it).
-c - Puts the screenshot into your clipboard
-p - Cleans the link directory of Nougat based on the linking policy.
Particularly useful as it cleans any links that no
longer point to a screenshot (i.e. deleted screeenshot).
EOF
exit
}
temporary=false
clean=false
silent=false
stdout=false
fullscreen=false
focused_monitor=false
copytoclipboard=false
getconfigdir(){
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}"
echo "$CONFIG_DIR"
}
configfile="`getconfigdir`/nougat/config.sh"
if [[ -f "${configfile}" ]]
then
source "${configfile}"
else
# V2
if [[ -f "`getconfigdir`/nougat" ]]
then
mv "`getconfigdir`/nougat" "`getconfigdir`/nougat.old"
source "`getconfigdir`/nougat.old"
cat >> "${configfile}" << EOF
# AUTOGENERATED CONFIG - NOUGAT V3 - PORTED FROM NOUGAT V2 CONFIG
SCREENSHOT_DIRECTORY="${NOUGAT_SCREENSHOT_DIRECTORY}"
ORGANIZATION_POLICY="${NOUGAT_ORGANIZATION_POLICY}"
NOUGAT_LINKING_POLICY="${NOUGAT_LINKING_POLICY}"
EOF
# V1
elif [[ -n "${NOUGAT_SCREENSHOT_DIRECTORY}" ]]
then
cat >> "${configfile}" << EOF
# AUTOGENERATED CONFIG - NOUGAT V3 - PORTED FROM NOUGAT V1 CONFIG
SCREENSHOT_DIRECTORY="${NOUGAT_SCREENSHOT_DIRECTORY}"
EOF
else
mkdir -p "`getconfigdir`/nougat/"
cat >> "${configfile}" << EOF
# AUTOGENERATED CONFIG - NOUGAT V3
SELECTION_METHOD="default"
SCREENSHOT_DIRECTORY="\$HOME/Pictures/Screenshots"
SCREENCAST_DIRECTORY="\$HOME/Videos/Screencasts"
DEFAULT_POLICY='\${year}/\${month}/\${day}/\${hour}:\${minute}:\${second}'
EOF
fi
source "${configfile}"
fi
unset configfile
SELECTION_METHOD="${SELECTION_METHOD:-default}"
SCREENSHOT_DIRECTORY="${SCREENSHOT_DIRECTORY:-$HOME/Pictures/Screenshots}"
SCREENCAST_DIRECTORY="${SCREENCAST_DIRECTORY:-$HOME/Videos/Screencasts}"
DEFAULT_POLICY='${year}/${month}/${day}/${hour}:${minute}:${second}'
ORGANIZATION_POLICY="${ORGANIZATION_POLICY:-$DEFAULT_POLICY}"
LINKING_POLICY="${LINKING_POLICY}"
getconfiguration(){
echo "${!1}"
}
require(){
command -v "$1" &> /dev/null || {
echo "$1 is not installed and is required."
exit 1
}
}
maketemp(){
path=`mktemp`
mv ${path} ${path}.$1
echo ${path}.$1
}
getmime(){
file --mime-type --brief $1
}
getcanonicalpaths(){
read -r year month day hour minute second <<< `date +'%Y %B %d %H %M %S'`
suffix="${1}"
extension="${2}"
if [[ "${3}" == "image" ]]
then
base_path="`getconfiguration SCREENSHOT_DIRECTORY`"
elif [[ "${3}" == "video" ]]
then
base_path="`getconfiguration SCREENCAST_DIRECTORY`"
fi
org_fullpath="${base_path}/`getconfiguration ORGANIZATION_POLICY`"
org_fullpath="${org_fullpath}${suffix}.${extension}"
if [[ -n "`getconfiguration LINKING_POLICY`" ]]
then
link_fullpath="${base_path}/`getconfiguration LINKING_POLICY`"
link_fullpath="${link_fullpath}${suffix}.${extension}"
else
link_fullpath=''
fi
org_fullpath="`eval echo "${org_fullpath}"`"
link_fullpath="`eval echo "${link_fullpath}"`"
echo `dirname "${org_fullpath}"` `basename "${org_fullpath}"` `dirname "${link_fullpath}"` `basename "${link_fullpath}"`
}
temporary(){
filename=`date +'%Y-%B-%d-%H:%M:%S'`
suffix="${1}"
mime=`getmime $2`
_IFS=$IFS
IFS='/'
read -r filetype extension <<< "${mime}"
IFS=$_IFS
filename="${filename}${suffix}.${extension}"
cp "${2}" "/tmp/${filename}"
echo "/tmp/${filename}"
}
save(){
mime=`getmime $2`
_IFS=$IFS
IFS='/'
read -r filetype extension <<< "${mime}"
IFS=$_IFS
read -r fullpath filename linkpath linkname <<< `getcanonicalpaths "${1}" "${extension}" "${filetype}"`
mkdir -p "${fullpath}"
[[ -n "${linkpath}" ]] && mkdir -p "${linkpath}"
cp "${2}" "${fullpath}/${filename}"
[[ -n "${linkpath}" ]] && ln -s "${fullpath}/${filename}" "${linkpath}/${linkname}"
echo "${fullpath}/${filename} ${linkpath}/${linkname}"
}
copy(){
require xclip
mime=`getmime $1`
xclip -selection clipboard -t ${mime} ${1}
}
post(){
if [[ "${copytoclipboard}" == "true" ]]
then
copy ${1}
fi
output=''
if [[ "${temporary}" == "true" ]]
then
output=`temporary "" "${1}"`
else
read -r filepath linkpath <<< `save "" "${1}"`
output="${filepath}\n${linkpath}"
fi
if [[ "${silent}" == "false" ]]
then
echo -e "${output}"
else
if [[ "${stdio}" == "true" ]]
then
if [[ ! -t 1 ]]
then
cat "${1}"
else
cat >&2 <<EOF
Refusing to output file to terminal.
--output should only be used when redirecting files
EOF
fi
fi
fi
# We're done here. Let's clean up, boys.
rm ${1}
}
select_default(){
require slop
slop -of '%w %h %x %y'
}
select_dark(){
require slop
slop -c 0,0,0,0.35 -o -l -f '%w %h %x %y'
}
select_light(){
require slop
slop -c 1,1,1,0.25 -o -l -f '%w %h %x %y'
}
select_root_window(){
require xrandr
xrandr="$(xrandr --nograb | grep -E 'current [0-9]+ x [0-9]+')"
sed -r "s/^.*current ([0-9]+) x ([0-9]+),.*$/\1 \2 0 0/" <<< "$xrandr"
}
select_focused_monitor(){
require xdotool
require xrandr
xrandr="$(xrandr --nograb | grep -E 'connected (primary )?[0-9]+x[0-9]+\+[0-9]+\+[0-9]+')"
[[ -z "$xrandr" ]] && return 1
eval "$(xdotool getmouselocation --shell)"
monitor_index=0
while read -r width height xoff yoff
do
if [[
"${X}" -ge "${xoff}" && "${Y}" -ge "${yoff}" && "${X}" -lt "$(($xoff+$width))" && "${Y}" -lt "$(($yoff+$height))"
]]
then
echo "${width} ${height} ${xoff} ${yoff}"
return 0
fi
((monitor_index++))
done <<< "$(sed -r "s/^([^ ]*).*\b([0-9]+)x([0-9]+)\+([0-9]+)\+([0-9]+).*$/\2 \3 \4 \5/" <<< "$xrandr" | sort -nk4,5)"
return 1
}
require ffmpeg
record_region(){
path=`maketemp mp4`
case `getconfiguration SELECTION_METHOD` in
dark)
geometry=`select_dark`
;;
light)
geometry=`select_light`
;;
*)
geometry=`select_default`
;;
esac
sleep 0.5
[[ -z "${geometry}" ]] && exit 0
read -r width height x y <<< ${geometry}
ffmpeg -f x11grab -s ${width}x${height} -i :0.0+${x},${y} -vcodec libx264 -preset veryfast -tune zerolatency -vsync 0 -y -loglevel 0 ${path}
post ${path}
}
record_fullscreen(){
path=`maketemp mp4`
geometry=`select_root_window`
read -r width height x y <<< ${geometry}
ffmpeg -f x11grab -s ${width}x${height} -i :0.0+0,0 -vcodec libx264 -preset veryfast -tune zerolatency -vsync 0 -y -loglevel 0 ${path}
post ${path}
}
record_focused_monitor(){
path=`maketemp mp4`
geometry=`select_focused_monitor`
read -r width height x y <<< ${geometry}
ffmpeg -f x11grab -s ${width}x${height} -i :0.0+${x},${y} -vcodec libx264 -preset veryfast -tune zerolatency -vsync 0 -y -loglevel 0 ${path}
post ${path}
}
require import
capture_region(){
path=`maketemp png`
case `getconfiguration SELECTION_METHOD` in
dark)
geometry=`select_dark`
;;
light)
geometry=`select_light`
;;
*)
geometry=`select_default`
;;
esac
sleep 0.5
[[ -z "${geometry}" ]] && exit 0
read -r width height x y <<< ${geometry}
geometry="${width}x${height}+${x}+${y}"
import -window root -crop ${geometry} ${path}
post ${path}
}
capture_fullscreen(){
path=`maketemp png`
import -window root ${path}
post ${path}
}
capture_focused_monitor(){
path=`maketemp png`
geometry=`select_focused_monitor`
read -r width height x y <<< ${geometry}
geometry="${width}x${height}+${x}+${y}"
import -window root -crop ${geometry} ${path}
post ${path}
}
longoptions="help,silent,temporary,copy,fullscreen,monitor,output,purge"
shortoptions="h,s,t,c,f,m,i,p"
# Configuration variables
longoptions="${longoptions},selection-method:"
longoptions="${longoptions},screenshot-directory:,screencast-directory"
longoptions="${longoptions},organization-policy:,linking-policy:"
# Screenshot & record
longoptions="${longoptions},screenshot,record"
getopt_opts="--options=${shortoptions} --longoptions=${longoptions}"
parsed=`getopt ${getopt_opts} --name "$0" -- "$@"`
eval set -- "${parsed}"
action=''
setaction(){
[[ ! -z "${action}" ]] && echo 'Only a single action can be done at a time.' && exit 1
action="$1"
}
while true
do
case "$1" in
-h|--help)
saveourship
;;
-s|--silent)
silent=true
shift
;;
-t|--temporary)
temporary=true
shift
;;
-c|--copy)
copytoclipboard=true
shift
;;
-f|--fullscreen)
fullscreen=true
shift
;;
-m|--monitor)
focused_monitor=true
shift
;;
-i|--output)
silent=true
stdio=true
shift
;;
-p|--purge)
# not yet implemented
shift
;;
#config variables
--selection-method)
SELECTION_METHOD=${2:-${SELECTION_METHOD}}
shift 2
;;
--screenshot-directory)
SCREENSHOT_DIRECTORY=${2:-${SCREENSHOT_DIRECTORY}}
shift 2
;;
--screencast-directory)
SCREENCAST_DIRECTORY=${2:-${SCREENCAST_DIRECTORY}}
shift 2
;;
--organization-policy)
ORGANIZATION_POLICY=${2:-${ORGANIZATION_POLICY}}
shift 2
;;
--linking-policy)
LINKING_POLICY=${2:-${LINKING_POLICY}}
shift 2
;;
# Screenshot
--screenshot)
setaction 'capture'
shift
;;
# Record
--record)
setaction 'record'
shift
;;
--)
shift
break
;;
esac
done
if [[ ! -z "${action}" ]]
then
if [[ "$fullscreen" == "true" && "$focused_monitor" == "true" ]]
then
echo "Only one selection mode can be specified at once."
exit 1
fi
if [[ "$fullscreen" == "true" ]]
then
action="${action}_fullscreen"
elif [[ "$focused_monitor" == "true" ]]
then
action="${action}_monitor"
else
action="${action}_region"
fi
$action
else
echo "No action set."
exit 1
fi