From 15437de691afabd283f305fdbe6ddf9ee5a878e7 Mon Sep 17 00:00:00 2001 From: Bob Igo Date: Tue, 16 Jun 2009 13:54:21 -0400 Subject: Preliminary mplayer wrapper; basic functionality only --- abs/core-testing/mplayer-wrapper/PKGBUILD | 16 ++ .../mplayer-wrapper/bin/mplayer-resumer.pl | 188 +++++++++++++++++++++ .../mplayer-wrapper/bin/mplayer-wrapper.pl | 110 ++++++++++++ 3 files changed, 314 insertions(+) create mode 100644 abs/core-testing/mplayer-wrapper/PKGBUILD create mode 100755 abs/core-testing/mplayer-wrapper/bin/mplayer-resumer.pl create mode 100755 abs/core-testing/mplayer-wrapper/bin/mplayer-wrapper.pl diff --git a/abs/core-testing/mplayer-wrapper/PKGBUILD b/abs/core-testing/mplayer-wrapper/PKGBUILD new file mode 100644 index 0000000..82f1082 --- /dev/null +++ b/abs/core-testing/mplayer-wrapper/PKGBUILD @@ -0,0 +1,16 @@ +pkgname=mplayer-wrapper +pkgver=1 +pkgrel=1 +pkgdesc="wrapper for mplayer and mplayer derivatives" +arch=('i686' 'x86_64') + +depends=('perl') + +source=(mplayer-wrapper.pl) + +license=('GPL2') + +build() { + cd $startdir + install -m0777 -D bin/* $startdir/pkg/usr/LH/bin/ +} diff --git a/abs/core-testing/mplayer-wrapper/bin/mplayer-resumer.pl b/abs/core-testing/mplayer-wrapper/bin/mplayer-resumer.pl new file mode 100755 index 0000000..c785a25 --- /dev/null +++ b/abs/core-testing/mplayer-wrapper/bin/mplayer-resumer.pl @@ -0,0 +1,188 @@ +#!/usr/bin/perl + +use Shell; +use strict; +use POSIX qw(floor); + +# Written by Bob Igo from the MythTV Store at http://MythiC.TV +# Email: bob@stormlogic.com +# +# If you run into problems with this script, please send me email + +# PURPOSE: +# -------------------------- +# This is a wrapper script to prove the concept of having MythTV +# resume playback of previously-stopped video where you left off. +# It's likely that a good solution will look different than this +# initial code. + +# RATIONALE: +# -------------------------- +# Watching 90% of a video and stopping causes you to return to the +# beginning again the next time you watch it. Remembering where +# you were in the video and resuming at that position is a much nicer +# behavior for the user. +# +# By default, mplayer spits out timecode information that tells you +# where you are in the video, to the tenth of a second. Mplayer also +# supports a seek feature on the command-line. We can make use of these +# features to write an mplayer wrapper that will remember the last +# position in a video file and resume to it on playback. + +# PARAMETERS: +# -------------------------- +# see print_usage() below + +# FILES: +# -------------------------- +# $infile, the video to play +# $resumefile, the video's resume file (see get_resume_filename() below) + +# KNOWN ISSUES: +# -------------------------- +# Mplayer misreports the timecodes on .nuv MPEG-2 files. Currently, anything +# captured via an HDTV tuner card and put into your /myth/video directory +# will fail with this resumer. +# +# Current theories include the timecode having to do with the show's broadcast +# time, recording time, or perhaps its upload time to the station that +# broadcast it. + +# DESIGN LIMITATION: +# ------------------------- +# If the video file to be played is on a read-only filesystem, or otherwise +# lives in a location that cannot be written to, resume will fail. This is +# because the current implementation uses a file parallel to the video file +# to store the timecode. +# + +# CHANGE LOG: +# 5/3/2006 +# Added last time started checking. +# If this script is restarted within $tdiff (default 5 seconds) +# then it will delete the file used to keep track of the videos +# resume position. + + +my $infile; +my $resumefile; +my $mplayer_parameters; +my $fudge_factor=2; # number of additional seconds to skip back before playback +my $tnow; # Time now. +my $tprev; # Time the prog was last started. + # Returned from the modification time of the xx.resume file. +my $tdiff=5; # How many seconds before we should start from + # the beginning of the movie +#DEBUG +#open(DEBUG,">/tmp/debug") || die "unable to open debug file"; + +sub init () { + $tnow = time(); + $infile = @ARGV[$#ARGV]; + + $resumefile = &get_resume_filename($infile); + # This returns the 9th element of the 13 element array + # created by the stat function. + $tprev = (stat ($resumefile))[9]; + # if this file is restarted in less than 5 seconds then + # remove the .resume file + if ( ($tnow - $tprev) < $tdiff ) { + unlink($resumefile); + } + + $mplayer_parameters = join(' ',@ARGV[0..$#ARGV-1]); +} + +&init(); +&save_time_offset(&mplayer($mplayer_parameters,$infile), $resumefile); + +#close(DEBUG); + +# For $pathname, return $path.$filename.resume +sub get_resume_filename () { + my($pathname)=@_; + + my $idx = rindex($pathname,"/"); + + if ($idx == -1) { # There was no "/" in $pathname + return ".".$pathname.".resume"; + } else { + # Now we need to split out the path from the filename. + my $path = substr($pathname,0,$idx+1); + my $filename = substr($pathname,$idx+1); + return "$path.$filename.resume"; + } +} + +# Calls mplayer and returns the last known video position +sub mplayer () { + my($parameters,$infile)=@_; + my $seconds=0; + my $timecode=&get_time_offset($infile); + my $command = "mplayer $parameters -ss $timecode \"$infile\" 2>&1 2>/dev/null |"; + + open(SHELL, $command); + # The kind of line we care about looks like this example: + # A:1215.2 V:1215.2 A-V: 0.006 ct: 0.210 207/201 13% 0% 1.9% 0 0 68% + # But all we care to look at is the first number. + + while () { + #print DEBUG $_; + if (m/A: *[0-9]+\.[0-9]/) { # See if this line has timecodes on it + my $last_timecode_line = &extract_last_timecode_line($_); + if ($last_timecode_line =~ m/ *([0-9]+\.[0-9]) V/) { + $seconds=$1; + } + } + } + close(SHELL); + + return $seconds; + + sub extract_last_timecode_line () { + my ($line)=@_; + my @lines=split('A:',$line); + return @lines[$#lines-1]; + } +} + +# Save the last known video position +sub save_time_offset () { + my($seconds, $resumefile)=@_; + + open(RESUMEFILE, ">$resumefile") || die "Unable to open $resumefile for writing"; + print RESUMEFILE "$seconds"; + close(RESUMEFILE); +} + +# returns the number of seconds corresponding to the last known video position, +# in hh:mm:ss format, compatible with the "-ss" parameter to mplayer +sub get_time_offset () { + my($videofile)=@_; + my($resumefile) = &get_resume_filename($videofile); + my $seconds=0; + my $timecode; + + open(RESUMEFILE, "<$resumefile") || return "00:00:00"; + while() { + $seconds=$_; + } + close(RESUMEFILE); + + my $hours = floor($seconds/3600); + $seconds = $seconds - $hours*3600; + + my $minutes = floor($seconds/60); + $seconds = int($seconds - $minutes*60) - $fudge_factor; + + $timecode = sprintf "%02d:%02d:%02d",$hours,$minutes,$seconds; +# print "TIMECODE: $timecode\n"; + return $timecode; +} + +sub print_usage () { + print "USAGE:\n"; + print "\t",$ARGV[0], "[mplayer parameters] video_file\n"; + print "\t","e.g. ",$ARGV[0], "-fs -zoom my.mpg\n"; + print "\t","Version 5/3/2006\n"; +} diff --git a/abs/core-testing/mplayer-wrapper/bin/mplayer-wrapper.pl b/abs/core-testing/mplayer-wrapper/bin/mplayer-wrapper.pl new file mode 100755 index 0000000..583786d --- /dev/null +++ b/abs/core-testing/mplayer-wrapper/bin/mplayer-wrapper.pl @@ -0,0 +1,110 @@ +#!/usr/bin/perl + +use Shell; +use strict; +use POSIX qw(floor); + +# Written by Bob Igo from the MythTV Store at http://MythiC.TV +# including some original code and contributions from Nick C. +# and graysky. +# Email: bob@stormlogic.com +# +# If you run into problems with this script, please send me email + +# PURPOSE: +# -------------------------- +# This is a wrapper script that tries to find the best parameters +# for calling an underlying video player. The outer layer determines +# the best playback parameters, while the inner layer picks the best +# player to call. + +# RATIONALE: +# -------------------------- +# Default video playback options are not optimal on all hardware or +# for all video types. In addition, common video players do not +# offer to bookmark video so that you can resume where you left off. +# Both of these problems can be addressed by this wrapper. + +# PARAMETERS: +# -------------------------- +# The same parameters you'd use for mplayer, some of which may be +# translated automatically for use with smplayer. + +# FILES: +# -------------------------- +# $mediafile, the file to play + +sub run () { + my $mediafile = @ARGV[$#ARGV]; + my $player = &pick_player(); + + my $player_parameters = join(' ', + &translate_parameters($player,@ARGV[0..$#ARGV-1]), + &dynamic_parameters($mediafile)); + &player($player,$player_parameters,$mediafile); +} + +&run(); + +# Translates any parameters into ones that will be compatible with the given player. +sub translate_parameters() { + my($player,@parameters)=@_; + + if ($player eq "smplayer") { + # Stupidly, smplayer uses a different set of command-line parameters than generic + # mplayer, so we need to translate mplayer-centric ones into the few that are + # available in smplayer-ese. + my %smplayer_parameter_translation_array = ( + "-fs" => "-fullscreen", + "-zoom" => " " + ); + + sub translate() { + my($flag)=@_; + return $smplayer_parameter_translation_array{$flag}; + } + + return map(&translate($_), @parameters); + } else { + return @parameters; + } +} + +# Returns an array of dynamic parameters based in part on the media. +sub dynamic_parameters () { + my($mediafile)=@_; + return(); # ??? empty for now; further development required +} + +# Find the best player for use on this system. The script prefers smplayer, +# which has built-in bookmarking, falling back to mplayer-resumer.pl, which +# implements bookmarking as an mplayer wrapper, if smplayer cannot be found. +# Finally, if no bookmarking players can be found, a barebones mplayer is used. +sub pick_player () { + my @possible_players = ("smplayer", "mplayer-resumer.pl", "mplayer"); + my $command; + my $candidate_player; + foreach (@possible_players) { + $candidate_player = $_; + $command = "which $candidate_player |"; + open(SHELL, $command); + if () { + #print "player $candidate_player : $_\n"; + return $candidate_player; + } + close(SHELL); + } +} + +# Calls player +sub player () { + my($player,$parameters,$mediafile)=@_; + my $command = "$player $parameters \"$mediafile\" 2>&1 2>/dev/null |"; + + #print "DEBUG: command is:\n$command\n"; + open(SHELL, $command); + while () { + print $_; + } + close(SHELL); +} -- cgit v0.12