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.
147 GetOptions ("help|?" => \$help,
149 "mozembed" => \$mozembed,
151 "splash!" => \$splash,
152 "start=s" => \$start,
153 "verbose" => \$verbose,
154 "version" => \$version,
161 pod2usage (1) if $help;
163 print "@PACKAGE@ @VERSION@\n";
166 die "techtalk-pse: cannot use --start and --last options together\n"
167 if defined $last && defined $start;
169 die "techtalk-pse: too many arguments\n" if !$mozembed && @ARGV >= 2;
171 # Get the true name of the program.
178 chdir $d or die "techtalk-pse: chdir: $d: $!";
180 # XXX In future allow people to specify an archive and unpack
182 die "techtalk-pse: argument is not a directory"
186 # Get the talk directory and set environment variable $talkdir
187 # which is inherited by all the scripts.
188 my $talkdir = getcwd;
189 $ENV{talkdir} = $talkdir;
199 foreach (glob ("*")) {
200 if (/^(\d+)(?:-.*)\.(html|sh)$/) {
201 print STDERR "reading $_\n" if $verbose;
205 warn "techtalk-pse: $_: command file is not executable (+x)\n"
206 if $ext eq "sh" && ! -x $_;
208 my $h = { name => $_, seq => $1, ext => $2, i => $i };
213 print STDERR "ignoring $_\n" if $verbose;
218 $files[0]->{first} = 1;
219 $files[$#files]->{last} = 1;
223 print STDERR "read ", 0+@files, " files\n" if $verbose;
225 warn "techtalk-pse: no files found, continuing anyway ...\n"
228 # Run with --mozembed: see below.
229 run_mozembed () if $mozembed;
231 # Else, normal run of the program ...
233 # Work out what slide we're starting on.
235 if (defined $current) {
236 die "start slide not implemented yet XXX"
239 $current = $files[0];
241 # else $current is undefined
244 my $w = Gtk2::AboutDialog->new;
245 $w->set_authors ("Richard W.M. Jones");
247 "Superior technical demonstration software\n"
249 $w->set_program_name ("Tech Talk Platinum Supreme Edition (PSE)");
250 $w->set_version ("@VERSION@");
251 $w->set_website ("http://people.redhat.com/~rjones");
252 $w->set_license ("GNU General Public License v2 or above");
254 print STDERR "calling \$w->destroy on about dialog\n" if $verbose;
257 # The dialog doesn't really get destroyed here. We have
258 # to add this hack to really destroy it.
259 Glib::Idle->add (sub { Gtk2->main_quit; return FALSE; });
264 if (defined $current) {
265 my $go = show_slide ($current);
267 print STDERR "go = $go\n" if $verbose;
268 last MAIN if $go eq "QUIT";
270 my $i = $current->{i};
271 print STDERR "i = $i\n" if $verbose;
272 $i-- if $go eq "PREV" && $i > 0;
273 $i++ if $go eq "NEXT" && $i+1 < @files;
274 $i = 0 if $go eq "FIRST";
275 $i = $#files if $go eq "LAST";
276 $i = $1 if $go =~ /^I_(\d+)$/;
277 $current = $files[$i];
280 print "No slides found. Press any key to reload directory ...\n";
284 # Reread directory between slides.
287 if (defined $current && !exists $files{$current->{name}}) {
288 # Current slide was deleted.
290 $current = $files[0] if @files;
298 # Display an HTML page.
299 if ($slide->{ext} eq "html") {
300 # MozEmbed is incredibly crashy, so we run ourself as a
301 # subprocess, so when it segfaults we don't care. If all goes
302 # well and it doesn't crash, it should print a line 'RESULT FOO'
303 # where 'FOO' is the instruction (eg. 'NEXT', 'PREV', 'QUIT' etc).
304 my @cmd = ($0, "--mozembed", $talkdir, $slide->{name});
305 print STDERR "running subcommand: ", join (" ", @cmd), "\n"
308 or die "failed to execute subcommand: ", join(" ", @cmd), ": $!\n";
311 if (/^RESULT ([A-Z]+.*)/) {
313 print STDERR "subcommand result: $r\n" if $verbose;
317 # No RESULT line? Subcommand probably segfaulted, just
318 # continue to next slide.
322 # Run a shell command.
323 elsif ($slide->{ext} eq "sh") {
325 # http://docstore.mik.ua/orelly/perl/cookbook/ch10_17.htm
326 local *run_process = sub {
328 die "fork: $!" unless defined $pid;
332 exec ("./".$slide->{name});
333 die "failed to execute command: ", $slide->{name}, ": $!";
337 local *kill_process = sub {
338 print STDERR "sending TERM signal to process group $pid\n"
346 my $w = Gtk2::Window->new ();
348 my $s = $w->get_screen;
349 $w->set_default_size ($s->get_width, -1);
351 $w->set_decorated (0);
354 make_button_bar ((exists $slide->{first}),
355 (exists $slide->{last}),
356 sub { $r = $_[0]; $w->destroy },
365 $w->signal_connect (destroy => sub {
374 print STDERR "returning r=$r\n" if $verbose;
379 # If invoked with the --mozembed parameter then we just display a
380 # single page. This is just to prevent crashes in MozEmbed from
381 # killing the whole program.
384 my $w = Gtk2::Window->new ();
385 my $vbox = Gtk2::VBox->new ();
386 my $moz = Gtk2::MozEmbed->new ();
391 $current = $files{$name};
392 my $url = "file://$talkdir/$name";
395 make_button_bar ($current->{first}, $current->{last},
396 sub { print "RESULT ", $_[0], "\n"; $w->destroy }
399 $vbox->pack_start ($bbox, 0, 0, 0);
402 #$w->set_default_size (640, 480);
405 $w->signal_connect (destroy => sub {
411 $moz->load_url ($url);
418 # Make the standard button bar across the top of the page.
426 my $bbox = Gtk2::Toolbar->new ();
430 my $bnext = Gtk2::ToolButton->new (undef, "Next slide");
431 $bnext->signal_connect (clicked => sub { &$cb ("NEXT") });
432 $bnext->set_sensitive (!$last);
433 $bbox->insert ($bnext, $i++);
435 my $bback = Gtk2::ToolButton->new (undef, "Back");
436 $bback->signal_connect (clicked => sub { &$cb ("PREV") });
437 $bback->set_sensitive (!$first);
438 $bbox->insert ($bback, $i++);
440 if (exists $params{restart}) {
441 $bbox->insert (Gtk2::SeparatorToolItem->new (), $i++);
443 my $brestart = Gtk2::ToolButton->new (undef, "Kill & restart");
444 $brestart->signal_connect (clicked => $params{restart});
445 $bbox->insert ($brestart, $i++);
448 my $sep = Gtk2::SeparatorToolItem->new ();
449 $sep->set_expand (TRUE);
450 $sep->set_draw (FALSE);
451 $bbox->insert ($sep, $i++);
453 my $optsmenu = Gtk2::Menu->new ();
455 my $bfirst = Gtk2::MenuItem->new ("First slide");
456 $bfirst->signal_connect (activate => sub { \&$cb ("FIRST") });
458 $optsmenu->append ($bfirst);
460 my $blast = Gtk2::MenuItem->new ("Last slide");
461 $blast->signal_connect (activate => sub { \&$cb ("LAST") });
463 $optsmenu->append ($blast);
465 my $slidesmenu = Gtk2::Menu->new ();
467 my $item = Gtk2::MenuItem->new ($_->{name});
469 $item->signal_connect (activate => sub { \&$cb ("I_$index") });
470 $item->set_sensitive ($current->{i} != $index);
472 $slidesmenu->append ($item);
475 my $bslides = Gtk2::MenuItem->new ("Slides");
476 $bslides->set_submenu ($slidesmenu);
478 $optsmenu->append ($bslides);
480 my $sep2 = Gtk2::SeparatorMenuItem->new ();
482 $optsmenu->append ($sep2);
484 my $bscreenshot = Gtk2::MenuItem->new ("Take a screenshot");
485 $bscreenshot->signal_connect (activate => sub { screenshot () });
486 $bscreenshot->show ();
487 $optsmenu->append ($bscreenshot);
489 my $sep3 = Gtk2::SeparatorMenuItem->new ();
491 $optsmenu->append ($sep3);
493 my $bquit = Gtk2::MenuItem->new ("Quit");
494 $bquit->signal_connect (activate => sub { \&$cb ("QUIT") });
496 $optsmenu->append ($bquit);
498 my $boptions = Gtk2::MenuToolButton->new (undef, "Options");
499 #$boptions->signal_connect (clicked =>
500 # sub { $optsmenu->popup (undef, undef, undef, undef, ?, ?) } );
501 $bbox->insert ($boptions, $i++);
502 $boptions->set_menu ($optsmenu);
507 # Try running the external "gnome-screenshot" program, if it's
508 # available, else take a screenshot using gdk routines.
511 system ("gnome-screenshot");
514 # We are going to save the entire screen.
515 my $root = Gtk2::Gdk->get_default_root_window ();
516 my ($width, $height) = $root->get_size;
518 # Create blank pixbuf to hold the image.
519 my $gdkpixbuf = Gtk2::Gdk::Pixbuf->new ('rgb',
520 0, 8, $width, $height);
522 $gdkpixbuf->get_from_drawable ($root, $root->get_colormap (),
523 0, 0, 0, 0, $width, $height);
526 $i++ while -f "screenshot$i.png";
527 $gdkpixbuf->save ("screenshot$i.png", 'png');
539 =head2 START WRITING A TALK
541 [Before you start writing your real talk, I urge you to read
542 L</WHAT MAKES A GOOD TALK> below].
544 To start your talk, all you have to do is to make a new directory
550 A tech talk consists of HTML files ("slides") and shell scripts. The
551 filenames must start with a number, followed optionally by a
552 description, followed by the extension (C<.html> or C<.sh>). So to
553 start our talk with two slides:
555 echo "This is the introduction" > 0010-introduction.html
556 echo "This is the second slide" > 0020-second.html
558 To run it, run the command from within the talk directory:
562 Any other file in the directory is ignored, so if you want to add
563 Makefiles, version control files etc, just go ahead.
565 =head2 TIPS FOR WRITING HTML
567 You may have your own techniques and tools for writing HTML, so
568 this section is just to share my ideas. I start every
569 HTML file with a standard stylesheet and Javascript header:
571 <link rel="stylesheet" href="style.css" type="text/css"/>
572 <script src="code.js" type="text/javascript"></script>
574 That just ensures that I can put common styling instructions for all
575 my slides in a single file (C<style.css>), and I have one place where
576 I can add all Javascript, if I need to use any (C<code.js>).
578 =head3 BACKGROUNDS, FONTS AND LOGOS
580 To add a common background and font size to all slides, put this in
585 background: url(background-image.jpg) no-repeat;
588 To add a logo in one corner:
591 background: url(logo.jpg) top right no-repeat;
594 =head3 SCALING AND CENTERING
596 Scaling slide text and images so that they appear at the same
597 proportionate size for any screen resolution can be done using
599 L<https://developer.mozilla.org/En/DOM/window.innerHeight>).
601 If you want to center text horizontally, use CSS, eg:
607 To center text vertically, CSS3 is supposed to offer a solution some
608 time, but while you're waiting for that try
609 L<http://www.w3.org/Style/Examples/007/center#vertical>.
611 =head3 PREVIEWING HTML
613 I find it helpful to have Firefox open to display the HTML files and
614 styles as I edit them. Just start firefox in the talk directory:
616 firefox file://$(pwd) &
618 When you edit an HTML file, click the Firefox reload button to
619 immediately see your changes.
621 Tech Talk PSE uses Mozilla embedding to display HTML, which uses the
622 same Mozilla engine as Firefox, so what you should see in Firefox
623 should be identical to what Tech Talk PSE displays.
625 =head2 CREATING FIGURES
627 Use your favorite tool to draw the figure, convert it to an image (in
628 any format that the Mozilla engine can display) and include it using
629 an C<E<lt>imgE<gt>> tag, eg:
633 Suitable tools include: XFig, GnuPlot, GraphViz, and many TeX tools
634 such as PicTex and in particular TikZ.
636 =head2 EMBEDDING VIDEOS, ANIMATIONS, ETC.
638 Using HTML 5, embedding videos in the browser is easy. See:
639 L<https://developer.mozilla.org/En/Using_audio_and_video_in_Firefox>
641 For animations, you could try L<Haxe|http://haxe.org/> which has a
642 Javascript back-end. There are many other possibilities.
644 If you are B<sure> that the venue will have an internet connection,
645 why not embed a YouTube video.
647 =head2 DISPLAYING EXISTING WEB PAGES
649 Obviously you could just have an HTML file that contains a redirect to
652 <meta http-equiv="Refresh" content="0; url=http://www.example.com/">
654 However if you want your talk to work offline, then it's better to
655 download the web page in advance, eg. using Firefox's "Save Page As
656 -E<gt> Web Page, complete" feature, into the talk directory, then
657 either rename or make a symbolic link to the slide name:
659 ln -s "haXe - Welcome to haXe.html" 0010-haxe-homepage.html
661 =head2 TIPS FOR WRITING SHELL SCRIPTS
663 Make sure each C<*.sh> file you write is executable, otherwise Tech
664 Talk PSE won't be able to run it. (The program gives a warning if you
667 A good idea is to start each script by sourcing some common functions.
668 All my scripts start with:
673 where C<functions> is another file (ignored by Tech Talk PSE) which
674 contains common functions for setting shell history and starting a
677 In C<functions>, I have:
679 # -*- shell-script -*-
681 # Place any local environment variables required in 'local'.
682 if [ -f local ]; then source local; fi
686 export HISTFILE=$talkdir/history
693 echo "$@" >> $HISTFILE
698 # Make $HISTFILE unwritable so the shell won't update it
702 # Run gnome-terminal.
706 --geometry=+100+100 \
709 -e '/bin/bash --norc' \
713 By initializing the shell history, during your talk you can rapidly
714 recall commands to start parts of the demonstration just by hitting
715 the Up arrow. A complete shell script from one of my talks would look
720 add_history guestfish -i debian.img
721 terminal --title="Examining a Debian guest image in guestfish"
723 This is just a starting point for your own scripts. You may want to
724 use a different terminal, such as xterm, and you may want to adjust
729 =head2 ORDER OF FILES
731 Tech Talk PSE displays the slides in the directory in lexicographic
732 order (the same order as C<LANG=C ls -1>). Only files matching the
733 following regexp are considered:
735 ^(\d+)(?:-.*)\.(html|sh)$
737 For future compatibility, you should ensure that every slide has a
738 unique numeric part (ie. I<don't> have C<0010-aaa.html> and
739 C<0010-bbb.html>). This is because in future we want to have the
740 ability to display multiple files side by side.
742 Also for future compatibility, I<don't> use file names that have an
743 uppercase letter immediately after the numeric part. This is because
744 in future we want to allow placement hints using filenames like
745 C<0010L-on-the-left.html> and C<0010R-on-the-right.html>.
747 =head2 BASE URL AND CURRENT DIRECTORY
749 The base URL is set to the be the directory containing the talk files.
750 Thus you should use relative paths, eg:
754 You can also place assets into subdirectories, because subdirectories
755 are ignored by Tech Talk PSE, eg:
757 <img src="images/fig1.gif">
759 When running shell scripts, the current directory is also set to be
760 the directory containing the talk files, so the same rules about using
761 relative paths apply there too.
763 The environment variable C<$talkdir> is exported to scripts and it
764 contains the absolute path of the directory containing the talk files.
765 When a script is run, the current directory is the same as
766 C<$talkdir>, but if your script changes directory (eg. into a
767 subdirectory containing supporting files) then it can be useful to use
768 C<$talkdir> to refer back to the original directory.
770 =head1 WHAT MAKES A GOOD TALK
772 I like what Edward Tufte writes, for example his evisceration of
773 PowerPoint use at NASA here:
774 L<http://www.edwardtufte.com/bboard/q-and-a-fetch-msg?msg_id=0001yB>
776 However it is sometimes hard to translate his ideas into clear
777 presentations, and not all of that is the fault of the tools. Here
778 are my thoughts and rules on how to deliver a good talk.
780 B<First, most important rule:> Before you start drawing any slides at
781 all, write your talk as a short essay.
783 This is the number one mistake that presenters make, and it is partly
784 a tool fault, because PowerPoint, OpenOffice, even Tech Talk PSE, all
785 open up on an initial blank slide, inviting you to write a title and
786 some bullet points. If you start that way, you will end up using the
787 program as a kind of clumsy outlining tool, and then reading that
788 outline to your audience. That's boring and a waste of time for you
789 and your audience. (It would be quicker for them just to download the
790 talk and read it at home).
792 B<Secondly:> How long do you want to spend preparing the talk? A good
793 talk, with a sound essay behind it, well thought out diagrams and
794 figures, and interesting demonstrations, takes many hours to prepare.
795 How many hours? I would suggest thinking about how many hours of
796 effort your audience are putting in. Even just 20 people sitting
797 there for half an hour is 10 man-hours of attention, and that is a
798 very small talk, and doesn't include all the extra time and hassle
799 that it took to get them all in one place.
801 I don't think you can get away with spending less than two full days
802 preparing a talk, if you want to master the topic and draw up accurate
803 slides. Steve Jobs is reputed to spend weeks preparing his annual
804 sales talk to the Apple faithful.
806 B<Thirdly:> Now that you're going to write your talk as an essay, what
807 should go in the slides? I would say that you should consider
808 delivering the essay, I<not> the slides, to people who don't make the
809 talk. An essay can be turned into an article or blog posting, whereas
810 even "read-out-the-bullet-point" slides have a low information
811 density, large size, and end-user compatibility problems (*.pptx
814 What, then, goes on the slides? Anything you cannot just say:
815 diagrams, graphs, videos, animations, and of course (only with Tech
816 Talk PSE!) demonstrations.
818 B<Lastly:> Once you've got your talk as an essay and slides, practice,
819 practice and practice again. Deliver the talk to yourself in the
820 mirror, to your colleagues. Practice going backwards and forwards
821 through the slides, using your actual laptop and the software so you
822 know what to click and what keys to press. Partly memorize what you
823 are going to say (but use short notes written on paper if you need
828 The Cognitive Style of PowerPoint, Tufte, Edward R.
832 Richard W.M. Jones L<http://people.redhat.com/~rjones/>
836 Copyright (C) 2010 Red Hat Inc.
838 This program is free software; you can redistribute it and/or modify
839 it under the terms of the GNU General Public License as published by
840 the Free Software Foundation; either version 2 of the License, or
841 (at your option) any later version.
843 This program is distributed in the hope that it will be useful,
844 but WITHOUT ANY WARRANTY; without even the implied warranty of
845 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
846 GNU General Public License for more details.
848 You should have received a copy of the GNU General Public License
849 along with this program; if not, write to the Free Software
850 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.