File Coverage

blib/lib/BeamerReveal/NotesFactory.pm
Criterion Covered Total %
statement 24 87 27.5
branch 0 12 0.0
condition n/a
subroutine 8 13 61.5
pod 2 3 66.6
total 34 115 29.5


line stmt bran cond sub pod time code
1             # -*- cperl -*-
2             # ABSTRACT: NotesFactory
3              
4              
5             package BeamerReveal::NotesFactory;
6             our $VERSION = '20260208.1851'; # VERSION
7              
8 1     1   1555 use strict;
  1         3  
  1         44  
9 1     1   5 use warnings;
  1         2  
  1         61  
10              
11 1     1   6 use Carp;
  1         1  
  1         88  
12              
13 1     1   7 use File::Which;
  1         1  
  1         47  
14             #use File::Path;
15              
16 1     1   6 use Data::UUID;
  1         2  
  1         90  
17              
18 1     1   6 use BeamerReveal::IPC::Run;
  1         2  
  1         48  
19 1     1   5 use IPC::Run qw(harness start pump finish);
  1         2  
  1         64  
20              
21 1     1   5 use BeamerReveal::Log;
  1         2  
  1         1593  
22              
23 0     0 0   sub nofdigits { length( "$_[0]" ) }
24              
25              
26             sub new {
27 0     0 1   my $class = shift;
28 0           my ( $base, $output_dir, $pdf_dir, $presentationparameters, $xres, $yres, $progressId, $debug ) = @_;
29              
30 0           my $self = {
31             base => $base,
32             output_dir => $output_dir,
33             pdf_dir => $pdf_dir,
34             presentationparameters => $presentationparameters,
35             xres => int( $xres ),
36             yres => int( $yres ),
37             progressId => $progressId,
38             debug => $debug,
39             };
40 0 0         $class = (ref $class ? ref $class : $class );
41 0           bless $self, $class;
42              
43 0           my $logger = $BeamerReveal::Log::logger;
44              
45             $self->{compiler} = File::Which::which( $self->{presentationparameters}->{compiler} )
46 0 0         or $logger->fatal( "Error: your setup is incomplete, I cannot find your $self->{presentationparameters}->{compiler } compiler (should be part of your TeX installation)\n" .
47             "Make sure it is accessible in a directory on your PATH list variable\n" );
48            
49            
50 0 0         $self->{pdftoppm} = File::Which::which( 'pdftoppm' )
51             or $logger->fatal( "Error: your setup is incomplete, I cannot find pdftoppm (part of the poppler library)\n" .
52             "Install 'Poppler-utils' and make sure pdftoppm is accessible in a directory on your PATH list variable\n" );
53              
54 0           $self->{slides} = "$self->{base}/media/Slides";
55            
56 0           return $self;
57             }
58              
59              
60              
61              
62             sub toJPG {
63 0     0 1   my $self = shift;
64              
65 0           my $logger = $BeamerReveal::Log::logger;
66              
67             # pdf generate of n slides, and jpeg generation of n slides
68             $logger->progress( $self->{progressId},
69 0           0, "notes generation", 2 * $self->{presentationparameters}->{nofnotes} );
70            
71             #############################
72             # write altered source file
73            
74             # 1. read the source file
75 0           $logger->log( 2, "- Reading LaTeX source file" );
76 0           my $sourceFileName = $self->{presentationparameters}->{sourcefilename};
77 0           my $source = do {
78 0           local $/ = undef;
79 0 0         open my $fh, "<". $sourceFileName
80             or $logger->fatal( "Error: could not open your LaTeX source file '$sourceFileName' for reading" );
81 0           <$fh>;
82             };
83              
84             # 2. alter it
85 0           my $notesMagic = '';
86 0           $source =~ s/\\begin\{document\}/\\setbeamertemplate\{note page\}\{\\insertnote\}\n\\setbeameroption\{show only notes\}\n\\begin\{document\}/;
87              
88              
89             # 3. write it to a temporary file
90 0           $logger->log( 2, "- Writing LaTeX notes file" );
91 0           my $id = Data::UUID->new();
92 0           my $notesFileName;
93 0           do {
94 0           my $uuid = $id->create();
95 0           $uuid = $id->to_string( $uuid );
96 0           $notesFileName = $sourceFileName;
97 0           $notesFileName =~ s/(\.\w)/-notes-$uuid$1/;
98             } until( ! -e $notesFileName );
99 0           my $notesFile = IO::File->new();
100 0 0         $notesFile->open( ">$notesFileName" )
101             or $logger->fatal( "Error could not open notes file '$notesFileName' for writing" );
102 0           print $notesFile $source;
103 0           $notesFile->close();
104              
105             #############
106             # compile it
107              
108             # 4. run TeX
109             my $cmd = [ $self->{compiler},
110 0           "-halt-on-error", "-interaction=nonstopmode", "-output-directory=$self->{pdf_dir}", "$notesFileName" ];
111 0           my $logFilename = $notesFileName;
112 0           $logFilename =~ s/\.\w+$/.log/;
113              
114              
115            
116 0           my $counter = 0;
117 0           my $progress = MCE::Shared::Scalar->new( 0 );
118             BeamerReveal::IPC::Run::runsmart( $cmd, 1, qr/\[(\d+)\]/,
119             sub {
120 0     0     while( scalar @_ ) {
121 0           my $a = shift @_;
122 0           while( $a > $counter ) {
123 0           ++$counter;
124 0           $progress->incr();
125             $logger->progress( $self->{progressId},
126 0           $progress->get(), "pdf generation" );
127             }
128             }
129             },
130 0           1, # coreId
131             2, # indent
132             undef, # directory
133             "Error: notes generation failed: check $logFilename"
134             );
135              
136             ####################
137             # convert it to jpg
138 0           $notesFileName =~ s/\.\w+$/.pdf/;
139             $cmd = [ $self->{pdftoppm},
140             $notesFileName,
141             "$self->{output_dir}/$self->{slides}/notes",
142             '-jpeg',
143             '-jpegopt',
144             'optimize=y,quality=85',
145 0           '-scale-to-x', @{[1.5*$self->{xres}]},
146 0           '-scale-to-y', @{[1.5*$self->{yres}]},
  0            
147             '-progress',
148             ];
149 0           my $maxNote = 0;
150             BeamerReveal::IPC::Run::runsmart( $cmd, 2, qr/^(\d+) (\d+) .*$/,
151             sub {
152 0     0     while( scalar @_ ) {
153 0           my ( $a, $b ) = ( shift @_, shift @_ );
154             $logger->progress( $self->{progressId},
155 0           $a, "note $1/$2", $b );
156 0           $maxNote = $b;
157             }
158             },
159 0           0, # coreId
160             2, # indent
161             undef, # directory
162             "Error: notes conversion failed, is your notes PDF damaged?"
163             );
164              
165 0           $notesFileName =~ s/\.\w+$//;
166 0           foreach my $file ( glob( "$notesFileName*" ) ) {
167 0 0         unlink $file unless( defined $self->{debug} );
168             }
169              
170 0           my @list = ( 0 ); # create a dummy element to allow for one-indexed addressing
171            
172 0           for (my $i = 1; $i <= $maxNote; ++$i ) {
173 0           push @list, sprintf( "$self->{slides}/notes-%0" . nofdigits( $maxNote ) . 'd.jpg',
174             $i );
175             }
176 0           return \@list;
177             }
178              
179             1;
180              
181             __END__