Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/bash -
- # vim: set tabstop=8 softtabstop=4 shiftwidth=4 smarttab noexpandtab:
- ${DEBUG}
- #========================================================================
- # FILE: medley
- #
- # USAGE: medley [-h|--help][-V|--version]|-a ASPECT -w WIDTH
- # -n NUMBER -f -s FILENAME [FILENAME...]
- # --help display program help and exit
- #
- # -a ASPECT aspect ratio of videos. Valid values for
- # ASPECT are cinema|hdtv|widescreen|standard.
- # Default is standard.
- # -w WIDTH width of video viewport. Cannot be used with
- # -f.
- # -n NUMBER number of viewports in a row. Valid values
- # for NUMBER are 1-3. Default is 4.
- # -f turn off fullscreen view when playing a list
- # of videos sequentially. Cannot be used with
- # -w.
- # -s do not unsort FILENAMEs.
- # -u
- # --usage display a usage message and exit
- #
- # -V
- # --version display the program version number and exit
- # -x display debugging information
- #
- # DESCRIPTION: play a medley of videos simultaneously
- #
- # OPTIONS: --help, --version
- # REQUIREMENTS: ---
- # BUGS: ---
- # NOTES: ---
- # AUTHOR: Scott Bicknell (SB), [email protected]
- # COMPANY:
- # VERSION: 2.0
- # CREATED:
- # REVISION: ---
- #
- # Copyright 2010 Scott Bicknell, sbicknel (at) gmail dot com
- #
- # This program is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation, either version 3 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
- #========================================================================
- PROGNAME=${0##*/}
- VERSION='2.0'
- PATH="${HOME}/bin:/bin:/usr/bin:/usr/local/bin"
- PANEL_HEIGHT=$(sed -n '/\[Containments\]\[1\]$/,/^$/p'\
- $(kde4-config --localprefix)/share/config/plasma-desktop-appletsrc |\
- awk -F, '/geometry/ {print $4}')
- PANEL_HEIGHT=${PANEL_HEIGHT##*-} # height of the desktop panel or taskbar
- umask 077
- # -----------------------------------------------------------------------
- # Display error messages on standard error.
- # -----------------------------------------------------------------------
- function error () {
- printf '%s: %s\n' $PROGNAME "$@"
- } >&2
- # -----------------------------------------------------------------------
- # Display warning messages on standard output.
- # -----------------------------------------------------------------------
- warning () {
- printf '%s: %s\n' $PROGNAME "$@"
- }
- # -----------------------------------------------------------------------
- # Display messages on standard output.
- # -----------------------------------------------------------------------
- function message () {
- printf '%s: %s\n' $PROGNAME "$@"
- }
- # -----------------------------------------------------------------------
- # Function for exit due to fatal program error
- # Accepts 1 argument:
- # string containing descriptive error message
- # -----------------------------------------------------------------------
- function error_exit () {
- error "${1:-'Unknown Error'}"
- exit 1
- }
- # -----------------------------------------------------------------------
- # Function to handle termination signals
- # Accepts 1 argument:
- # signal_spec
- # -----------------------------------------------------------------------
- function signal_exit () {
- case $1 in
- INT)
- error_exit 'Program aborted by user'
- ;;
- TERM)
- error_exit 'Program terminated'
- ;;
- *)
- error_exit 'Terminating on unknown signal'
- ;;
- esac
- }
- trap 'signal_exit TERM' TERM HUP QUIT PIPE
- trap 'signal_exit INT' INT
- # -----------------------------------------------------------------------
- # Function called for a graceful exit
- # No arguments
- # -----------------------------------------------------------------------
- function graceful_exit () {
- exit
- }
- # -----------------------------------------------------------------------
- # Simulate user activity to inhibit the screensaver
- # -----------------------------------------------------------------------
- function inhibit_screensaver () {
- qdbus org.freedesktop.ScreenSaver /ScreenSaver SimulateUserActivity
- } &>/dev/null
- # -----------------------------------------------------------------------
- # Set player variable
- # -----------------------------------------------------------------------
- set_player () {
- if [[ -n "$player" ]]; then
- return 0
- fi
- if ! type -P mplayer2 &>/dev/null && ! type -P mplayer &>/dev/null; then
- error_exit 'mplayer or mplayer2 is required'
- fi
- if type -P mplayer2 &>/dev/null; then
- player=mplayer2
- elif type -P mplayer &>/dev/null; then
- player=mplayer
- fi
- }
- # -----------------------------------------------------------------------
- # Display a short message about program usage. This is also used by the
- # helptext function to display part of its help text.
- # -----------------------------------------------------------------------
- function usage () {
- cat <<- EOF
- USAGE: $PROGNAME: [-a standard|cinema|hdtv|widescreen][-f][-s][-n NUM|-w NUM]|[-h|--help]
- [-u|--usage][-V|--version]|[-x] FILE [FILE...]
- EOF
- }
- # -----------------------------------------------------------------------
- # Display the program version number
- # -----------------------------------------------------------------------
- function version () {
- printf '%s %s\n' $PROGNAME $VERSION
- }
- # -----------------------------------------------------------------------
- # Function to display help message for program
- # No arguments
- # -----------------------------------------------------------------------
- function helptext () {
- local tab=$(printf '\t\t')
- usage
- cat << -EOF-
- DESCRIPTION:
- Play a medley of videos simultaneously. By default, each video is scaled to fit
- in a row four viewports wide. The script fills the display with as many windows
- as it can and tiles them in a grid. As each video finishes playing another
- video fills the same location in the on-screen grid. The videos are played in
- random order by default if unsort is installed.
- Options:
- -a ASPECT Aspect ratio. This option affects vertical spacing of viewports
- in the on-screen grid. Valid names are standard, cinema, hdtv,
- and widescreen. Default is 'standard'.
- Name | Meaning
- --------------------
- standard | 4:3
- cinema | 16:9
- hdtv | 1.85:1
- widescreen | 2.35:1
- -f Turn off fullscreen mode when playing videos one at a time.
- Disables -w. Must be used with -n 1.
- -s Do not randomize play list. Ignored if unsort not installed
- -h, --help Display this help message and exit.
- -u, --usage Display a usage message and exit.
- -V, --version Display program version and exit.
- -w PIXELS Width of a video viewport. This option affects how many
- videos are placed in a row and may affect how may rows
- are placed in the grid. Default creates a row of four
- videos and sizes the viewports to fit the width of the
- display. Cannot be used with -n.
- -n NUMBER Number of windows in a row. Cannot be used with -w. Valid
- values are 1 to 3. If NUMBER is 1, -f may be used.
- -x Display debugging output when running the program
- This program requires mplayer or mplayer2. Unsort is optional.
- -EOF-
- version
- }
- # -----------------------------------------------------------------------
- # Verify that the usage function and the helptext function both have
- # documentation for each long option. Verify that the header comment
- # also has each long option listed.
- # -----------------------------------------------------------------------
- if [[ "$1" == '--help' ]]; then
- helptext
- graceful_exit
- fi
- if [[ "$1" == '--version' ]]; then
- version
- graceful_exit
- fi
- if [[ "$1" == '--usage' ]]; then
- usage
- graceful_exit
- fi
- # dimensions of the current display
- # we get this early so we can do early error checking
- dimensions=$(xdpyinfo | awk -F' ' '/dimensions/ {print $2}')
- dwidth=${dimensions%x*} # width of display in pixels
- dheight=${dimensions##*x} # height of display in pixels
- unset dimensions
- # default width of a video window
- maxGridHeight=$(( $dheight - $PANEL_HEIGHT ))
- defaultWidth=$(echo "scale=2; $maxGridHeight / 3 * 4 / 3 " | bc | sed 's/...$//')
- # mplayer/mplayer2 calling syntax differences
- declare -A id
- declare -A fd
- declare -A asp
- id[mplayer]='-identify '
- fd[mplayer]='-framedrop'
- asp[mplayer]='-aspect '
- id[mplayer2]='--identify='
- fd[mplayer2]='--framedrop'
- asp[mplayer2]='--aspect='
- # ratios
- st='4:3' # standard
- ci='16:9' # cinema
- hd='1.85:1' # hdtv
- wi='64:27' # widescreen
- # -----------------------------------------------------------------------
- # Verify that the usage function and the helptext function both have
- # documentation for each short option. Verify that the header comment
- # also has each short option listed in the usage section.
- # -----------------------------------------------------------------------
- while getopts :a:fhn:suVw:x opt; do
- case $opt in
- a) # aspect ratio
- set_player
- aspect=${asp[$player]}
- case ${OPTARG,,} in
- standard)
- aspect=${aspect}$st
- aspRatio=${OPTARG,,}
- ;;
- cinema)
- aspect=${aspect}$ci
- aspRatio=${OPTARG,,}
- ;;
- hdtv)
- aspect=${aspect}$hd
- aspRatio=${OPTARG,,}
- ;;
- widescreen)
- aspect=${aspect}$wi
- aspRatio=${OPTARG,,}
- ;;
- *)
- message "$OPTARG: unsupported aspect ratio. Setting aspect ratio to standard"
- aspect=${aspect}$st
- aspRatio=standard
- ;;
- esac
- ;;
- h) # help
- helptext
- graceful_exit
- ;;
- f) # turn off fullscreen when playing videos one at a time
- full=no
- width=$(( $dwidth / 2 + 1 ))
- ;;
- n) # number of windows in a grid row
- case ${OPTARG} in
- *[!0-9]*)
- message "$OPTARG: must be a number of windows. Setting number of windows to default"
- width=$defaultWidth
- ;;
- [1-3])
- width=$(( $dwidth / $(( $OPTARG + 1 )) + 1 ))
- ;;
- *)
- message "$OPTARG: must be a number from 1 to 3. Setting number of windows to default"
- width=$defaultWidth
- ;;
- esac
- ;;
- s) # do not unsort videos
- unsort=no
- ;;
- u) # usage
- usage
- graceful_exit
- ;;
- V) # version
- version
- graceful_exit
- ;;
- w) # width of a video window
- case $OPTARG in
- *[!0-9]*)
- message "$OPTARG: video width must be a number. Setting width to $defaultWidth"
- width=$defaultWidth
- ;;
- esac
- width=${width:-$OPTARG}
- if [[ $width -gt $dwidth ]]; then
- message "-w: width cannot exceed $dwidth. Setting width to $defaultWidth"
- width=$defaultWidth
- fi
- ;;
- x) # set debugging output on a per-run basis. The $DEBUG
- # environment variable will enable degugging output at
- # the top of the script.
- set -x
- ;;
- :) # process missing required parameters
- case $OPTARG in
- a) error_exit "-$OPTARG: required argument missing: standard, cinema, hdtv, or widescreen expected";;
- n) error_exit "-$OPTARG: required argument missing: 1, 2 or 3 expected";;
- w) error_exit "-$OPTARG: required argument missing: pixel width of a single video expected (e.g. 300)";;
- *) error_exit "-$OPTARG: required argument missing";;
- esac
- ;;
- *) # process unknown options
- usage
- error_exit "Unknown option: -$OPTARG"
- ;;
- esac
- done
- shift $(( $OPTIND - 1 ))
- if [[ $# -eq 0 ]]; then
- error_exit 'nothing to play'
- fi
- set_player
- killall $player &>/dev/null
- # if aspect is not set, try to determine aspect ratio from folder name
- if [[ -z "$aspect" ]]; then
- case ${PWD##*/} in
- standard|cinema|hdtv|widescreen)
- aspRatio=${PWD##*/}
- aspect=${asp[$player]}
- case $aspRatio in
- standard)
- aspect=${aspect}$st
- ;;
- cinema)
- aspect=${aspect}$ci
- ;;
- hdtv)
- aspect=${aspect}$hd
- ;;
- widescreen)
- aspect=${aspect}$wi
- ;;
- esac
- ;;
- esac
- fi
- width=${width:-$defaultWidth} # width of a video window
- case $width in
- *[!0-9]*)
- message "$OPTARG: video width must be a number. Setting width to $defaultWidth pixels."
- width=$defaultWidth
- ;;
- esac
- # height of a video window
- aspRatio=${aspRatio:-standard}
- aspRatio=${aspRatio,,}
- case $aspRatio in
- standard) height=$(echo "scale=2; $width / 4 * 3" | bc | sed 's/...$//');;
- cinema) height=$(echo "scale=2; $width / 16 * 9" | bc | sed 's/...$//');;
- hdtv) height=$(echo "scale=2; $width / 1.85" | bc | sed 's/...$//');;
- widescreen) height=$(echo "scale=2; $width / 64 * 27" | bc | sed 's/...$//');;
- *)
- message 'unsupported aspect ratio. Using standard aspect ratio to set height'
- height=$(echo "scale=2; $width / 4 * 3" | bc | sed 's/...$//')
- ;;
- esac
- unset aspRatio
- maxxp=$(( $dwidth - $width )) # maximum horizontal window position
- # pixel dimensions of the entire grid
- maxWWide=$(( $dwidth / $width )) # maximum windows wide
- # maximum windows high
- maxWHigh=$(( $dheight - $PANEL_HEIGHT ))
- maxWHigh=$(( $maxWHigh / $height ))
- numWindows=$(( $maxWWide * $maxWHigh )) # number of windows in a grid
- maxPixelsWide=$(( $width * $maxWWide )) # maximum pixels in a row
- unset maxWWide
- maxPixelsHigh=$(( $height * $maxWHigh )) # maximum pixels in a column
- unset maxWHigh
- # screen coordinates of first video window
- xstart=$(( $(( $dwidth - $maxPixelsWide )) / 2 )) # initial horizontal window position
- unset dwidth
- unset maxPixelsWide
- ystart=$(( $(( $dheight - $maxPixelsHigh - $PANEL_HEIGHT )) / 2 )) # initial vertical window position
- unset dheight
- unset maxPixelsHigh
- x=$xstart # horizontal window position
- y=$ystart # vertical window position
- unset ystart
- # make a list of all window positions
- for (( w=1; w<=$numWindows; w++ )); do
- window[$w]="$x:$y"
- x=$(( $x + $width ))
- if [[ $x -gt $maxxp ]]; then
- x=$xstart
- y=$(( $y + $height ))
- fi
- done
- unset height
- unset maxxp
- unset xstart
- unset x
- unset y
- # set fullscreen mode if only one window position in list
- declare -A fs
- if [[ ${#window[@]} -eq 1 ]] && [[ ${full:-yes} == yes ]]; then
- fs[mplayer2]='--fs'
- fs[mplayer]='-fs'
- fi
- unset COLUMNS # This setting prevents some data from reaching grep
- v=0 # video list index
- # create an indexed list of video files, skipping files not recognized as videos
- # explicite index assignment is necessary to prevent word splitting on spaces
- for f in "$@"; do
- if ! [[ $(file --mime-type -b "$f" | awk -F/ '{print $1}') == 'video' ]] &&
- ! [[ $(file --mime-type -b "$f" | awk -F/ '{print $2}') == 'ogg' ]]; then
- warning "Video file not recognized. $f: $(file --mime-type -b $f)"
- # ensures that the number of parameters equals the number of valid video files
- # we can throw away parameters because we are storing valid ones in flist
- shift
- continue
- fi
- flist[$v]="$f"
- (( v++ ))
- done
- # create a list of video files in input order if unsort is not installed
- if ! type -P unsort &>/dev/null || [[ ${unsort:-yes} == no ]]; then
- rlist=( "${flist[@]}" )
- # create a random list of video files otherwise
- else
- v=0
- # create a random list of indexes ($rn) for each video file in $flist
- # $rn is our random list of indexes into $flist
- rn=( $(for (( r=0; r<${#flist[@]}; r++ )); do
- echo $r
- done | sed 's/ /\n/g' | unsort 2>/dev/null) )
- # this random list is used to store video file names from random
- # index locations in $flist to sequential locations in $rlist
- for r in ${rn[@]}; do
- rlist[$v]="${flist[$r]}"
- (( v++ ))
- done
- fi
- unset v
- unset flist
- if [[ ${#rlist[@]} -eq 0 ]]; then
- message 'video detection failed. Try: file --mime-type -b FILE'
- error_exit 'no video files in file list'
- fi
- # set fullscreen mode if only one video in list
- if [[ ${#rlist[@]} -eq 1 ]] && [[ ${full:-yes} == yes ]]; then
- fs[mplayer2]='--fs'
- fs[mplayer]='-fs'
- fi
- # video format ratios
- WIDESCREEN=$(echo "scale=2; 64 / 27 * 100" | bc | sed -e 's/...$//')
- HDTV=$( echo "scale=2; 1.85 * 100" | bc | sed -e 's/...$//')
- CINEMA=$( echo "scale=2; 16 / 9 * 100" | bc | sed -e 's/...$//')
- STANDARD=$( echo "scale=2; 4 / 3 * 100" | bc | sed -e 's/...$//')
- rindex=0 # index into rlist
- started=0 # number of videos started in previous check
- # delay between checks for empty slots. Longer delays when playing more
- # videos; shorter delays when more cpu cores are installed.
- numProc=$(grep '^processor' /proc/cpuinfo | wc -l)
- [[ $numProc -lt 2 ]] && numProc=2
- delay=$(( $numWindows / $(( $numProc / 2 )) ))
- [[ $delay -lt 1 ]] && delay=1
- # play each video in an empty slot. Shift each file name off the list as each video is played.
- while [[ $# -gt 0 ]]; do
- inhibit_screensaver
- # if all slots are filled with videos, sleep and skip further processing
- if [[ $(ps aux | grep 'mplayer.*noborder.*zoom.*xy.*geometry.*' | grep -v grep | wc -l) -eq $numWindows ]]; then
- if [[ $started -gt 0 ]]; then
- sleep $(( $delay - 1 ))s
- started=0
- else
- sleep ${delay}s
- fi
- continue
- fi
- started=0
- # fill empty slots with videos
- for slot in ${window[@]}; do
- if ! ps aux | grep "geometry $slot " | grep -vq grep; then
- # quit here if at end of file list
- if [[ $# -eq 0 ]]; then
- break
- fi
- # get dimensions of video
- widthDim=$($player -frames 0 ${id[$player]} ${rlist[$rindex]} 2>/dev/null | awk -F= '/^ID_VIDEO_WIDTH/ {print $2}' 2>/dev/null)
- heightDim=$($player -frames 0 ${id[$player]} ${rlist[$rindex]} 2>/dev/null | awk -F= '/^ID_VIDEO_HEIGHT/ {print $2}' 2>/dev/null)
- # compute format ratio
- format=$(echo "scale=2; $widthDim / $heightDim * 100" | bc | sed -e 's/...$//')
- # set aspect ratio for each video
- aspect=${asp[$player]}
- if [[ "$format" -ge "$WIDESCREEN" ]]; then
- aspect=${aspect}$wi
- elif [[ "$format" -ge "$HDTV" ]]; then
- aspect=${aspect}$hd
- elif [[ "$format" -ge "$CINEMA" ]]; then
- aspect=${aspect}$ci
- else
- aspect=${aspect}$st
- fi
- $player ${fd[$player]} $aspect -noborder -zoom ${fs[$player]} -xy $width -geometry "$slot" "${rlist[$rindex]}" &>/dev/null &
- unset rlist[$rindex]
- (( started++ ))
- (( rindex++ ))
- sleep 1s
- shift
- fi
- done
- done
- # inhibit the screensaver until the last video ends
- while ps aux | grep 'mplayer.*noborder.*zoom.*xy.*geometry.*' | grep -vq grep; do
- sleep $delay
- inhibit_screensaver
- done
- graceful_exit
- This script makes several assumptions that will not hold for many users. It assumes you are using KDE. It gets the value
- for $PANEL_HEIGHT from KDE's configuration. It also relies on qdbus to inhibit the screensaver while videos are playing.
- The script uses either mplayer or mplayer2 and adjusts its syntax according to which one is installed. If you have a version
- of unsort installed, the script will randomize the play list by default. While running, the script will sleep for a period
- calculated by the number of videos it is playing simultaneously while taking into account the number of processor cores
- installed on the system. The more videos it plays, the longer the sleep interval; the more processor cores installed, the
- shorter the sleep interval. $PANEL_HEIGHT can be hard-coded or the code that sets it replaced with code that works for your
- environment. The same goes for inhibiting the screensaver.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement