summaryrefslogtreecommitdiffstats
path: root/abs/core/linhes-scripts/mplayer-resumer.pl
blob: c785a25e3cf7027db4c4ae9202bf5628b20c7735 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
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 (<SHELL>) {
	#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(<RESUMEFILE>) {
	$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";
}