6 # Copyright (C) 2010 Red Hat Inc.
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software
20 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 use Cwd qw(getcwd abs_path);
30 use Glib qw(TRUE FALSE);
38 techtalk-pse - superior technical demonstration software
42 cd /path/to/talk/; techtalk-pse
44 techtalk-pse /path/to/talk/
48 Tech Talk "Platinum Supreme Edition" (PSE) is Linux Presentation
49 Software designed by technical people to give technical software
50 demonstrations to other technical people. It is designed to be simple
51 to use (for people who know how to use an editor and the command line)
52 and powerful, so that you can create informative, technically accurate
53 and entertaining talks and demonstrations.
55 Tech Talk PSE is good at opening editors at the right place, opening
56 shell prompts with preloaded history, compiling and running things
57 during the demonstration, displaying text, photos, figures and video.
59 Tech Talk PSE is I<bad> at slide effects, chart junk and bullet
62 This manual page covers all the documentation you will need to use
63 Tech Talk PSE. The next section covers running the tool from the
64 command line. After that there is a L</TUTORIAL> section to get you
65 started. Then there is a detailed L</REFERENCE> section. Finally
66 there is a discussion on L<WHAT MAKES A GOOD TALK>.
68 =head1 RUNNING THE TOOL FROM THE COMMAND LINE
70 A Tech Talk PSE talk is not a single file, but a directory full of
71 files. (If you want to start a new talk, see the L</TUTORIAL> section
72 below). To display or run the talk, change into the directory
73 containing all those files and run the C<techtalk-pse> command:
75 cd /path/to/talk/; techtalk-pse
77 You can also run C<techtalk-pse> without changing directory, instead
78 specifying the path to the talk:
80 techtalk-pse /path/to/talk/
92 Display brief help and exit.
100 Start at the last slide.
102 You cannot use this with the B<-n> / B<--start> option.
108 =item B<-n SLIDE> | B<--start SLIDE>
110 Start at the named slide. I<SLIDE> is the shortest unique prefix of
111 the slide name, so to start at a slide named
112 I<00010-introduction.html>, you could use I<-n 00010> or I<-n 00010-intro>,
113 or give the full filename I<-n 00010-introduction.html>.
115 The default is to start at the first slide in the talk.
123 Don't display the initial "splash" screen which advertises Tech Talk
124 PSE to your audience. Just go straight into the talk.
132 Display verbose messages, useful for debugging or tracing
133 what the program is doing.
141 Display version number and exit.
149 GetOptions ("help|?" => \$help,
151 "mozembed" => \$mozembed,
152 "mozembed-first" => \$mozembed_first,
153 "mozembed-last" => \$mozembed_last,
155 "splash!" => \$splash,
156 "start=s" => \$start,
157 "verbose" => \$verbose,
158 "version" => \$version,
165 pod2usage (1) if $help;
167 print "@PACKAGE@ @VERSION@\n";
170 die "techtalk-pse: cannot use --start and --last options together\n"
171 if defined $last && defined $start;
173 # Run with --mozembed: see below.
174 run_mozembed () if $mozembed;
176 # Normal run of the program.
177 die "techtalk-pse: too many arguments\n" if @ARGV >= 2;
179 # Get the true name of the program.
186 chdir $d or die "techtalk-pse: chdir: $d: $!";
188 # XXX In future allow people to specify an archive and unpack
190 die "techtalk-pse: argument is not a directory"
202 foreach (glob ("*")) {
203 if (/^(\d+)(?:-.*)\.(html|sh)$/) {
204 print STDERR "reading $_\n" if $verbose;
208 warn "techtalk-pse: $_: command file is not executable (+x)\n"
209 if $ext eq "sh" && ! -x $_;
211 my $h = { name => $_, seq => $1, ext => $2, i => $i };
216 print STDERR "ignoring $_\n" if $verbose;
221 $files[0]->{first} = 1;
222 $files[$#files]->{last} = 1;
226 print STDERR "read ", 0+@files, " files\n" if $verbose;
228 warn "techtalk-pse: no files found, continuing anyway ...\n"
231 # Work out what slide we're starting on.
233 if (defined $current) {
234 die "start slide not implemented yet XXX"
237 $current = $files[0];
239 # else $current is undefined
242 my $w = Gtk2::AboutDialog->new;
243 $w->set_authors ("Richard W.M. Jones");
245 "Superior technical demonstration software\n".
248 "↑ — Go back one slide\n".
249 "↓ — Go forward one slide\n"
251 $w->set_program_name ("Tech Talk Platinum Supreme Edition (PSE)");
252 $w->set_version ("@VERSION@");
253 $w->set_website ("http://people.redhat.com/~rjones");
254 $w->set_license ("GNU General Public License v2 or above");
256 print STDERR "calling \$w->destroy on about dialog\n" if $verbose;
261 if (defined $current) {
262 my $go = show_slide ($current);
264 print STDERR "go = $go\n" if $verbose;
265 last MAIN if $go eq "QUIT";
267 my $i = $current->{i};
268 print STDERR "i = $i\n" if $verbose;
269 $i-- if $go eq "PREV" && $i > 0;
270 $i++ if $go eq "NEXT" && $i+1 < @files;
271 $current = $files[$i];
274 print "No slides found. Press any key to reload directory ...\n";
278 # Reread directory between slides.
281 if (defined $current && !exists $files{$current->{name}}) {
282 # Current slide was deleted.
284 $current = $files[0] if @files;
292 # Display an HTML page.
293 if ($slide->{ext} eq "html") {
294 # MozEmbed is incredibly crashy, so we run ourself as a
295 # subprocess, so when it segfaults we don't care.
296 my @cmd = ($0, "--mozembed");
297 push @cmd, "--mozembed-first" if exists $slide->{first};
298 push @cmd, "--mozembed-last" if exists $slide->{last};
300 my $url = "file://" . $cwd . "/" . $slide->{name};
303 die "failed to execute subcommand: ", join(" ", @cmd), ": $!\n"
306 # Subcommand probably segfaulted, just continue to next slide.
319 # Run a shell command.
320 elsif ($slide->{ext} eq "sh") {
322 # http://docstore.mik.ua/orelly/perl/cookbook/ch10_17.htm
323 local *run_process = sub {
325 die "fork: $!" unless defined $pid;
329 $ENV{PATH} = ".:$ENV{PATH}";
330 exec ($slide->{name});
331 die "failed to execute command: ", $slide->{name}, ": $!";
335 local *kill_process = sub {
336 print STDERR "sending TERM signal to process group $pid\n"
344 my $w = Gtk2::Window->new ();
346 my $s = $w->get_screen;
347 $w->set_default_size ($s->get_width, -1);
349 $w->set_decorated (0);
351 my $bbox = Gtk2::HButtonBox->new ();
352 $bbox->set_layout ('start');
354 my $bnext = Gtk2::Button->new ("Next slide");
355 $bnext->signal_connect (clicked => sub { $r = "NEXT"; $w->destroy });
356 $bnext->set_sensitive (!(exists $slide->{last}));
359 my $bback = Gtk2::Button->new ("Back");
360 $bback->signal_connect (clicked => sub { $r = "PREV"; $w->destroy });
361 $bback->set_sensitive (!(exists $slide->{first}));
364 my $brestart = Gtk2::Button->new ("Kill & restart");
365 $brestart->signal_connect (clicked => sub {
369 $bbox->add ($brestart);
371 my $bquit = Gtk2::Button->new ("Quit");
372 $bquit->signal_connect (clicked => sub { $r = "QUIT"; $w->destroy });
374 $bbox->set_child_secondary ($bquit, 1);
378 $w->signal_connect (destroy => sub {
387 print STDERR "returning r=$r\n" if $verbose;
392 # If invoked with the --mozembed parameter then we just display a
393 # single page. This is just to prevent crashes in MozEmbed from
394 # killing the whole program.
399 my $w = Gtk2::Window->new ();
400 my $vbox = Gtk2::VBox->new ();
401 my $moz = Gtk2::MozEmbed->new ();
403 my $bbox = Gtk2::HButtonBox->new ();
404 $bbox->set_layout ('start');
406 $vbox->pack_start ($bbox, 0, 0, 0);
409 #$w->set_default_size (640, 480);
412 my $bnext = Gtk2::Button->new ("Next slide");
413 $bnext->signal_connect (clicked => sub { $r = 0; $w->destroy });
414 $bnext->set_sensitive (!$mozembed_last);
417 my $bback = Gtk2::Button->new ("Back");
418 $bback->signal_connect (clicked => sub { $r = 1; $w->destroy });
419 $bback->set_sensitive (!$mozembed_first);
422 my $bquit = Gtk2::Button->new ("Quit");
423 $bquit->signal_connect (clicked => sub { $r = 2; $w->destroy });
425 $bbox->set_child_secondary ($bquit, 1);
427 $w->signal_connect (destroy => sub {
433 $moz->load_url ($ARGV[0]);
445 =head1 WHAT MAKES A GOOD TALK
449 The Cognitive Style of PowerPoint, Tufte, Edward R.
453 Richard W.M. Jones L<http://people.redhat.com/~rjones/>
457 Copyright (C) 2010 Red Hat Inc.
459 This program is free software; you can redistribute it and/or modify
460 it under the terms of the GNU General Public License as published by
461 the Free Software Foundation; either version 2 of the License, or
462 (at your option) any later version.
464 This program is distributed in the hope that it will be useful,
465 but WITHOUT ANY WARRANTY; without even the implied warranty of
466 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
467 GNU General Public License for more details.
469 You should have received a copy of the GNU General Public License
470 along with this program; if not, write to the Free Software
471 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.