Re-add some missing files.
authorCarl Hetherington <cth@carlh.net>
Sun, 14 Apr 2013 13:08:57 +0000 (14:08 +0100)
committerCarl Hetherington <cth@carlh.net>
Sun, 14 Apr 2013 13:08:57 +0000 (14:08 +0100)
18 files changed:
dcpomatic.desktop.in [new file with mode: 0644]
doc/manual/dcpomatic-html.xsl [new file with mode: 0644]
doc/manual/dcpomatic-pdf.xml [new file with mode: 0644]
doc/manual/dcpomatic.css [new file with mode: 0644]
doc/manual/dcpomatic.sty [new file with mode: 0644]
doc/manual/dcpomatic.xml [new file with mode: 0644]
icons/128x128/dcpomatic.png [new file with mode: 0644]
icons/16x16/dcpomatic.png [new file with mode: 0644]
icons/22x22/dcpomatic.png [new file with mode: 0644]
icons/32x32/dcpomatic.png [new file with mode: 0644]
icons/48x48/dcpomatic.png [new file with mode: 0644]
icons/64x64/dcpomatic.png [new file with mode: 0644]
run/dcpomatic [new file with mode: 0755]
src/tools/dcpomatic.cc [new file with mode: 0644]
windows/dcpomatic.bmp [new file with mode: 0644]
windows/dcpomatic.ico [new file with mode: 0644]
windows/dcpomatic.rc [new file with mode: 0644]
windows/dcpomatic_taskbar.ico [new file with mode: 0644]

diff --git a/dcpomatic.desktop.in b/dcpomatic.desktop.in
new file mode 100644 (file)
index 0000000..aabd992
--- /dev/null
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Encoding=UTF-8
+Version=1.0
+Type=Application
+Terminal=false
+Exec=@PREFIX@/bin/dcpomatic
+Name=DCP-o-matic
+Icon=dcpomatic
+Comment=DCP generator
+Categories=AudioVideo;Video
diff --git a/doc/manual/dcpomatic-html.xsl b/doc/manual/dcpomatic-html.xsl
new file mode 100644 (file)
index 0000000..144675d
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:fo="http://www.w3.org/1999/XSL/Format"
+                version="1.0">
+
+<!-- Our CSS -->
+<xsl:param name="html.stylesheet" select="'dcpomatic.css'"/>
+
+<!-- I can't fathom xmlto's logic with image scaling, so I've turned it off -->
+<xsl:param name="ignore.image.scaling" select="1"/>
+
+</xsl:stylesheet>
diff --git a/doc/manual/dcpomatic-pdf.xml b/doc/manual/dcpomatic-pdf.xml
new file mode 100644 (file)
index 0000000..414fb64
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version='1.0' encoding="iso-8859-1"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'>
+
+<!-- colour links in black -->
+<xsl:param name="latex.hyperparam">colorlinks,linkcolor=black,urlcolor=black</xsl:param>
+
+<!-- no revhistory table -->
+<xsl:param name="doc.collab.show">0</xsl:param>
+<xsl:param name="latex.output.revhistory">0</xsl:param>
+
+<!-- hack images to vaguely the right size -->
+<xsl:param name="imagedata.default.scale">scale=0.6</xsl:param>
+
+<!-- don't make too-ridiculous section numbers -->
+<xsl:param name="doc.section.depth">3</xsl:param>
+
+</xsl:stylesheet>
diff --git a/doc/manual/dcpomatic.css b/doc/manual/dcpomatic.css
new file mode 100644 (file)
index 0000000..0e4982f
--- /dev/null
@@ -0,0 +1,19 @@
+body {
+    font-family: luxi sans, sans-serif;
+    margin-left: 4em;
+    margin-right: 4em;
+    margin-top: 1em;
+    margin-bottom: 1em;
+    background-color: #E2E8EE;
+}
+
+div.sidebar {
+    margin-left: 1em;
+    margin-right: 1em;
+    padding-left: 1em;
+    padding-right: 1em;
+    border-color: #000000;
+    border-width: 2px;
+    border-style: solid;
+    background-color: #E2E8EE;
+}
diff --git a/doc/manual/dcpomatic.sty b/doc/manual/dcpomatic.sty
new file mode 100644 (file)
index 0000000..834e581
--- /dev/null
@@ -0,0 +1,68 @@
+%%
+%% This style is derivated from the docbook one
+%%
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{ardour}[2007/04/04 My DocBook Style]
+
+%% Just use the original package and pass the options
+\RequirePackageWithOptions{docbook}
+
+% Use a nice font
+\usepackage{lmodern}
+
+% Define \dbend as the dangerous bend sign
+\font\manual=manfnt
+\def\dbend{{\manual\char127}}
+
+% Redefine sidebar environment to use the dangerous bend style
+% Danger, Will Robinson!
+\def\sidebar{\begin{trivlist}\item[]\noindent%
+\begingroup\hangindent=2pc\hangafter=-2%\clubpenalty=10000%
+\def\par{\endgraf\endgroup}%
+\hbox to0pt{\hskip-\hangindent\dbend\hfill}\ignorespaces}
+\def\endsidebar{\par\end{trivlist}}
+
+
+% Futz with the title page; basically a copy of
+% /usr/share/texmf/tex/latex/dblatex/style/dbk_title.sty
+% with authors added.
+
+\def\DBKcover{
+\ifthenelse{\equal{\DBKedition}{}}{\def\edhead{}}{\def\edhead{Ed. \DBKedition}}
+
+\pagestyle{empty}
+
+% interligne double
+\setlength{\oldbaselineskip}{\baselineskip}
+\setlength{\baselineskip}{2\oldbaselineskip}
+\textsf{
+\vfill
+\vspace{2.5cm}
+\begin{center}
+  \huge{\textbf{\DBKtitle}}\\ %
+  \ \\ %
+  \ \\ %
+  \Large{\DBKauthor}\\ %
+  \ifx\DBKsubtitle\relax\else%
+    \underline{\ \ \ \ \ \ \ \ \ \ \ }\\ %
+    \ \\ %
+    \huge{\textbf{\DBKsubtitle}}\\ %
+  \fi
+\end{center}
+\vfill
+\setlength{\baselineskip}{\oldbaselineskip}
+\hspace{1cm}
+\vspace{1cm}
+\begin{center}
+\begin{tabular}{p{7cm} p{7cm}}
+\Large{\DBKreference{} \edhead} & \\
+\end{tabular}
+\end{center}
+}
+
+% Format for the other pages
+\newpage
+\setlength{\baselineskip}{\oldbaselineskip}
+%\chead[]{\DBKcheadfront}
+\lfoot[]{}
+}
diff --git a/doc/manual/dcpomatic.xml b/doc/manual/dcpomatic.xml
new file mode 100644 (file)
index 0000000..ee7b960
--- /dev/null
@@ -0,0 +1,932 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE book [
+<!ENTITY % sgml.features "IGNORE">
+<!ENTITY % xml.features "INCLUDE">
+<!ENTITY % dbcent PUBLIC "-//OASIS//ENTITIES DocBook Character Entities V4.5//EN"
+   "/usr/share/xml/docbook/schema/dtd/4.5/dbcentx.mod">
+%dbcent;
+<!ENTITY % extensions SYSTEM "extensions.ent">
+%extensions;
+]>
+<book xmlns="http://docbook.org/ns/docbook" version="5.0" xml:lang="en">
+
+<bookinfo>
+<title>DCP-o-matic</title>
+<author><firstname>Carl</firstname><surname>Hetherington</surname></author>
+</bookinfo>
+
+<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:lang="en">
+<title>Introduction</title>
+
+<para>
+Hello, and welcome to DCP-o-matic!
+</para>
+
+<section>
+<title>What is DCP-o-matic?</title>
+
+<para>
+DCP-o-matic is a program to generate <ulink
+url="http://en.wikipedia.org/wiki/Digital_Cinema_Package">Digital
+Cinema Packages</ulink> (DCPs) from DVDs, Blu-Rays, video files such as MP4
+and AVI, or still images.  The resulting DCPs will play on modern digital
+cinema projectors.
+</para>
+
+<para>
+You might find it useful to make DVDs easier to present, to encode
+independently-shot feature films, or to generate local advertising for
+your cinema.
+</para>
+
+</section>
+
+<section>
+<title>Licence</title>
+
+<para>
+DCP-o-matic is licensed under the <ulink url="http://www.gnu.org/licenses/old-licenses/gpl-2.0.html">GNU GPL</ulink>.
+</para>
+
+</section>
+
+</chapter>
+
+<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:lang="en">
+<title>Installation</title>
+
+<section>
+<title>Windows</title>
+
+<para>
+To install DCP-o-matic on Windows, simply download the installer from
+<ulink url="http://carlh.net/software/dcpomatic">http://carlh.net</ulink>
+and double-click it.  Click through the installer wizard, and
+DCP-o-matic will be installed onto your machine.
+</para>
+
+<para>
+If you are using a 32-bit version of Windows, you will need the 32-bit
+installer.  For 64-bit Windows, either installer will work, but I
+suggest you used the 64-bit version as it will allow DCP-o-matic to
+use more memory.  You may find that DCP-o-matic crashes if you run
+many parallel encoding threads (more than 4) on the 32-bit
+version.
+</para>
+
+</section>
+
+<section>
+<title>Ubuntu Linux</title>
+
+<para>
+You can install DCP-o-matic on Ubuntu 12.04 (&lsquo;Precise
+Pangolin&rsquo;) or 12.10 (&lsquo;Quantal Quetzal&rsquo;) using
+<code>.deb</code> packages: download the appropriate package from
+<ulink
+url="http://carlh.net/software/dcpomatic">http://carlh.net</ulink> and
+double-click it.  Ubuntu will install the necessary bits and pieces
+and set DCP-o-matic up for you.
+</para>
+
+</section>
+
+<section>
+<title>Other Linux distributions</title>
+
+<para>
+Installation on non-Ubuntu Linux is currently a little involved, as
+there are no packages available (yet); you will have to compile it
+from source.  If you are using a non-Ubuntu distribution, do let me
+know via the <ulink url="mailto:dcpomatic@carlh.net">mailing
+list</ulink> and I will see about building some packages.
+</para>
+
+<para>
+The following dependencies are required:
+<itemizedlist>
+<listitem><ulink url="http://ffmpeg.org/">FFmpeg</ulink></listitem>
+<listitem><ulink url="http://www.mega-nerd.com/libsndfile/">libsndfile</ulink></listitem>
+<listitem><ulink url="http://www.openssl.org/">OpenSSL</ulink></listitem>
+<listitem><ulink url="http://www.openjpeg.org/">libopenjpeg</ulink></listitem>
+<listitem><ulink url="http://www.imagemagick.org/script/index.php">ImageMagick</ulink></listitem>
+<listitem><ulink url="http://www.boost.org/">Boost</ulink></listitem>
+<listitem><ulink url="http://www.libssh.org/">libssh</ulink></listitem>
+<listitem><ulink url="http://www.gtk.org/">GTK</ulink></listitem>
+<listitem><ulink url="http://www.wxwidgets.org/">wxWidgets</ulink></listitem>
+<listitem><ulink url="http://carlh.net/software/libdcp/">libdcp</ulink></listitem>
+</itemizedlist>
+</para>
+
+<para>
+Once you have installed the development packages for the dependencies,
+download the source code from <ulink
+url="http://carlh.net/software/dcpomatic">http://carlh.net</ulink>,
+unpack it and run the following commands from inside the source
+directory:
+</para>
+
+<programlisting>
+./waf configure
+./waf build
+sudo ./waf install
+</programlisting>
+
+<para>
+With any luck, this will build and install DCP-o-matic on your system.  To run it, enter:
+</para>
+
+<programlisting>
+dcpomatic
+</programlisting>
+
+<para>
+in a shell.
+</para>
+
+</section>
+</chapter>
+
+<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:lang="en">
+<title>Creating a video DCP</title>
+
+<para>
+In this chapter we will see how to create a video DCP using
+DCP-o-matic.  We will gloss over some of the finer details, which are
+explained in later chapters.
+</para>
+
+<section>
+<title>Creating a new film</title>
+
+<para>
+Let's make a very simple DCP to see how DCP-o-matic works.  First, we
+need some content.  Download the low-resolution trailer for the open
+movie <ulink url="http://sintel.org/">Sintel</ulink> from <ulink
+url="http://ftp.nluug.nl/ftp/graphics/blender/apricot/trailer/Sintel_Trailer1.480p.DivX_Plus_HD.mkv">their
+website</ulink>.  Generally, of course, one would want to use the
+highest-resolution material available, but for this test we will use
+the low-resolution version to save everyone's bandwidth bills.
+</para>
+
+<para>
+Now, start DCP-o-matic and its window will open.  First, we will
+create a new &lsquo;film&rsquo;.  A &lsquo;film&rsquo; is how DCP-o-matic refers to
+a piece of content, along with some settings, which we will make into
+a DCP.  DCP-o-matic stores its data in a folder on your disk while it
+creates the DCP.  You can create a new film by selecting
+<guilabel>New</guilabel> from the <guilabel>File</guilabel> menu, as
+shown in <xref linkend="fig-file-new"/>.
+</para>
+
+<figure id="fig-file-new"> 
+  <title>Creating a new film</title> 
+  <mediaobject>
+    <imageobject> 
+      <imagedata fileref="screenshots/file-new&scs;"/>
+    </imageobject> 
+  </mediaobject>
+</figure>
+
+<para>
+This will open a dialogue box for the new film, as shown in <xref
+linkend="fig-video-new-film"/>.
+</para>
+
+<figure id="fig-video-new-film"> 
+  <title>Dialogue box for creating a new film</title> 
+  <mediaobject>
+    <imageobject> 
+      <imagedata fileref="screenshots/video-new-film&scs;"/>
+    </imageobject> 
+  </mediaobject>
+</figure>
+
+<para>
+In this dialogue box you can choose a name for the film.  This will be
+used to name the folder to store its data in, and also as the initial
+name for the DCP itself.  You can also choose whereabouts you want to create
+the film.  In the example from the figure, DCP-o-matic will create a
+folder called &lsquo;DCP Test&rsquo; inside my home folder (carl) into which it
+will write its working files.
+</para>
+
+<para>
+If you always create your DCPs in a particular folder, you can use
+DCP-o-matic's <guilabel>Preferences</guilabel> to make life a little
+easier by setting the default folder that DCP-o-matic will offer in this dialogue.
+See <xref linkend="ch-preferences"/>.
+</para>
+
+</section>
+
+<section>
+<title>Selecting content</title>
+
+<para>
+The next step is to set the content that you want to use.  Click the
+content selector, as shown in <xref
+linkend="fig-click-content-selector"/>, and a file chooser will
+open for you to select the content file to use, as shown in <xref
+linkend="fig-video-select-content-file"/>.
+</para>
+
+<figure id="fig-click-content-selector">
+  <title>Opening the content selector</title> 
+  <mediaobject>
+    <imageobject> 
+      <imagedata fileref="screenshots/click-content-selector&scs;"/>
+    </imageobject> 
+  </mediaobject>
+</figure>
+
+<figure id="fig-video-select-content-file"> 
+  <title>Selecting a video content file</title> 
+  <mediaobject>
+    <imageobject> 
+      <imagedata fileref="screenshots/video-select-content-file&scs;"/>
+    </imageobject> 
+  </mediaobject>
+</figure>
+
+<para>
+Select your content file and click <guilabel>Open</guilabel>.  In this
+case we are using the Sintel trailer that we downloaded earlier.
+</para>
+
+<para>
+When you do this, DCP-o-matic will take a look at your file.  After a
+short while (when the progress bar at the bottom right of the window
+has finished), you can look through your content using the slider to
+the right of the window, as shown in <xref linkend="fig-examine-thumbs"/>.
+</para>
+
+<figure id="fig-examine-thumbs"> 
+  <title>Examining the content</title>
+  <mediaobject>
+    <imageobject> 
+      <imagedata fileref="screenshots/examine-thumbs&scs;"/>
+    </imageobject> 
+  </mediaobject>
+</figure>
+
+<para>
+Dragging the slider will move through your video.  You can also click
+the <guilabel>Play</guilabel> button to play the content back.  Note
+that there will be no sound, and playback might not be entirely
+accurate (it may be slightly slower or faster than it should be, for
+example).  This player is really only intended for brief inspection of
+content; if you need to check it more thoroughly, use another player
+such as <ulink url="http://projects.gnome.org/totem/index.html">Totem</ulink>, <ulink url="http://www.mplayerhq.hu/design7/news.html">mplayer</ulink> or <ulink url="http://www.videolan.org/vlc/index.html">VLC</ulink>.
+</para>
+
+</section>
+
+<section>
+<title>Setting up</title>
+
+<para>
+Now there are a few things to set up to describe how the DCP should be
+created.  The settings are divided into four tabs: film, video, audio and subtitles.
+</para>
+
+<section>
+<title>Film tab</title>
+
+<para>
+The &lsquo;film&rsquo; tab contains settings that pertain to the whole film, as shown in <xref linkend="fig-film-tab"/>.
+</para>
+
+<figure id="fig-film-tab"> 
+  <title>Film settings tab</title>
+  <mediaobject>
+    <imageobject> 
+      <imagedata fileref="screenshots/film-tab&scs;"/>
+    </imageobject> 
+  </mediaobject>
+</figure>
+
+<para>
+The first thing here is the name.  This is generally set to the title
+of the film that is being encoded.  If <guilabel>Use DCI
+name</guilabel> is not ticked, the name that you specify will be used
+as-is for the name of the DCP.  If <guilabel>Use DCI name</guilabel>
+is ticked, the name that you enter will be used as part of a
+DCI-compliant name.
+</para>
+
+<para>
+Underneath the name field is a preview of the name that the DCP will
+get.  To use a DCI-compliant name, tick the <guilabel>Use DCI
+name</guilabel> checkbox.  The DCI name will be composed using details
+of your content's soundtrack, the current date and other things that
+can be specified in the DCI name details dialogue box, which you can
+open by clicking on the <guilabel>Details</guilabel> button.
+</para>
+
+<para>
+If the DCP name is long, it may not all be visible.  You can see the
+full name by hovering the mouse pointer over the partial name.
+</para>
+
+<para>
+The <guilabel>Trust content's header</guilabel> button starts off
+checked, and this means that DCP-o-matic will use the content's header
+information to determine its length.  If, for some reason, this header
+length is wrong, uncheck the <guilabel>Trust content's
+header</guilabel> button and DCP-o-matic will run through the content
+to find its exact length.  This may take a while for large pieces of content.
+</para>
+
+<para>
+Next up is the content type.  This can be
+&lsquo;feature&rsquo;, &lsquo;trailer&rsquo; or whatever; select the
+required type from the drop-down list.
+</para>
+
+<para>
+The <guilabel>trim frames</guilabel> settings allow you to trim frames
+from the beginning and end of the content; any trimmed frames will not
+be included in the DCP.
+</para>
+
+</section>
+
+<section>
+<title>Video tab</title>
+
+<para>
+This tab contains settings related to the picture in your DCP, as shown in <xref linkend="fig-video-tab"/>.
+</para>
+
+<figure id="fig-video-tab"> 
+  <title>Video settings tab</title>
+  <mediaobject>
+    <imageobject> 
+      <imagedata fileref="screenshots/video-tab&scs;"/>
+    </imageobject> 
+  </mediaobject>
+</figure>
+
+<para>
+The first option on this tab is the format.  This will govern the
+shape that DCP-o-matic will make your image into.  Select the aspect
+ratio that your content should be presented in.  The &lsquo;4:3 within
+Flat&rsquo; and &lsquo;16:9 within Flat&rsquo; settings will put the
+image at the specified ratio within a Flat (1.85:1) frame, so that you
+can project the DCP using your projector's Flat preset.
+</para>
+
+<para>
+The remaining options can often be left alone, but may sometimes be
+useful.  The &lsquo;crop&rsquo; settings can be used to crop your
+content, which can be used to remove black borders from round the
+edges of DVD images, for example.  The specified number of pixels will
+be trimmed from each edge, and the content image in the right of the
+window will be updated to show the effect of the crop.
+</para>
+
+<para>
+The &lsquo;filters&rsquo; settings allow you to apply various video
+filters to the image.  These may be useful to try to improve
+poor-quality sources like DVDs.  We will discuss filtering later in the manual.
+<!-- XXX: link -->
+</para>
+
+<para>
+The &lsquo;scaler&rsquo; is the method that will be used to scale up
+your content to the required size for the DCP, if required.  We will
+discuss the options in more detail later; Bicubic is a fine choice in
+most situations.
+<!-- XXX: link -->
+</para>
+
+<para>
+The &lsquo;colour look-up table&rsquo; specifies the colour space that
+your input content will be expected to be in.  If in doubt, leave it
+set to &lsquo;sRGB&rsquo;.
+</para>
+
+<para>
+Finally, the &lsquo;JPEG2000 bandwidth&rsquo; setting changes how big the final
+image files used within the DCP will be.  Larger numbers will give
+better quality, but correspondingly larger DCPs.  The bandwidth can be
+between 50 and 250 megabits per second (MBps).
+</para>
+
+</section>
+
+<section>
+<title>Audio tab</title>
+
+<para>
+This tab contains settings related to the sound in your DCP, as shown in <xref linkend="fig-audio-tab"/>.
+</para>
+
+<figure id="fig-audio-tab"> 
+  <title>Audio settings tab</title>
+  <mediaobject>
+    <imageobject> 
+      <imagedata fileref="screenshots/audio-tab&scs;"/>
+    </imageobject> 
+  </mediaobject>
+</figure>
+
+
+<para>
+&lsquo;Audio Gain&rsquo; is used to alter the volume of the
+soundtrack.  The specified gain (in dB) will be applied to each sound
+channel before it is written to the DCP.
+</para>
+
+<para>
+If you use a sound processor that DCP-o-matic knows about, it can help
+you calculate changes in gain that you should apply.  Say, for
+example, that you make a test DCP and find that you have to run it at
+volume 5 instead of volume 7 to get a good sound level in the screen.
+If this is the case, click the <guilabel>Calculate...</guilabel>
+button next to the audio gain entry, and the dialogue box in <xref
+linkend="fig-calculate-audio-gain"/> will open.
+</para>
+
+<figure id="fig-calculate-audio-gain"> 
+  <title>Calculating audio gain</title>
+  <mediaobject>
+    <imageobject> 
+      <imagedata fileref="screenshots/calculate-audio-gain&scs;"/>
+    </imageobject> 
+  </mediaobject>
+</figure>
+
+<para>
+For our example, put 5 in the first box and 7 in the second and click
+<guilabel>OK</guilabel>.  DCP-o-matic will calculate the audio gain
+that it should apply to make this happen.  Then you can re-make the
+DCP (this will be reasonably fast, as the video data will already have
+been done) and it should play back at the correct volume with 7 on
+your sound-rack fader.
+</para>
+
+<para>
+Current versions of DCP-o-matic only know about the Dolby CP750.  If
+you use a different sound processor, and know the gain curve of its
+volume control, <ulink url="mailto:cth@carlh.net">get in
+touch</ulink>.
+</para>
+
+<para>
+&lsquo;Audio Delay&rsquo; is used to adjust the synchronisation
+between audio and video.  A positive delay will move the audio later
+with respect to the video, and a negative delay will move it earlier.
+</para>
+
+<para>
+By default the <guilabel>Use content&lsquo;s audio</guilabel> button
+will be selected.  This means that the DCP will use one of the
+soundtracks from your content file; you can select the soundtrack that
+you wish to use from the drop-down box.
+</para>
+
+<para>
+Note that if your content's audio is mono, DCP-o-matic will place it
+in the centre channel in the DCP.
+</para>
+
+<para>
+Alternatively, you can supply different sound files by clicking the
+<guilabel>Use external audio</guilabel> button and choosing a WAV file
+for any channels that you want to appear in the DCP.  These files can
+be any bit depth and sampling rate, and will be re-sampled and
+bit-depth converted if required.
+</para>
+
+</section>
+<section>
+<title>Subtitles tab</title>
+
+<para>
+This tab contains settings related to subtitles in your DCP, as shown in <xref linkend="fig-subtitles-tab"/>.
+</para>
+
+<figure id="fig-subtitles-tab"> 
+  <title>Subtitle settings tab</title>
+  <mediaobject>
+    <imageobject> 
+      <imagedata fileref="screenshots/subtitles-tab&scs;"/>
+    </imageobject> 
+  </mediaobject>
+</figure>
+
+<para>
+DCP-o-matic will extract subtitles from the content, if present, and
+they can be &lsquo;burnt into&rsquo; the DCP (that is, they are
+included in the image and not overlaid by the projector).  Note that
+DVD and Blu-Ray subtitles are stored as bitmaps, so it is not possible
+(automatically) to use non-burnt-in subtitles with these sources.
+Select the <guilabel>With Subtitles</guilabel> checkbox to enable
+subtitles.  The <guilabel>offset</guilabel> control moves the
+subtitles up and down the image, and the <guilabel>scale</guilabel>
+control changes their size.
+</para>
+
+<para>
+Future versions of DCP-o-matic will hopefully include the option to
+use text subtitles (as is the norm with most professionally-mastered
+DCPs).
+</para>
+
+</section>
+</section>
+
+<section>
+<title>Making the DCP</title>
+
+<para>
+Now that we have set everything up, choose <guilabel>Make
+DCP</guilabel> from the <guilabel>Jobs</guilabel> menu.  DCP-o-matic
+will encode your DCP.  This may take some time (many hours in some
+cases).  While the job is in progress, DCP-o-matic will update you on
+how it is getting on with the progress bar in the bottom of its window, as shown in <xref linkend="fig-making-dcp"/>.
+</para>
+
+<figure id="fig-making-dcp">
+  <title>Making the DCP</title>
+  <mediaobject>
+    <imageobject> 
+      <imagedata fileref="screenshots/making-dcp&scs;"/>
+    </imageobject> 
+  </mediaobject>
+</figure>
+
+<para>
+When it has finished, the DCP will end up on your disk inside the
+film's directory.  You can then copy this to a projector via a USB
+stick, hard-drive or network connection.
+</para>
+
+<para>
+Alternatively, if you have a projector or TMS that is accessible via
+SCP across your network, you can upload the content directly from
+DCP-o-matic.  See <xref linkend="sec-tms-upload"/>.
+</para>
+
+</section>
+</chapter>
+
+
+<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:lang="en">
+<title>Creating a still-image DCP</title>
+
+<para>
+DCP-o-matic can also be used to create DCPs of a still image, perhaps
+for an advertisement or an on-screen announcement.  This chapter shows you
+how to do it.
+</para>
+
+<para>
+As with video DCPs, the first step is to create a new
+&lsquo;Film&rsquo;; select <guilabel>New</guilabel> from the
+<guilabel>File</guilabel> menu and the new film dialogue will open as
+shown in <xref linkend="fig-still-new-film"/>.
+</para>
+
+<figure id="fig-still-new-film"> 
+  <title>Dialogue box for creating a new film</title> 
+  <mediaobject>
+    <imageobject> 
+      <imagedata fileref="screenshots/still-new-film&scs;"/>
+    </imageobject> 
+  </mediaobject>
+</figure>
+
+<para>
+Enter a name and click <guilabel>OK</guilabel>.  Then we set up the
+content; click the content selector as before, and this time we will
+choose an image file, as shown in <xref
+linkend="fig-still-select-content-file"/>.
+</para>
+
+<figure id="fig-still-select-content-file"> 
+  <title>Selecting a still content file</title> 
+  <mediaobject>
+    <imageobject> 
+      <imagedata fileref="screenshots/still-select-content-file&scs;"/>
+    </imageobject> 
+  </mediaobject>
+</figure>
+
+<para>
+Setting up for a still image DCP is somewhat simpler than for a video;
+the tabs are all the same, but many options are removed and a few are added.
+</para>
+
+<para>
+As with video, you can select a content type and the format (ratio)
+that your image should be presented in.  It will be scaled and padded
+to fit the selected ratio, but in such a way that the pixel aspect
+ratio is preserved.  In other words, the image will not be stretched,
+merely scaled; if you want to stretch your image, you will need to do
+so in a separate program before importing it into DCP-o-matic.  You
+can also crop your image, if you so choose, and then set a duration
+(in seconds) that the image should appear on screen.
+</para>
+
+<para>
+Still-image DCPs can include sound; this can be added from the
+<guilabel>Audio</guilabel> tab.  If your specified duration is shorter
+than the audio, the audio will be cut off at the duration; if it is
+longer, silence will be added after your audio.
+</para>
+
+<para>
+Finally, as with video, you can choose <guilabel>Make DCP</guilabel>
+from the <guilabel>Jobs</guilabel> menu to create your DCP.  This will
+be much quicker than creating a video DCP, as DCP-o-matic only needs
+to encode a single frame which it can then repeat.
+</para>
+
+</chapter>
+
+
+<chapter xml:id="ch-preferences" xmlns="http://docbook.org/ns/docbook" version="5.0" xml:lang="en">
+<title>Preferences</title>
+
+<para>
+DCP-o-matic provides a few preferences which can be used to modify its
+behaviour.  This chapter explains those options.
+</para>
+
+<section>
+<title>The preferences dialogue</title>
+
+<para>
+The preferences dialogue is opened by choosing
+<guilabel>Preferences...</guilabel> from the <guilabel>Edit</guilabel>
+menu.  The dialogue is shown in <xref linkend="fig-prefs"/>.
+</para>
+
+<figure id="fig-prefs"> 
+  <title>Preferences</title> 
+  <mediaobject>
+    <imageobject> 
+      <imagedata fileref="screenshots/prefs&scs;"/>
+    </imageobject> 
+  </mediaobject>
+</figure>
+
+<section>
+<title>TMS setup</title>
+
+<para>
+The first part of the dialogue gives some options for specifying
+details about your TMS.  If you do this, and your TMS accepts SSH
+connections, you can upload DCPs directly from DCP-o-matic to the TMS.
+This is discussed in <xref linkend="sec-tms-upload"/>.
+</para>
+
+<para>
+<guilabel>TMS IP address</guilabel> should be set to the IP address of
+your TMS, <guilabel>TMS target path</guilabel> to the place that DCPs
+should be uploaded to (which will be relative to the home directory of
+the SSH user).  Finally, the user name and password are the
+credentials required to log into the TMS via SSH.
+</para>
+</section>
+
+<section>
+<title>Threads</title>
+
+<para>
+When DCP-o-matic is encoding DCPs it can use multiple parallel threads
+to speed things up.  Set this value to the number of threads
+DCP-o-matic should use.  This would typically be set to the number of
+processors (or processor cores) in your machine.
+</para>
+
+</section>
+
+<section>
+<title>Default directory for new films</title>
+
+<para>
+This is the directory which DCP-o-matic will suggest initially as a place to put new films.
+</para>
+
+</section>
+
+<section>
+<title>A/B options</title>
+
+<para>
+These options are for DCP-o-matic's special mode of making A/B
+comparison DCPs for checking the performance of video filters.  Their
+use is described in <xref linkend="sec-ab"/>.
+</para>
+
+</section>
+
+<section>
+<title>Encoding servers</title>
+
+<para>
+If you have spare machines sitting around on your network not doing
+much, they can be pressed into service to speed up DCP encodes.  This
+is done by running a small server program on the machine, which will
+encode video sent to it by the &lsquo;master&rsquo; DCP-o-matic.  This
+option is described in more detail in <xref linkend="sec-servers"/>.
+Use these preferences to specify the encoding servers that should be
+used.
+</para>
+
+</section>
+
+</section>
+</chapter>
+
+<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:lang="en">
+<title>Advanced topics</title>
+
+<para>This chapter describes some parts of DCP-o-matic that are
+probably not essential, but which you might find useful in some
+circumstances.
+</para>
+
+<section>
+<title>Filtering</title>
+
+<para>
+DCP-o-matic offers a variety of filters that can be applied to your
+video content.  You can set up the filters by clicking the
+<guilabel>Edit</guilabel> button next to the filters entry in the
+setup area of the DCP-o-matic window; this opens the filters selector
+as shown in <xref linkend="fig-filters"/>.
+</para>
+
+<figure id="fig-filters"> 
+  <title>Filters selector</title> 
+  <mediaobject>
+    <imageobject> 
+      <imagedata fileref="screenshots/filters&scs;"/>
+    </imageobject> 
+  </mediaobject>
+</figure>
+
+<para>
+After changing the filters setup, you will need to regenerate the DCP
+to see the effect on the cinema screen.  The preview in DCP-o-matic
+will update itself whenever filters are changed, though of course this
+image is much smaller and of lower resolution than a projected image!
+</para>
+
+</section>
+
+<section>
+<title>Scaling</title>
+
+<para>
+If your source material is not of the DCI-specified size, or if it
+uses non-square pixels, DCP-o-matic will need to scale it.  The
+algorithm used to scale is set up by the <guilabel>Scaler</guilabel>
+entry in the film setup area.  We think &lsquo;Bicubic&rsquo; is the
+best all-round option, but tests are ongoing.
+</para>
+
+</section>
+
+<section xml:id="sec-tms-upload">
+<title>TMS upload</title>
+
+<para>
+If you have configured details of a TMS in the preferences dialogue
+(<xref linkend="ch-preferences"/>) you can upload a completed DCP
+straight to your TMS buy choosing <guilabel>Send DCP to TMS</guilabel>
+from the <guilabel>Jobs</guilabel> menu.
+</para>
+
+</section>
+
+
+<section xml:id="sec-ab">
+<title>A/B comparison</title>
+
+<para>
+When evaluating the effects of different filters or scalers on the
+image quality, A/B mode might be useful.  In this mode, DCP-o-matic
+will generate a DCP where the left half of the image uses some
+&lsquo;reference&rsquo; filtering and scaling, and the right half of
+the image uses a different set of filters and a different scaler.
+This DCP can then be played back on a projector and the image quality
+evaluated.
+</para>
+
+<para>
+To enable A/B mode, click the A/B checkbox in the setup area of the
+DCP-o-matic window.  When you generate your DCP, the left half of the
+screen will use the filters and scaler specified in the <xref
+linkend="ch-preferences">preferences</xref> dialogue, and the right
+half will use the filters and scaler specified in the film setup.
+</para>
+
+</section>
+
+<section xml:id="sec-servers">
+<title>Encoding servers</title>
+
+<para>
+One way to increase the speed of DCP encoding is to use more
+than one machine at the same time.  An instance of DCP-o-matic can
+offload some of the time-consuming JPEG2000 encoding to any number of
+other machines on a network.  To do this, one &lsquo;master&rsquo;
+machine runs DCP-o-matic, and the &lsquo;server&rsquo; machines run
+a small program called &lsquo;servomatic&rsquo;.
+</para>
+
+<section>
+<title>Running the servers</title>
+
+<para>
+There are two options for the encoding server;
+<code>servomatic_cli</code>, which runs on the command line, and
+<code>servomatic_gui</code>, which has a simple GUI.  The command line
+version is well-suited to headless servers, especially on Linux, and
+the GUI version works best on Windows where it will put an icon in the
+system tray.
+</para>
+
+<para>
+To run the command line version, simply enter:
+</para>
+
+<programlisting>
+servomatic_cli
+</programlisting>
+
+<para>
+at a command prompt.  If you are running the program on a machine with
+a multi-core processor, you can run multiple parallel encoding threads
+by doing something like:
+</para>
+
+<programlisting>
+servomatic_cli -t 4
+</programlisting>
+
+<para>
+to run 4 threads in parallel.
+</para>
+
+<para>
+To run the GUI version on windows, run the &lsquo;DCP-o-matic encode
+server&rsquo; from the start menu.  An icon will appear in the system
+tray; right-click it to open a menu from whence you can quit the
+server or open a window to show its status.
+</para>
+
+</section>
+<section>
+<title>Setting up DCP-o-matic</title>
+
+<para>
+Once your servers are running, you need to tell your master
+DCP-o-matic instance about them.  Start DCP-o-matic and open the
+<guilabel>Preferences</guilabel> dialog from the
+<guilabel>Edit</guilabel> menu.  At the bottom of this dialog is a
+section where you can add, edit and remove encoding servers.  For each
+encoding server you need only specify its IP address and the number of
+threads that it is running, so that DCP-o-matic knows how many
+parallel encode jobs to send to the server.
+</para>
+
+<para>
+Once this is done, any encodes that you start will split the workload
+up between the master machine and the servers.
+</para>
+
+</section>
+<section>
+<title>Some notes about encode servers</title>
+
+<para>
+DCP-o-matic does not mind if servers come and go; if a server
+disappears, DCP-o-matic will stop sending work to it, and will check
+it every minute or so in case it has come back online.
+</para>
+
+<para>
+You will probably find that using a 1Gb/s or faster network will
+provide a significant speed-up compared to a 100Mb/s network.
+</para>
+
+<para>
+Making changes to the server configuration in the master DCP-o-matic
+will have no effect while an encode is running; the changes will only
+be noticed when a new encode is started.
+</para>
+
+</section>
+</section>
+
+</chapter>
+
+
+</book>
diff --git a/icons/128x128/dcpomatic.png b/icons/128x128/dcpomatic.png
new file mode 100644 (file)
index 0000000..9936b39
Binary files /dev/null and b/icons/128x128/dcpomatic.png differ
diff --git a/icons/16x16/dcpomatic.png b/icons/16x16/dcpomatic.png
new file mode 100644 (file)
index 0000000..3c5a10f
Binary files /dev/null and b/icons/16x16/dcpomatic.png differ
diff --git a/icons/22x22/dcpomatic.png b/icons/22x22/dcpomatic.png
new file mode 100644 (file)
index 0000000..dddb862
Binary files /dev/null and b/icons/22x22/dcpomatic.png differ
diff --git a/icons/32x32/dcpomatic.png b/icons/32x32/dcpomatic.png
new file mode 100644 (file)
index 0000000..8cecf08
Binary files /dev/null and b/icons/32x32/dcpomatic.png differ
diff --git a/icons/48x48/dcpomatic.png b/icons/48x48/dcpomatic.png
new file mode 100644 (file)
index 0000000..07bf2d1
Binary files /dev/null and b/icons/48x48/dcpomatic.png differ
diff --git a/icons/64x64/dcpomatic.png b/icons/64x64/dcpomatic.png
new file mode 100644 (file)
index 0000000..35564a8
Binary files /dev/null and b/icons/64x64/dcpomatic.png differ
diff --git a/run/dcpomatic b/run/dcpomatic
new file mode 100755 (executable)
index 0000000..7ea0877
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+export LD_LIBRARY_PATH=build/src/lib:build/src/wx:build/src/asdcplib/src:$LD_LIBRARY_PATH
+if [ "$1" == "--debug" ]; then
+    shift
+    gdb --args build/src/tools/dcpomatic $*
+elif [ "$1" == "--valgrind" ]; then
+    shift
+    valgrind --tool="memcheck" build/src/tools/dcpomatic $*
+elif [ "$1" == "--i18n" ]; then
+    shift
+    LANGUAGE=fr_FR.UTF8 LANG=fr_FR.UTF8 build/src/tools/dcpomatic "$*"
+else
+    build/src/tools/dcpomatic $*
+fi
diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc
new file mode 100644 (file)
index 0000000..ee9f997
--- /dev/null
@@ -0,0 +1,578 @@
+/*
+    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <iostream>
+#include <boost/filesystem.hpp>
+#ifdef __WXMSW__
+#include <shellapi.h>
+#endif
+#include <wx/aboutdlg.h>
+#include <wx/stdpaths.h>
+#include <wx/cmdline.h>
+#include "wx/film_viewer.h"
+#include "wx/film_editor.h"
+#include "wx/job_manager_view.h"
+#include "wx/config_dialog.h"
+#include "wx/job_wrapper.h"
+#include "wx/wx_util.h"
+#include "wx/new_film_dialog.h"
+#include "wx/properties_dialog.h"
+#include "wx/wx_ui_signaller.h"
+#include "lib/film.h"
+#include "lib/format.h"
+#include "lib/config.h"
+#include "lib/filter.h"
+#include "lib/util.h"
+#include "lib/scaler.h"
+#include "lib/exceptions.h"
+#include "lib/version.h"
+#include "lib/ui_signaller.h"
+#include "lib/log.h"
+
+using std::cout;
+using std::string;
+using std::wstring;
+using std::stringstream;
+using std::map;
+using std::make_pair;
+using std::exception;
+using boost::shared_ptr;
+
+static FilmEditor* film_editor = 0;
+static FilmViewer* film_viewer = 0;
+static shared_ptr<Film> film;
+static std::string log_level;
+static std::string film_to_load;
+static std::string film_to_create;
+static wxMenu* jobs_menu = 0;
+static wxLocale* locale = 0;
+
+static void set_menu_sensitivity ();
+
+class FilmChangedDialog
+{
+public:
+       FilmChangedDialog ()
+       {
+               _dialog = new wxMessageDialog (
+                       0,
+                       wxString::Format (_("Save changes to film \"%s\" before closing?"), std_to_wx (film->name ()).data()),
+                       _("Film changed"),
+                       wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION
+                       );
+       }
+
+       ~FilmChangedDialog ()
+       {
+               _dialog->Destroy ();
+       }
+
+       int run ()
+       {
+               return _dialog->ShowModal ();
+       }
+
+private:       
+       wxMessageDialog* _dialog;
+};
+
+
+void
+maybe_save_then_delete_film ()
+{
+       if (!film) {
+               return;
+       }
+                       
+       if (film->dirty ()) {
+               FilmChangedDialog d;
+               switch (d.run ()) {
+               case wxID_NO:
+                       break;
+               case wxID_YES:
+                       film->write_metadata ();
+                       break;
+               }
+       }
+       
+       film.reset ();
+}
+
+enum Sensitivity {
+       ALWAYS,
+       NEEDS_FILM
+};
+
+map<wxMenuItem*, Sensitivity> menu_items;
+       
+void
+add_item (wxMenu* menu, wxString text, int id, Sensitivity sens)
+{
+       wxMenuItem* item = menu->Append (id, text);
+       menu_items.insert (make_pair (item, sens));
+}
+
+void
+set_menu_sensitivity ()
+{
+       for (map<wxMenuItem*, Sensitivity>::iterator i = menu_items.begin(); i != menu_items.end(); ++i) {
+               if (i->second == NEEDS_FILM) {
+                       i->first->Enable (film != 0);
+               } else {
+                       i->first->Enable (true);
+               }
+       }
+}
+
+enum {
+       ID_file_new = 1,
+       ID_file_open,
+       ID_file_save,
+       ID_file_properties,
+       ID_file_quit,
+       ID_edit_preferences,
+       ID_jobs_make_dcp,
+       ID_jobs_send_dcp_to_tms,
+       ID_jobs_show_dcp,
+       ID_jobs_analyse_audio,
+       ID_help_about
+};
+
+void
+setup_menu (wxMenuBar* m)
+{
+       wxMenu* file = new wxMenu;
+       add_item (file, _("New..."), ID_file_new, ALWAYS);
+       add_item (file, _("&Open..."), ID_file_open, ALWAYS);
+       file->AppendSeparator ();
+       add_item (file, _("&Save"), ID_file_save, NEEDS_FILM);
+       file->AppendSeparator ();
+       add_item (file, _("&Properties..."), ID_file_properties, NEEDS_FILM);
+       file->AppendSeparator ();
+       add_item (file, _("&Quit"), ID_file_quit, ALWAYS);
+
+       wxMenu* edit = new wxMenu;
+       add_item (edit, _("&Preferences..."), ID_edit_preferences, ALWAYS);
+
+       jobs_menu = new wxMenu;
+       add_item (jobs_menu, _("&Make DCP"), ID_jobs_make_dcp, NEEDS_FILM);
+       add_item (jobs_menu, _("&Send DCP to TMS"), ID_jobs_send_dcp_to_tms, NEEDS_FILM);
+       add_item (jobs_menu, _("S&how DCP"), ID_jobs_show_dcp, NEEDS_FILM);
+       jobs_menu->AppendSeparator ();
+       add_item (jobs_menu, _("&Analyse audio"), ID_jobs_analyse_audio, NEEDS_FILM);
+
+       wxMenu* help = new wxMenu;
+       add_item (help, _("About"), ID_help_about, ALWAYS);
+
+       m->Append (file, _("&File"));
+       m->Append (edit, _("&Edit"));
+       m->Append (jobs_menu, _("&Jobs"));
+       m->Append (help, _("&Help"));
+}
+
+bool
+window_closed (wxCommandEvent &)
+{
+       maybe_save_then_delete_film ();
+       return false;
+}
+
+class Frame : public wxFrame
+{
+public:
+       Frame (wxString const & title)
+               : wxFrame (NULL, -1, title)
+       {
+               wxMenuBar* bar = new wxMenuBar;
+               setup_menu (bar);
+               SetMenuBar (bar);
+
+               Connect (ID_file_new, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::file_new));
+               Connect (ID_file_open, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::file_open));
+               Connect (ID_file_save, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::file_save));
+               Connect (ID_file_properties, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::file_properties));
+               Connect (ID_file_quit, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::file_quit));
+               Connect (ID_edit_preferences, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::edit_preferences));
+               Connect (ID_jobs_make_dcp, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_make_dcp));
+               Connect (ID_jobs_send_dcp_to_tms, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_send_dcp_to_tms));
+               Connect (ID_jobs_show_dcp, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_show_dcp));
+               Connect (ID_jobs_analyse_audio, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_analyse_audio));
+               Connect (ID_help_about, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::help_about));
+
+               Connect (wxID_ANY, wxEVT_MENU_OPEN, wxMenuEventHandler (Frame::menu_opened));
+
+               wxPanel* panel = new wxPanel (this);
+               wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
+               s->Add (panel, 1, wxEXPAND);
+               SetSizer (s);
+
+               film_editor = new FilmEditor (film, panel);
+               film_viewer = new FilmViewer (film, panel);
+               JobManagerView* job_manager_view = new JobManagerView (panel);
+
+               _top_sizer = new wxBoxSizer (wxHORIZONTAL);
+               _top_sizer->Add (film_editor, 0, wxALL, 6);
+               _top_sizer->Add (film_viewer, 1, wxEXPAND | wxALL, 6);
+
+               wxBoxSizer* main_sizer = new wxBoxSizer (wxVERTICAL);
+               main_sizer->Add (_top_sizer, 2, wxEXPAND | wxALL, 6);
+               main_sizer->Add (job_manager_view, 1, wxEXPAND | wxALL, 6);
+               panel->SetSizer (main_sizer);
+
+               set_menu_sensitivity ();
+
+               film_editor->FileChanged.connect (bind (&Frame::file_changed, this, _1));
+               if (film) {
+                       file_changed (film->directory ());
+               } else {
+                       file_changed ("");
+               }
+
+               set_film ();
+
+               film_editor->Connect (wxID_ANY, wxEVT_SIZE, wxSizeEventHandler (Frame::film_editor_sized), 0, this);
+       }
+
+private:
+
+       void film_editor_sized (wxSizeEvent &)
+       {
+               static bool in_layout = false;
+               if (!in_layout) {
+                       in_layout = true;
+                       _top_sizer->Layout ();
+                       in_layout = false;
+               }
+       }
+
+       void menu_opened (wxMenuEvent& ev)
+       {
+               if (ev.GetMenu() != jobs_menu) {
+                       return;
+               }
+
+               bool const have_dcp = film && film->have_dcp();
+               jobs_menu->Enable (ID_jobs_send_dcp_to_tms, have_dcp);
+               jobs_menu->Enable (ID_jobs_show_dcp, have_dcp);
+       }
+
+       void set_film ()
+       {
+               film_viewer->set_film (film);
+               film_editor->set_film (film);
+               set_menu_sensitivity ();
+       }
+
+       void file_changed (string f)
+       {
+               stringstream s;
+               s << wx_to_std (_("DCP-o-matic"));
+               if (!f.empty ()) {
+                       s << " - " << f;
+               }
+               
+               SetTitle (std_to_wx (s.str()));
+       }
+       
+       void file_new (wxCommandEvent &)
+       {
+               NewFilmDialog* d = new NewFilmDialog (this);
+               int const r = d->ShowModal ();
+               
+               if (r == wxID_OK) {
+
+                       if (boost::filesystem::exists (d->get_path())) {
+                               error_dialog (this, std_to_wx (String::compose (wx_to_std (_("The directory %1 already exists.")), d->get_path().c_str())));
+                               return;
+                       }
+                       
+                       maybe_save_then_delete_film ();
+                       film.reset (new Film (d->get_path (), false));
+                       film->log()->set_level (log_level);
+                       film->set_name (boost::filesystem::path (d->get_path()).filename().generic_string());
+                       set_film ();
+               }
+               
+               d->Destroy ();
+       }
+
+       void file_open (wxCommandEvent &)
+       {
+               wxDirDialog* c = new wxDirDialog (this, _("Select film to open"), wxStandardPaths::Get().GetDocumentsDir(), wxDEFAULT_DIALOG_STYLE | wxDD_DIR_MUST_EXIST);
+               int r;
+               while (1) {
+                       r = c->ShowModal ();
+                       if (r == wxID_OK && c->GetPath() == wxStandardPaths::Get().GetDocumentsDir()) {
+                               error_dialog (this, _("You did not select a folder.  Make sure that you select a folder before clicking Open."));
+                       } else {
+                               break;
+                       }
+               }
+                       
+               if (r == wxID_OK) {
+                       maybe_save_then_delete_film ();
+                       try {
+                               film.reset (new Film (wx_to_std (c->GetPath ())));
+                               film->log()->set_level (log_level);
+                               set_film ();
+                       } catch (std::exception& e) {
+                               wxString p = c->GetPath ();
+                               wxCharBuffer b = p.ToUTF8 ();
+                               error_dialog (this, wxString::Format (_("Could not open film at %s (%s)"), p.data(), std_to_wx (e.what()).data()));
+                       }
+               }
+
+               c->Destroy ();
+       }
+
+       void file_save (wxCommandEvent &)
+       {
+               film->write_metadata ();
+       }
+
+       void file_properties (wxCommandEvent &)
+       {
+               PropertiesDialog* d = new PropertiesDialog (this, film);
+               d->ShowModal ();
+               d->Destroy ();
+       }
+       
+       void file_quit (wxCommandEvent &)
+       {
+               maybe_save_then_delete_film ();
+               Close (true);
+       }
+
+       void edit_preferences (wxCommandEvent &)
+       {
+               ConfigDialog* d = new ConfigDialog (this);
+               d->ShowModal ();
+               d->Destroy ();
+               Config::instance()->write ();
+       }
+
+       void jobs_make_dcp (wxCommandEvent &)
+       {
+               JobWrapper::make_dcp (this, film);
+       }
+       
+       void jobs_send_dcp_to_tms (wxCommandEvent &)
+       {
+               film->send_dcp_to_tms ();
+       }
+
+       void jobs_show_dcp (wxCommandEvent &)
+       {
+#ifdef __WXMSW__
+               string d = film->directory();
+               wstring w;
+               w.assign (d.begin(), d.end());
+               ShellExecute (0, L"open", w.c_str(), 0, 0, SW_SHOWDEFAULT);
+#else
+               int r = system ("which nautilus");
+               if (WEXITSTATUS (r) == 0) {
+                       system (string ("nautilus " + film->directory()).c_str ());
+               } else {
+                       int r = system ("which konqueror");
+                       if (WEXITSTATUS (r) == 0) {
+                               system (string ("konqueror " + film->directory()).c_str ());
+                       }
+               }
+#endif         
+       }
+
+       void jobs_analyse_audio (wxCommandEvent &)
+       {
+               film->analyse_audio ();
+       }
+       
+       void help_about (wxCommandEvent &)
+       {
+               wxAboutDialogInfo info;
+               info.SetName (_("DCP-o-matic"));
+               if (strcmp (dcpomatic_git_commit, "release") == 0) {
+                       info.SetVersion (std_to_wx (String::compose ("version %1", dcpomatic_version)));
+               } else {
+                       info.SetVersion (std_to_wx (String::compose ("version %1 git %2", dcpomatic_version, dcpomatic_git_commit)));
+               }
+               info.SetDescription (_("Free, open-source DCP generation from almost anything."));
+               info.SetCopyright (_("(C) 2012-2013 Carl Hetherington, Terrence Meiczinger, Paul Davis, Ole Laursen"));
+
+               wxArrayString authors;
+               authors.Add (wxT ("Carl Hetherington"));
+               authors.Add (wxT ("Terrence Meiczinger"));
+               authors.Add (wxT ("Paul Davis"));
+               authors.Add (wxT ("Ole Laursen"));
+               info.SetDevelopers (authors);
+
+               wxArrayString translators;
+               translators.Add (wxT ("Olivier Perriere"));
+               translators.Add (wxT ("Lilian Lefranc"));
+               translators.Add (wxT ("Thierry Journet"));
+               translators.Add (wxT ("Massimiliano Broggi"));
+               translators.Add (wxT ("Manuel AC"));
+               translators.Add (wxT ("Adam Klotblixt"));
+               info.SetTranslators (translators);
+               
+               info.SetWebSite (wxT ("http://carlh.net/software/dcpomatic"));
+               wxAboutBox (info);
+       }
+
+       wxSizer* _top_sizer;
+};
+
+#if wxMINOR_VERSION == 9
+static const wxCmdLineEntryDesc command_line_description[] = {
+       { wxCMD_LINE_OPTION, "l", "log", "set log level (silent, verbose or timing)", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
+       { wxCMD_LINE_SWITCH, "n", "new", "create new film", wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
+        { wxCMD_LINE_PARAM, 0, 0, "film to load or create", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL },
+       { wxCMD_LINE_NONE, "", "", "", wxCmdLineParamType (0), 0 }
+};
+#else
+static const wxCmdLineEntryDesc command_line_description[] = {
+       { wxCMD_LINE_OPTION, wxT("l"), wxT("log"), wxT("set log level (silent, verbose or timing)"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
+       { wxCMD_LINE_SWITCH, wxT("n"), wxT("new"), wxT("create new film"), wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
+        { wxCMD_LINE_PARAM, 0, 0, wxT("film to load or create"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL },
+       { wxCMD_LINE_NONE, wxT(""), wxT(""), wxT(""), wxCmdLineParamType (0), 0 }
+};
+#endif
+
+void
+setup_i18n ()
+{
+       int language = wxLANGUAGE_DEFAULT;
+
+       if (Config::instance()->language()) {
+               wxLanguageInfo const * li = wxLocale::FindLanguageInfo (std_to_wx (Config::instance()->language().get()));
+               if (li) {
+                       language = li->Language;
+               }
+       }
+       if (wxLocale::IsAvailable (language)) {
+               locale = new wxLocale (language, wxLOCALE_LOAD_DEFAULT);
+
+#ifdef DCPOMATIC_WINDOWS
+               locale->AddCatalogLookupPathPrefix (std_to_wx (mo_path().string()));
+#endif         
+
+               locale->AddCatalog (wxT ("libdcpomatic-wx"));
+               locale->AddCatalog (wxT ("dcpomatic"));
+               
+               if (!locale->IsOk()) {
+                       delete locale;
+                       locale = new wxLocale (wxLANGUAGE_ENGLISH);
+                       language = wxLANGUAGE_ENGLISH;
+               }
+       }
+
+       if (locale) {
+               dcpomatic_setup_i18n (wx_to_std (locale->GetCanonicalName ()));
+       }
+}
+
+class App : public wxApp
+{
+       bool OnInit ()
+       {
+               if (!wxApp::OnInit()) {
+                       return false;
+               }
+               
+#ifdef DCPOMATIC_POSIX         
+               unsetenv ("UBUNTU_MENUPROXY");
+#endif         
+
+               wxInitAllImageHandlers ();
+
+               /* Enable i18n; this will create a Config object
+                  to look for a force-configured language.  This Config
+                  object will be wrong, however, because dcpomatic_setup
+                  hasn't yet been called and there aren't any scalers, filters etc.
+                  set up yet.
+               */
+               setup_i18n ();
+
+               /* Set things up, including scalers / filters etc.
+                  which will now be internationalised correctly.
+               */
+               dcpomatic_setup ();
+
+               /* Force the configuration to be re-loaded correctly next
+                  time it is needed.
+               */
+               Config::drop ();
+
+               if (!film_to_load.empty() && boost::filesystem::is_directory (film_to_load)) {
+                       try {
+                               film.reset (new Film (film_to_load));
+                               film->log()->set_level (log_level);
+                       } catch (exception& e) {
+                               error_dialog (0, std_to_wx (String::compose (wx_to_std (_("Could not load film %1 (%2)")), film_to_load, e.what())));
+                       }
+               }
+
+               if (!film_to_create.empty ()) {
+                       film.reset (new Film (film_to_create, false));
+                       film->log()->set_level (log_level);
+                       film->set_name (boost::filesystem::path (film_to_create).filename().generic_string ());
+               }
+
+               Frame* f = new Frame (_("DCP-o-matic"));
+               SetTopWindow (f);
+               f->Maximize ();
+               f->Show ();
+
+               ui_signaller = new wxUISignaller (this);
+               this->Connect (-1, wxEVT_IDLE, wxIdleEventHandler (App::idle));
+
+               return true;
+       }
+
+       void OnInitCmdLine (wxCmdLineParser& parser)
+       {
+               parser.SetDesc (command_line_description);
+               parser.SetSwitchChars (wxT ("-"));
+       }
+
+       bool OnCmdLineParsed (wxCmdLineParser& parser)
+       {
+               if (parser.GetParamCount() > 0) {
+                       if (parser.Found (wxT ("new"))) {
+                               film_to_create = wx_to_std (parser.GetParam (0));
+                       } else {
+                               film_to_load = wx_to_std (parser.GetParam(0));
+                       }
+               }
+
+               wxString log;
+               if (parser.Found (wxT ("log"), &log)) {
+                       log_level = wx_to_std (log);
+               }
+
+               return true;
+       }
+
+       void idle (wxIdleEvent &)
+       {
+               ui_signaller->ui_idle ();
+       }
+};
+
+IMPLEMENT_APP (App)
diff --git a/windows/dcpomatic.bmp b/windows/dcpomatic.bmp
new file mode 100644 (file)
index 0000000..0a196f7
Binary files /dev/null and b/windows/dcpomatic.bmp differ
diff --git a/windows/dcpomatic.ico b/windows/dcpomatic.ico
new file mode 100644 (file)
index 0000000..225008c
Binary files /dev/null and b/windows/dcpomatic.ico differ
diff --git a/windows/dcpomatic.rc b/windows/dcpomatic.rc
new file mode 100644 (file)
index 0000000..3963873
--- /dev/null
@@ -0,0 +1,3 @@
+id ICON "dcpomatic.ico"
+taskbar_icon ICON "dcpomatic_taskbar.ico"
+#include "wx-2.9/wx/msw/wx.rc"
diff --git a/windows/dcpomatic_taskbar.ico b/windows/dcpomatic_taskbar.ico
new file mode 100644 (file)
index 0000000..f4489fa
Binary files /dev/null and b/windows/dcpomatic_taskbar.ico differ