move between subtitiles with F1/F4
[HTML5TV.git] / bin / mplayer.pl
1 #!/usr/bin/perl
2
3 use warnings;
4 use strict;
5
6 use IPC::Open3 qw(open3);
7 use IO::Epoll;
8 use Data::Dump qw(dump);
9 use File::Slurp;
10 use YAML;
11
12
13 my $movie = shift @ARGV
14         || 'media/lpc-2009-network-namespaces/Pavel Emelyanov.ogg';
15 #       || die "usage: $0 path/to/movie.ogv\n";
16
17 my $edl = "/dev/shm/edl";
18 my $subtitles = $movie;
19 $subtitles =~ s{\.\w+$}{.srt};
20
21 our $to_mplayer;
22 our $from_mplayer;
23
24 my $pid = open3( $to_mplayer, $from_mplayer, $from_mplayer,
25          'mplayer',
26                 '-slave', '-idle',
27                 '-quiet',
28                 '-edlout', $edl,
29                 '-osdlevel', 3,
30 );
31
32 my $epfd = epoll_create(10);
33
34 epoll_ctl($epfd, EPOLL_CTL_ADD, fileno STDIN         , EPOLLIN  ) >= 0 || die $!;
35 epoll_ctl($epfd, EPOLL_CTL_ADD, fileno $from_mplayer , EPOLLIN  ) >= 0 || die $!;
36 epoll_ctl($epfd, EPOLL_CTL_ADD, fileno $to_mplayer   , EPOLLOUT ) >= 0 || die $!;
37
38 warn "$movie ", -s $movie, " bytes $edl\n";
39 print $to_mplayer qq|loadfile "$movie"\n|;
40
41 $|=1;
42
43 my $line;
44 my $repl;
45
46 sub repl {
47         print "> ";
48         my $cmd = <STDIN>;
49         warn ">>> $cmd\n";
50         print $to_mplayer $cmd;
51 }
52
53
54 sub t_srt {
55         my $t = shift;
56         my $hh = int( $t / 3600 );
57         $t -= $hh * 3600;
58         my $mm = int( $t / 60 );
59         $t -= $mm * 60;
60         my $srt = sprintf "%02d:%02d:%04.1f", $hh, $mm, $t;
61         $srt =~ s{\.}{,};
62         return $srt;
63 }
64
65 our @subtitles;
66 sub save_subtitles {
67         my $nr = 0;
68         my $srt = "\n";
69         foreach my $s ( @subtitles ) {
70                 $srt .= $nr++ . "\n"
71                         . t_srt( $s->[0] ) . " --> " . t_srt( $s->[1] ) . "\n"
72                         . $s->[2] . "\n\n"
73                         ;
74         }
75         warn $srt;
76
77         write_file $subtitles, $srt;
78         YAML::DumpFile "$subtitles.yaml", @subtitles;
79
80         print $to_mplayer "sub_remove\n";
81         print $to_mplayer qq|sub_load "$subtitles"\n|;
82         print $to_mplayer "sub_select 1\n";
83
84 }
85
86 if ( -e "$subtitles.yaml" ) {
87         @subtitles = YAML::LoadFile "$subtitles.yaml";
88         warn "subtitles ", dump @subtitles;
89         save_subtitles;
90 }
91
92 sub add_subtitle {
93         print $to_mplayer qq|pause\n|;
94
95         warn "subtitles ", dump( @subtitles );
96         print "## ";
97         my $line = <STDIN>;
98         $subtitles[ $#subtitles ]->[2] = $line if defined $line;
99
100         my $preroll_pos = $subtitles[ $#subtitles ]->[0] - 1;
101         $preroll_pos = 0 if $preroll_pos < 0;
102         warn "PREROLL $preroll_pos\n";
103         print $to_mplayer "set_property time_pos $preroll_pos\n";
104
105         save_subtitles;
106
107         print $to_mplayer "play\n";
108 }
109
110 sub time_pos {
111         print $to_mplayer qq|get_property time_pos\n|;
112         my $pos = <$from_mplayer>;
113         if ( $pos =~ m{^ANS_time_pos=(\d+\.\d+)} ) {
114                 warn "# time_pos $1\n";
115                 return $1;
116         }
117 }
118
119 sub prev_subtitle {
120         my $pos = time_pos;
121         my $s = ( grep { $_->[0] < $pos } @subtitles )[0];
122         print $to_mplayer "set_property time_pos $s->[0]\n";
123 }
124
125 sub next_subtitle {
126         my $pos = time_pos;
127         my $s = ( grep { $_->[0] > $pos } @subtitles )[0];
128         print $to_mplayer "set_property time_pos $s->[0]\n";
129 }
130
131 while ( my $events = epoll_wait($epfd, 10, 1000) ) { # Max 10 events returned, 1s timeout
132
133         warn "no events" unless $events;
134
135         foreach my $e ( @$events ) {
136 #               warn "# event: ", dump($e), $/;
137
138                 my $fileno = $e->[0];
139
140                 if ( $fileno == fileno STDIN ) {
141                         my $chr;
142                         sysread STDIN, $chr, 1;
143                         print "$chr";
144                 } elsif ( $fileno == fileno $from_mplayer ) {
145                         my $chr;
146                         sysread $from_mplayer, $chr, 1;
147                         print $chr;
148
149                         if ( $chr =~ m{[\n\r]} ) {
150
151                                 exit if $line =~ m{Exiting};
152
153                                 if ( $line =~ m{No bind found for key '(.+)'} ) {
154
155                                         warn "CUSTOM $1\n";
156                                         repl if $1 eq 'c';
157                                         add_subtitle if $1 eq ',';
158
159                                         prev_subtitle if $1 eq 'F1';
160                                         next_subtitle if $1 eq 'F4';
161
162                                 } elsif ( $line =~ m{EDL}i ) {
163
164                                         print $to_mplayer qq|osd_show_text "$line"\n|;
165
166                                         if ( my $pos = time_pos ) {
167                                                 if ( $line =~ m{start}i ) {
168                                                         push @subtitles, [ $pos, $pos, '-' ];
169                                                 } else {
170                                                         $subtitles[ $#subtitles ]->[1] = $pos;
171                                                 }
172                                         }
173                                 }
174
175                                 $line = '';
176                         } else {
177                                 $line .= $chr;
178                         }
179
180
181                 } elsif ( $fileno == fileno $to_mplayer ) {
182 #                       warn "command";
183                 } else {
184                         die "invalid fileno $fileno";
185                 }
186         }
187
188 }
189