Merge master.
authorCarl Hetherington <cth@carlh.net>
Sat, 25 Oct 2014 13:47:43 +0000 (14:47 +0100)
committerCarl Hetherington <cth@carlh.net>
Sat, 25 Oct 2014 13:47:43 +0000 (14:47 +0100)
36 files changed:
1  2 
ChangeLog
debian/changelog
src/lib/colour_conversion.cc
src/lib/dcp_video.cc
src/lib/job.cc
src/lib/player_video.cc
src/lib/player_video.h
src/lib/playlist.cc
src/lib/po/de_DE.po
src/lib/po/es_ES.po
src/lib/po/fr_FR.po
src/lib/po/it_IT.po
src/lib/po/nl_NL.po
src/lib/po/sv_SE.po
src/lib/video_content.cc
src/lib/video_content.h
src/tools/dcpomatic.cc
src/tools/po/de_DE.po
src/tools/po/es_ES.po
src/tools/po/fr_FR.po
src/tools/po/it_IT.po
src/tools/po/nl_NL.po
src/tools/po/sv_SE.po
src/wx/about_dialog.cc
src/wx/film_editor.cc
src/wx/po/de_DE.po
src/wx/po/es_ES.po
src/wx/po/fr_FR.po
src/wx/po/it_IT.po
src/wx/po/nl_NL.po
src/wx/po/sv_SE.po
src/wx/timeline.cc
src/wx/timeline_dialog.cc
src/wx/timeline_dialog.h
src/wx/video_panel.cc
src/wx/video_panel.h

diff --cc ChangeLog
index 053c1f106cf2db45745c0af86978eeeb4f074712,1978d85f73dbbe7b6655119a64c610f808aaac9d..07c8218f763c61acf8dc53a64619f76d56f2527c
+++ b/ChangeLog
@@@ -1,7 -1,30 +1,34 @@@
+ 2014-10-24  Carl Hetherington  <cth@carlh.net>
+       * Add a pause button for jobs.
+       * Experimental support for bypassing colourspace conversion (#266).
+       * Version 1.76.6 released.
+ 2014-10-23  Carl Hetherington  <cth@carlh.net>
+       * Version 1.76.5 released.
+ 2014-10-23  Carl Hetherington  <cth@carlh.net>
+       * Version 1.76.4 released.
+ 2014-10-23  Carl Hetherington  <cth@carlh.net>
+       * Rename 'Add folder' to 'Add image sequence'
+       and add some tooltips.
+       * Move the "keep video in sequence" button into
+       the timeline dialogue.
+       * Fix mix-placement of content when using the "Down"
+       button to move it.
 +2014-10-22  Carl Hetherington  <cth@carlh.net>
 +
 +      * Version 2.0.15 released.
 +
  2014-10-22  Carl Hetherington  <cth@carlh.net>
  
        * Version 1.76.3 released.
index 5702a6dfd4ad3381feacb2aa813967c6f5ab271f,6f3d19700feaabba84e45680287888d6faa1f6f2..9087bd1051a832f11a1182d21c1fc22c8ea2229b
@@@ -195,8 -195,10 +195,15 @@@ dcpomatic (2.0.15-1) UNRELEASED; urgenc
    * New upstream release.
    * New upstream release.
    * New upstream release.
++<<<<<<< HEAD
 +
 + -- Carl Hetherington <carl@d1stkfactory>  Wed, 22 Oct 2014 14:24:53 +0100
++=======
+   * New upstream release.
+   * New upstream release.
+  -- Carl Hetherington <carl@d1stkfactory>  Fri, 24 Oct 2014 01:19:26 +0100
++>>>>>>> origin/master
  
  dcpomatic (0.87-1) UNRELEASED; urgency=low
  
Simple merge
index f6c671fd14774b655acb67708b75084c6a49eaf8,0000000000000000000000000000000000000000..cacba190f87603dfa5d12a1a27c953229af959a5
mode 100644,000000..100644
--- /dev/null
@@@ -1,332 -1,0 +1,339 @@@
-       shared_ptr<dcp::GammaLUT> in_lut = dcp::GammaLUT::cache.get (
-               12, _frame->colour_conversion().input_gamma, _frame->colour_conversion().input_gamma_linearised
-               );
-       
-       /* XXX: libdcp should probably use boost */
-       
-       double matrix[3][3];
-       for (int i = 0; i < 3; ++i) {
-               for (int j = 0; j < 3; ++j) {
-                       matrix[i][j] = _frame->colour_conversion().matrix (i, j);
 +/*
 +    Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
 +    Taken from code Copyright (C) 2010-2011 Terrence Meiczinger
 +
 +    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.
 +
 +*/
 +
 +/** @file  src/dcp_video_frame.cc
 + *  @brief A single frame of video destined for a DCP.
 + *
 + *  Given an Image and some settings, this class knows how to encode
 + *  the image to J2K either on the local host or on a remote server.
 + *
 + *  Objects of this class are used for the queue that we keep
 + *  of images that require encoding.
 + */
 +
 +#include <stdint.h>
 +#include <cstring>
 +#include <cstdlib>
 +#include <stdexcept>
 +#include <cstdio>
 +#include <iomanip>
 +#include <iostream>
 +#include <fstream>
 +#include <unistd.h>
 +#include <errno.h>
 +#include <boost/array.hpp>
 +#include <boost/asio.hpp>
 +#include <boost/filesystem.hpp>
 +#include <boost/lexical_cast.hpp>
 +#include <dcp/gamma_lut.h>
 +#include <dcp/xyz_frame.h>
 +#include <dcp/rgb_xyz.h>
 +#include <dcp/colour_matrix.h>
 +#include <dcp/raw_convert.h>
 +#include <libcxml/cxml.h>
 +#include "film.h"
 +#include "dcp_video.h"
 +#include "config.h"
 +#include "exceptions.h"
 +#include "server.h"
 +#include "util.h"
 +#include "scaler.h"
 +#include "image.h"
 +#include "log.h"
 +#include "cross.h"
 +#include "player_video.h"
 +#include "encoded_data.h"
 +
 +#define LOG_GENERAL(...) _log->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL);
 +
 +#include "i18n.h"
 +
 +using std::string;
 +using std::cout;
 +using boost::shared_ptr;
 +using boost::lexical_cast;
 +using dcp::Size;
 +using dcp::raw_convert;
 +
 +#define DCI_COEFFICENT (48.0 / 52.37)
 +
 +/** Construct a DCP video frame.
 + *  @param frame Input frame.
 + *  @param index Index of the frame within the DCP.
 + *  @param bw J2K bandwidth to use (see Config::j2k_bandwidth ())
 + *  @param l Log to write to.
 + */
 +DCPVideo::DCPVideo (
 +      shared_ptr<const PlayerVideo> frame, int index, int dcp_fps, int bw, Resolution r, bool b, shared_ptr<Log> l
 +      )
 +      : _frame (frame)
 +      , _index (index)
 +      , _frames_per_second (dcp_fps)
 +      , _j2k_bandwidth (bw)
 +      , _resolution (r)
 +      , _burn_subtitles (b)
 +      , _log (l)
 +{
 +      
 +}
 +
 +DCPVideo::DCPVideo (shared_ptr<const PlayerVideo> frame, shared_ptr<const cxml::Node> node, shared_ptr<Log> log)
 +      : _frame (frame)
 +      , _log (log)
 +{
 +      _index = node->number_child<int> ("Index");
 +      _frames_per_second = node->number_child<int> ("FramesPerSecond");
 +      _j2k_bandwidth = node->number_child<int> ("J2KBandwidth");
 +      _resolution = Resolution (node->optional_number_child<int>("Resolution").get_value_or (RESOLUTION_2K));
 +      _burn_subtitles = node->bool_child ("BurnSubtitles");
 +}
 +
 +/** J2K-encode this frame on the local host.
 + *  @return Encoded data.
 + */
 +shared_ptr<EncodedData>
 +DCPVideo::encode_locally ()
 +{
-       shared_ptr<dcp::XYZFrame> xyz = dcp::rgb_to_xyz (
-               _frame->image (AV_PIX_FMT_RGB48LE, _burn_subtitles),
-               in_lut,
-               dcp::GammaLUT::cache.get (16, 1 / _frame->colour_conversion().output_gamma, false),
-               matrix
-               );
++      shared_ptr<dcp::XYZFrame> xyz;
++
++      if (_frame->colour_conversion()) {
++              ColourConversion conversion = _frame->colour_conversion().get ();
++              shared_ptr<dcp::GammaLUT> in_lut = dcp::GammaLUT::cache.get (
++                      12, conversion.input_gamma, conversion.input_gamma_linearised
++                      );
++              
++              /* XXX: dcp should probably use boost */
++              
++              double matrix[3][3];
++              for (int i = 0; i < 3; ++i) {
++                      for (int j = 0; j < 3; ++j) {
++                              matrix[i][j] = conversion.matrix (i, j);
++                      }
 +              }
++              
++              xyz = dcp::rgb_to_xyz (
++                      _frame->image (AV_PIX_FMT_RGB48LE, _burn_subtitles),
++                      in_lut,
++                      dcp::GammaLUT::cache.get (16, 1 / conversion.output_gamma, false),
++                      matrix
++                      );
++      } else {
++              xyz = dcp::xyz_to_xyz (_frame->image (AV_PIX_FMT_RGB48LE, _burn_subtitles));
 +      }
 +
 +      /* Set the max image and component sizes based on frame_rate */
 +      int max_cs_len = ((float) _j2k_bandwidth) / 8 / _frames_per_second;
 +      if (_frame->eyes() == EYES_LEFT || _frame->eyes() == EYES_RIGHT) {
 +              /* In 3D we have only half the normal bandwidth per eye */
 +              max_cs_len /= 2;
 +      }
 +      int const max_comp_size = max_cs_len / 1.25;
 +
 +      /* get a J2K compressor handle */
 +      opj_cinfo_t* cinfo = opj_create_compress (CODEC_J2K);
 +      if (cinfo == 0) {
 +              throw EncodeError (N_("could not create JPEG2000 encoder"));
 +      }
 +
 +      /* Set encoding parameters to default values */
 +      opj_cparameters_t parameters;
 +      opj_set_default_encoder_parameters (&parameters);
 +
 +      /* Set default cinema parameters */
 +      parameters.tile_size_on = false;
 +      parameters.cp_tdx = 1;
 +      parameters.cp_tdy = 1;
 +      
 +      /* Tile part */
 +      parameters.tp_flag = 'C';
 +      parameters.tp_on = 1;
 +      
 +      /* Tile and Image shall be at (0,0) */
 +      parameters.cp_tx0 = 0;
 +      parameters.cp_ty0 = 0;
 +      parameters.image_offset_x0 = 0;
 +      parameters.image_offset_y0 = 0;
 +
 +      /* Codeblock size = 32x32 */
 +      parameters.cblockw_init = 32;
 +      parameters.cblockh_init = 32;
 +      parameters.csty |= 0x01;
 +      
 +      /* The progression order shall be CPRL */
 +      parameters.prog_order = CPRL;
 +      
 +      /* No ROI */
 +      parameters.roi_compno = -1;
 +      
 +      parameters.subsampling_dx = 1;
 +      parameters.subsampling_dy = 1;
 +      
 +      /* 9-7 transform */
 +      parameters.irreversible = 1;
 +      
 +      parameters.tcp_rates[0] = 0;
 +      parameters.tcp_numlayers++;
 +      parameters.cp_disto_alloc = 1;
 +      parameters.cp_rsiz = _resolution == RESOLUTION_2K ? CINEMA2K : CINEMA4K;
 +      if (_resolution == RESOLUTION_4K) {
 +              parameters.numpocs = 2;
 +              parameters.POC[0].tile = 1;
 +              parameters.POC[0].resno0 = 0; 
 +              parameters.POC[0].compno0 = 0;
 +              parameters.POC[0].layno1 = 1;
 +              parameters.POC[0].resno1 = parameters.numresolution - 1;
 +              parameters.POC[0].compno1 = 3;
 +              parameters.POC[0].prg1 = CPRL;
 +              parameters.POC[1].tile = 1;
 +              parameters.POC[1].resno0 = parameters.numresolution - 1; 
 +              parameters.POC[1].compno0 = 0;
 +              parameters.POC[1].layno1 = 1;
 +              parameters.POC[1].resno1 = parameters.numresolution;
 +              parameters.POC[1].compno1 = 3;
 +              parameters.POC[1].prg1 = CPRL;
 +      }
 +      
 +      parameters.cp_comment = strdup (N_("DCP-o-matic"));
 +      parameters.cp_cinema = _resolution == RESOLUTION_2K ? CINEMA2K_24 : CINEMA4K_24;
 +
 +      /* 3 components, so use MCT */
 +      parameters.tcp_mct = 1;
 +      
 +      /* set max image */
 +      parameters.max_comp_size = max_comp_size;
 +      parameters.tcp_rates[0] = ((float) (3 * xyz->size().width * xyz->size().height * 12)) / (max_cs_len * 8);
 +
 +      /* Set event manager to null (openjpeg 1.3 bug) */
 +      cinfo->event_mgr = 0;
 +
 +      /* Setup the encoder parameters using the current image and user parameters */
 +      opj_setup_encoder (cinfo, &parameters, xyz->opj_image ());
 +
 +      opj_cio_t* cio = opj_cio_open ((opj_common_ptr) cinfo, 0, 0);
 +      if (cio == 0) {
 +              opj_destroy_compress (cinfo);
 +              throw EncodeError (N_("could not open JPEG2000 stream"));
 +      }
 +
 +      int const r = opj_encode (cinfo, cio, xyz->opj_image(), 0);
 +      if (r == 0) {
 +              opj_cio_close (cio);
 +              opj_destroy_compress (cinfo);
 +              throw EncodeError (N_("JPEG2000 encoding failed"));
 +      }
 +
 +      switch (_frame->eyes()) {
 +      case EYES_BOTH:
 +              LOG_GENERAL (N_("Finished locally-encoded frame %1 for mono"), _index);
 +              break;
 +      case EYES_LEFT:
 +              LOG_GENERAL (N_("Finished locally-encoded frame %1 for L"), _index);
 +              break;
 +      case EYES_RIGHT:
 +              LOG_GENERAL (N_("Finished locally-encoded frame %1 for R"), _index);
 +              break;
 +      default:
 +              break;
 +      }
 +
 +      shared_ptr<EncodedData> enc (new LocallyEncodedData (cio->buffer, cio_tell (cio)));
 +
 +      opj_cio_close (cio);
 +      free (parameters.cp_comment);
 +      opj_destroy_compress (cinfo);
 +
 +      return enc;
 +}
 +
 +/** Send this frame to a remote server for J2K encoding, then read the result.
 + *  @param serv Server to send to.
 + *  @return Encoded data.
 + */
 +shared_ptr<EncodedData>
 +DCPVideo::encode_remotely (ServerDescription serv)
 +{
 +      boost::asio::io_service io_service;
 +      boost::asio::ip::tcp::resolver resolver (io_service);
 +      boost::asio::ip::tcp::resolver::query query (serv.host_name(), raw_convert<string> (Config::instance()->server_port_base ()));
 +      boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve (query);
 +
 +      shared_ptr<Socket> socket (new Socket);
 +
 +      socket->connect (*endpoint_iterator);
 +
 +      /* Collect all XML metadata */
 +      xmlpp::Document doc;
 +      xmlpp::Element* root = doc.create_root_node ("EncodingRequest");
 +      root->add_child("Version")->add_child_text (raw_convert<string> (SERVER_LINK_VERSION));
 +      add_metadata (root);
 +
 +      LOG_GENERAL (N_("Sending frame %1 to remote"), _index);
 +      
 +      /* Send XML metadata */
 +      string xml = doc.write_to_string ("UTF-8");
 +      socket->write (xml.length() + 1);
 +      socket->write ((uint8_t *) xml.c_str(), xml.length() + 1);
 +
 +      /* Send binary data */
 +      _frame->send_binary (socket, _burn_subtitles);
 +
 +      /* Read the response (JPEG2000-encoded data); this blocks until the data
 +         is ready and sent back.
 +      */
 +      shared_ptr<EncodedData> e (new RemotelyEncodedData (socket->read_uint32 ()));
 +      socket->read (e->data(), e->size());
 +
 +      LOG_GENERAL (N_("Finished remotely-encoded frame %1"), _index);
 +      
 +      return e;
 +}
 +
 +void
 +DCPVideo::add_metadata (xmlpp::Element* el) const
 +{
 +      el->add_child("Index")->add_child_text (raw_convert<string> (_index));
 +      el->add_child("FramesPerSecond")->add_child_text (raw_convert<string> (_frames_per_second));
 +      el->add_child("J2KBandwidth")->add_child_text (raw_convert<string> (_j2k_bandwidth));
 +      el->add_child("Resolution")->add_child_text (raw_convert<string> (int (_resolution)));
 +      el->add_child("BurnSubtitles")->add_child_text (_burn_subtitles ? "1" : "0");
 +      _frame->add_metadata (el, _burn_subtitles);
 +}
 +
 +Eyes
 +DCPVideo::eyes () const
 +{
 +      return _frame->eyes ();
 +}
 +
 +/** @return true if this DCPVideo is definitely the same as another;
 + *  (apart from the frame index), false if it is probably not.
 + */
 +bool
 +DCPVideo::same (shared_ptr<const DCPVideo> other) const
 +{
 +      if (_frames_per_second != other->_frames_per_second ||
 +          _j2k_bandwidth != other->_j2k_bandwidth ||
 +          _resolution != other->_resolution ||
 +          _burn_subtitles != other->_burn_subtitles) {
 +              return false;
 +      }
 +
 +      return _frame->same (other->_frame);
 +}
diff --cc src/lib/job.cc
Simple merge
index 8e6fcd5f3524f8baf4e00c54f791cc92bf4778a7,0000000000000000000000000000000000000000..b5f0b5fa5fde53309692c9380eb1cdf920c3f9c1
mode 100644,000000..100644
--- /dev/null
@@@ -1,209 -1,0 +1,212 @@@
-       ColourConversion colour_conversion
 +/*
 +    Copyright (C) 2013-2014 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 <dcp/raw_convert.h>
 +#include "player_video.h"
 +#include "image.h"
 +#include "image_proxy.h"
 +#include "j2k_image_proxy.h"
 +#include "scaler.h"
 +
 +using std::string;
 +using std::cout;
 +using dcp::raw_convert;
 +using boost::shared_ptr;
 +using boost::dynamic_pointer_cast;
++using boost::optional;
 +
 +PlayerVideo::PlayerVideo (
 +      shared_ptr<const ImageProxy> in,
 +      DCPTime time,
 +      Crop crop,
 +      boost::optional<float> fade,
 +      dcp::Size inter_size,
 +      dcp::Size out_size,
 +      Scaler const * scaler,
 +      Eyes eyes,
 +      Part part,
-       _colour_conversion = ColourConversion (node);
++      optional<ColourConversion> colour_conversion
 +      )
 +      : _in (in)
 +      , _time (time)
 +      , _crop (crop)
 +      , _fade (fade)
 +      , _inter_size (inter_size)
 +      , _out_size (out_size)
 +      , _scaler (scaler)
 +      , _eyes (eyes)
 +      , _part (part)
 +      , _colour_conversion (colour_conversion)
 +{
 +
 +}
 +
 +PlayerVideo::PlayerVideo (shared_ptr<cxml::Node> node, shared_ptr<Socket> socket, shared_ptr<Log> log)
 +{
 +      _time = DCPTime (node->number_child<DCPTime::Type> ("Time"));
 +      _crop = Crop (node);
 +      _fade = node->optional_number_child<float> ("Fade");
 +
 +      _inter_size = dcp::Size (node->number_child<int> ("InterWidth"), node->number_child<int> ("InterHeight"));
 +      _out_size = dcp::Size (node->number_child<int> ("OutWidth"), node->number_child<int> ("OutHeight"));
 +      _scaler = Scaler::from_id (node->string_child ("Scaler"));
 +      _eyes = (Eyes) node->number_child<int> ("Eyes");
 +      _part = (Part) node->number_child<int> ("Part");
-       _colour_conversion.as_xml (node);
++      _colour_conversion = ColourConversion::from_xml (node);
 +
 +      _in = image_proxy_factory (node->node_child ("In"), socket, log);
 +
 +      if (node->optional_number_child<int> ("SubtitleX")) {
 +              
 +              _subtitle.position = Position<int> (node->number_child<int> ("SubtitleX"), node->number_child<int> ("SubtitleY"));
 +
 +              _subtitle.image.reset (
 +                      new Image (PIX_FMT_RGBA, dcp::Size (node->number_child<int> ("SubtitleWidth"), node->number_child<int> ("SubtitleHeight")), true)
 +                      );
 +              
 +              _subtitle.image->read_from_socket (socket);
 +      }
 +}
 +
 +void
 +PlayerVideo::set_subtitle (PositionImage image)
 +{
 +      _subtitle = image;
 +}
 +
 +shared_ptr<Image>
 +PlayerVideo::image (AVPixelFormat pixel_format, bool burn_subtitle) const
 +{
 +      shared_ptr<Image> im = _in->image ();
 +      
 +      Crop total_crop = _crop;
 +      switch (_part) {
 +      case PART_LEFT_HALF:
 +              total_crop.right += im->size().width / 2;
 +              break;
 +      case PART_RIGHT_HALF:
 +              total_crop.left += im->size().width / 2;
 +              break;
 +      case PART_TOP_HALF:
 +              total_crop.bottom += im->size().height / 2;
 +              break;
 +      case PART_BOTTOM_HALF:
 +              total_crop.top += im->size().height / 2;
 +              break;
 +      default:
 +              break;
 +      }
 +              
 +      shared_ptr<Image> out = im->crop_scale_window (total_crop, _inter_size, _out_size, _scaler, pixel_format, true);
 +
 +      if (burn_subtitle && _subtitle.image) {
 +              out->alpha_blend (_subtitle.image, _subtitle.position);
 +      }
 +
 +      if (_fade) {
 +              out->fade (_fade.get ());
 +      }
 +
 +      return out;
 +}
 +
 +void
 +PlayerVideo::add_metadata (xmlpp::Node* node, bool send_subtitles) const
 +{
 +      node->add_child("Time")->add_child_text (raw_convert<string> (_time.get ()));
 +      _crop.as_xml (node);
 +      if (_fade) {
 +              node->add_child("Fade")->add_child_text (raw_convert<string> (_fade.get ()));
 +      }
 +      _in->add_metadata (node->add_child ("In"));
 +      node->add_child("InterWidth")->add_child_text (raw_convert<string> (_inter_size.width));
 +      node->add_child("InterHeight")->add_child_text (raw_convert<string> (_inter_size.height));
 +      node->add_child("OutWidth")->add_child_text (raw_convert<string> (_out_size.width));
 +      node->add_child("OutHeight")->add_child_text (raw_convert<string> (_out_size.height));
 +      node->add_child("Scaler")->add_child_text (_scaler->id ());
 +      node->add_child("Eyes")->add_child_text (raw_convert<string> (_eyes));
 +      node->add_child("Part")->add_child_text (raw_convert<string> (_part));
++      if (_colour_conversion) {
++              _colour_conversion.get().as_xml (node);
++      }
 +      if (send_subtitles && _subtitle.image) {
 +              node->add_child ("SubtitleWidth")->add_child_text (raw_convert<string> (_subtitle.image->size().width));
 +              node->add_child ("SubtitleHeight")->add_child_text (raw_convert<string> (_subtitle.image->size().height));
 +              node->add_child ("SubtitleX")->add_child_text (raw_convert<string> (_subtitle.position.x));
 +              node->add_child ("SubtitleY")->add_child_text (raw_convert<string> (_subtitle.position.y));
 +      }
 +}
 +
 +void
 +PlayerVideo::send_binary (shared_ptr<Socket> socket, bool send_subtitles) const
 +{
 +      _in->send_binary (socket);
 +      if (send_subtitles && _subtitle.image) {
 +              _subtitle.image->write_to_socket (socket);
 +      }
 +}
 +
 +bool
 +PlayerVideo::has_j2k () const
 +{
 +      /* XXX: burnt-in subtitle; maybe other things */
 +      
 +      shared_ptr<const J2KImageProxy> j2k = dynamic_pointer_cast<const J2KImageProxy> (_in);
 +      if (!j2k) {
 +              return false;
 +      }
 +      
 +      return _crop == Crop () && _inter_size == j2k->size();
 +}
 +
 +shared_ptr<EncodedData>
 +PlayerVideo::j2k () const
 +{
 +      shared_ptr<const J2KImageProxy> j2k = dynamic_pointer_cast<const J2KImageProxy> (_in);
 +      assert (j2k);
 +      return j2k->j2k ();
 +}
 +
 +Position<int>
 +PlayerVideo::inter_position () const
 +{
 +      return Position<int> ((_out_size.width - _inter_size.width) / 2, (_out_size.height - _inter_size.height) / 2);
 +}
 +
 +/** @return true if this PlayerVideo is definitely the same as another
 + * (apart from _time), false if it is probably not
 + */
 +bool
 +PlayerVideo::same (shared_ptr<const PlayerVideo> other) const
 +{
 +      if (_in != other->_in ||
 +          _crop != other->_crop ||
 +          _fade.get_value_or(0) != other->_fade.get_value_or(0) ||
 +          _inter_size != other->_inter_size ||
 +          _out_size != other->_out_size ||
 +          _scaler != other->_scaler ||
 +          _eyes != other->_eyes ||
 +          _part != other->_part ||
 +          _colour_conversion != other->_colour_conversion ||
 +          !_subtitle.same (other->_subtitle)) {
 +              return false;
 +      }
 +
 +      return _in->same (other->_in);
 +}
index e9d260972824b10e58c3a4a71e2b2388b8bf97a3,0000000000000000000000000000000000000000..610a7526cb26090d582e647fff99ca3518a9d035
mode 100644,000000..100644
--- /dev/null
@@@ -1,102 -1,0 +1,102 @@@
-               ColourConversion
 +/*
 +    Copyright (C) 2013-2014 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 <boost/shared_ptr.hpp>
 +extern "C" {
 +#include <libavutil/pixfmt.h>
 +}
 +#include "types.h"
 +#include "position.h"
 +#include "colour_conversion.h"
 +#include "position_image.h"
 +
 +class Image;
 +class ImageProxy;
 +class Scaler;
 +class Socket;
 +class Log;
 +class EncodedData;
 +
 +/** Everything needed to describe a video frame coming out of the player, but with the
 + *  bits still their raw form.  We may want to combine the bits on a remote machine,
 + *  or maybe not even bother to combine them at all.
 + */
 +class PlayerVideo
 +{
 +public:
 +      PlayerVideo (
 +              boost::shared_ptr<const ImageProxy>,
 +              DCPTime,
 +              Crop,
 +              boost::optional<float>,
 +              dcp::Size,
 +              dcp::Size,
 +              Scaler const *,
 +              Eyes,
 +              Part,
-       ColourConversion colour_conversion () const {
++              boost::optional<ColourConversion>
 +              );
 +      
 +      PlayerVideo (boost::shared_ptr<cxml::Node>, boost::shared_ptr<Socket>, boost::shared_ptr<Log>);
 +
 +      void set_subtitle (PositionImage);
 +      
 +      boost::shared_ptr<Image> image (AVPixelFormat pix_fmt, bool burn_subtitle) const;
 +
 +      void add_metadata (xmlpp::Node* node, bool send_subtitles) const;
 +      void send_binary (boost::shared_ptr<Socket> socket, bool send_subtitles) const;
 +
 +      bool has_j2k () const;
 +      boost::shared_ptr<EncodedData> j2k () const;
 +
 +      DCPTime time () const {
 +              return _time;
 +      }
 +
 +      Eyes eyes () const {
 +              return _eyes;
 +      }
 +
-       ColourConversion _colour_conversion;
++      boost::optional<ColourConversion> colour_conversion () const {
 +              return _colour_conversion;
 +      }
 +
 +      /** @return Position of the content within the overall image once it has been scaled up */
 +      Position<int> inter_position () const;
 +
 +      /** @return Size of the content within the overall image once it has been scaled up */
 +      dcp::Size inter_size () const {
 +              return _inter_size;
 +      }
 +
 +      bool same (boost::shared_ptr<const PlayerVideo> other) const;
 +
 +private:
 +      boost::shared_ptr<const ImageProxy> _in;
 +      DCPTime _time;
 +      Crop _crop;
 +      boost::optional<float> _fade;
 +      dcp::Size _inter_size;
 +      dcp::Size _out_size;
 +      Scaler const * _scaler;
 +      Eyes _eyes;
 +      Part _part;
++      boost::optional<ColourConversion> _colour_conversion;
 +      PositionImage _subtitle;
 +};
index 22412da4a3640b5313cd6d75cdb25422a4ee08f6,264d9ab4a1bf6c69e86976629a85e6af752793cb..4580e54d400e40e9fc59f7eaebec9bd806f8520d
@@@ -393,6 -395,23 +399,6 @@@ Playlist::move_later (shared_ptr<Conten
        }
  
        (*next)->set_position (c->position ());
-       c->set_position (c->position() + c->length_after_trim ());
+       c->set_position (c->position() + (*next)->length_after_trim ());
        sort (_content.begin(), _content.end(), ContentSorter ());
  }
 -
 -FrameRateChange
 -Playlist::active_frame_rate_change (Time t, int dcp_video_frame_rate) const
 -{
 -      for (ContentList::const_iterator i = _content.begin(); i != _content.end(); ++i) {
 -              shared_ptr<const VideoContent> vc = dynamic_pointer_cast<const VideoContent> (*i);
 -              if (!vc) {
 -                      continue;
 -              }
 -
 -              if (vc->position() >= t && t < vc->end()) {
 -                      return FrameRateChange (vc->video_frame_rate(), dcp_video_frame_rate);
 -              }
 -      }
 -
 -      return FrameRateChange (dcp_video_frame_rate, dcp_video_frame_rate);
 -}
index 68418910cb9fc190ff35e6526c8a77a1b29e8472,0dc9cd5df9c207a688fc84a8a89a00c8a59e558d..32a4b67e2ae9adde45131a8083a4f59d97d28ccc
@@@ -681,11 -624,19 +687,19 @@@ msgstr "kopiere %1
  msgid "could not create file %1"
  msgstr "Datei %1 konnte nicht erstellt werden."
  
- #: src/lib/writer.cc:430
 +#: src/lib/ffmpeg.cc:102
 +msgid "could not find stream information"
 +msgstr "Keine Spur-Information gefunden"
 +
 -#: src/lib/ffmpeg.cc:105
 -msgid "could not find stream information"
 -msgstr "Keine Spur-Information gefunden"
 -
+ #: src/lib/ffmpeg.cc:179
+ msgid "could not find audio decoder"
+ msgstr "Ton Dekoder nicht gefunden."
+ #: src/lib/ffmpeg.cc:158
+ msgid "could not find video decoder"
+ msgstr "Bild-Dekoder nicht gefunden"
+ #: src/lib/writer.cc:439
  msgid "could not move audio MXF into the DCP (%1)"
  msgstr "Ton MXF kann nicht in das DCP verschoben werden (%1)"
  
@@@ -816,15 -771,6 +830,9 @@@ msgstr "Standbild
  msgid "unknown"
  msgstr "unbekannt"
  
- #~ msgid "could not find audio decoder"
- #~ msgstr "Ton Dekoder nicht gefunden."
- #~ msgid "could not find video decoder"
- #~ msgstr "Bild-Dekoder nicht gefunden"
 +#~ msgid "non-bitmap subtitles not yet supported"
 +#~ msgstr "Nur Bitmap Untertitel werden unterstützt"
 +
  #~ msgid "Could not read DCP to make KDM for"
  #~ msgstr "DCP konnte nicht zur Schlüsselerstellung geöffnet werden"
  
index e874c64151ca619bc1663f6c60a01c9931e92e7a,4fcfac93a8a06c9abf85477b20581f9ae1743dfa..5dc99462b266e8d5d194761beb6b87620d4a1766
@@@ -675,7 -622,11 +681,15 @@@ msgstr "No se pudo crear el fichero (%1
  msgid "could not find stream information"
  msgstr "no se pudo encontrar información del flujo"
  
 +#: src/lib/writer.cc:430
++msgid "could not find audio decoder"
++msgstr "no se encontró el decodificador de audio"
++
+ #: src/lib/ffmpeg.cc:158
+ msgid "could not find video decoder"
+ msgstr "no se pudo encontrar decodificador de vídeo"
+ #: src/lib/writer.cc:439
  msgid "could not move audio MXF into the DCP (%1)"
  msgstr "no s puedo mover el audio MXF en el DCP (%1)"
  
@@@ -806,15 -761,6 +820,9 @@@ msgstr "imagen fija
  msgid "unknown"
  msgstr "desconocido"
  
- #~ msgid "could not find audio decoder"
- #~ msgstr "no se encontró el decodificador de audio"
- #~ msgid "could not find video decoder"
- #~ msgstr "no se pudo encontrar decodificador de vídeo"
 +#~ msgid "non-bitmap subtitles not yet supported"
 +#~ msgstr "todavía no se soportan subtítulos que no son en mapas de bits"
 +
  #~ msgid "Could not read DCP to make KDM for"
  #~ msgstr "No se pudo leer el DCP para hacer el KDM"
  
index 474da73f9a3a6fe24d33900b09c4c89e38716aa3,ff1152f390c7dbc259629a53142f9ff474a06e5a..bf8dc04f7cf1f35e158e833b1882241b6a2b014d
@@@ -674,11 -616,19 +680,19 @@@ msgstr "copie de %1
  msgid "could not create file %1"
  msgstr "Écriture vers fichier distant (%1) impossible"
  
- #: src/lib/writer.cc:430
 +#: src/lib/ffmpeg.cc:102
 +msgid "could not find stream information"
 +msgstr "information du flux introuvable"
 +
 -#: src/lib/ffmpeg.cc:105
 -msgid "could not find stream information"
 -msgstr "information du flux introuvable"
 -
+ #: src/lib/ffmpeg.cc:179
+ msgid "could not find audio decoder"
+ msgstr "décodeur audio introuvable"
+ #: src/lib/ffmpeg.cc:158
+ msgid "could not find video decoder"
+ msgstr "décodeur vidéo introuvable"
+ #: src/lib/writer.cc:439
  msgid "could not move audio MXF into the DCP (%1)"
  msgstr "ne peut déplacer un MXF son dans le DCP (%1)"
  
@@@ -811,15 -765,6 +825,9 @@@ msgstr "%1 [restant]
  msgid "unknown"
  msgstr "Inconnu"
  
- #~ msgid "could not find audio decoder"
- #~ msgstr "décodeur audio introuvable"
- #~ msgid "could not find video decoder"
- #~ msgstr "décodeur vidéo introuvable"
 +#~ msgid "non-bitmap subtitles not yet supported"
 +#~ msgstr "sous-titres non-bitmap non supportés actuellement"
 +
  #~ msgid "Could not read DCP to make KDM for"
  #~ msgstr "DCP illisible pour fabrication de KDM"
  
index a22ccee3ca5be3aedc9f104abaee92f071bef673,5863e5ad7726bec9db3feb8b3bce6bb37c574ee3..a3b1b9de752024c837ea207e6c3e5ac243e5c528
@@@ -829,15 -782,6 +843,9 @@@ msgstr "ancora
  msgid "unknown"
  msgstr "Errore sconosciuto"
  
- #~ msgid "could not find audio decoder"
- #~ msgstr "non riesco a trovare il decoder audio"
- #~ msgid "could not find video decoder"
- #~ msgstr "non riesco a trovare il decoder video"
 +#~ msgid "non-bitmap subtitles not yet supported"
 +#~ msgstr "sottotitoli non-bitmap non ancora supportati"
 +
  #~ msgid "Cubic interpolating deinterlacer"
  #~ msgstr "Deinterlacciatore cubico interpolato"
  
index 81a1e626bf2ff47a5e45ec7715dc2e1f649702bb,bc953fbbe8f549de561b2bb7b2a23323632e0744..414eacdc55d4772ffb3fa247fe5e15145bd8c919
@@@ -808,14 -763,5 +822,8 @@@ msgstr "still
  msgid "unknown"
  msgstr "onbekend"
  
- #~ msgid "could not find audio decoder"
- #~ msgstr "kan geen audio decoder vinden"
- #~ msgid "could not find video decoder"
- #~ msgstr "kan geen videodecoder vinden"
 +#~ msgid "non-bitmap subtitles not yet supported"
 +#~ msgstr "non-bitmap ondertitels worden nog niet ondersteund"
 +
  #~ msgid "Could not read DCP to make KDM for"
  #~ msgstr "Kan DCP niet lezen om KDM te maken"
index 29127294f9d2291671b9dd4deda2299120480214,0c11c69e087928ec8a8013ecab7c6b08e3d0627d..75a664191e633da678f093c07aea508a4c65033e
@@@ -819,15 -774,6 +833,9 @@@ msgstr "stillbild
  msgid "unknown"
  msgstr "okänd"
  
- #~ msgid "could not find audio decoder"
- #~ msgstr "kunde inte hitta audio-avkodare"
- #~ msgid "could not find video decoder"
- #~ msgstr "kunde inte hitta video-avkodare"
 +#~ msgid "non-bitmap subtitles not yet supported"
 +#~ msgstr "icke-rastergrafiska undertexter stöds inte ännu"
 +
  #~ msgid "Could not read DCP to make KDM for"
  #~ msgstr "Kunde inte läsa DCP för att skapa KDM"
  
index ba656e4c2410330da76bfb4a193facc646137c8d,3094a70c8ca34a87c01f13c82400cf46702ce139..976bc3aa02429736d66fc2b4a235943f8a2a408b
@@@ -65,12 -61,13 +65,12 @@@ VideoContent::VideoContent (shared_ptr<
        , _video_frame_type (VIDEO_FRAME_TYPE_2D)
        , _scale (Config::instance()->default_scale ())
  {
-       setup_default_colour_conversion ();
+       set_default_colour_conversion ();
  }
  
 -VideoContent::VideoContent (shared_ptr<const Film> f, Time s, VideoContent::Frame len)
 +VideoContent::VideoContent (shared_ptr<const Film> f, DCPTime s, ContentTime len)
        : Content (f, s)
        , _video_length (len)
 -      , _original_video_frame_rate (0)
        , _video_frame_rate (0)
        , _video_frame_type (VIDEO_FRAME_TYPE_2D)
        , _scale (Config::instance()->default_scale ())
@@@ -85,12 -83,13 +85,12 @@@ VideoContent::VideoContent (shared_ptr<
        , _video_frame_type (VIDEO_FRAME_TYPE_2D)
        , _scale (Config::instance()->default_scale ())
  {
-       setup_default_colour_conversion ();
+       set_default_colour_conversion ();
  }
  
 -VideoContent::VideoContent (shared_ptr<const Film> f, shared_ptr<const cxml::Node> node, int version)
 +VideoContent::VideoContent (shared_ptr<const Film> f, cxml::ConstNodePtr node, int version)
        : Content (f, node)
  {
 -      _video_length = node->number_child<VideoContent::Frame> ("VideoLength");
        _video_size.width = node->number_child<int> ("VideoWidth");
        _video_size.height = node->number_child<int> ("VideoHeight");
        _video_frame_rate = node->number_child<float> ("VideoFrameRate");
        } else {
                _scale = VideoContentScale (node->node_child ("Scale"));
        }
-       _colour_conversion = ColourConversion (node->node_child ("ColourConversion"));
 +      
+       if (node->optional_node_child ("ColourConversion")) {
+               _colour_conversion = ColourConversion (node->node_child ("ColourConversion"));
+       }
 +      if (version >= 32) {
 +              _fade_in = ContentTime (node->number_child<int64_t> ("FadeIn"));
 +              _fade_out = ContentTime (node->number_child<int64_t> ("FadeOut"));
 +      }
  }
  
  VideoContent::VideoContent (shared_ptr<const Film> f, vector<shared_ptr<Content> > c)
@@@ -186,15 -171,16 +189,17 @@@ VideoContent::as_xml (xmlpp::Node* node
        node->add_child("VideoFrameType")->add_child_text (raw_convert<string> (static_cast<int> (_video_frame_type)));
        _crop.as_xml (node);
        _scale.as_xml (node->add_child("Scale"));
-       _colour_conversion.as_xml (node->add_child("ColourConversion"));
+       if (_colour_conversion) {
+               _colour_conversion.get().as_xml (node->add_child("ColourConversion"));
+       }
 +      node->add_child("FadeIn")->add_child_text (raw_convert<string> (_fade_in.get ()));
 +      node->add_child("FadeOut")->add_child_text (raw_convert<string> (_fade_out.get ()));
  }
  
  void
- VideoContent::setup_default_colour_conversion ()
+ VideoContent::set_default_colour_conversion ()
  {
-       _colour_conversion = PresetColourConversion (_("sRGB"), 2.4, true, dcp::colour_matrix::srgb_to_xyz, 2.6).conversion;
 -      set_colour_conversion (PresetColourConversion (_("sRGB"), 2.4, true, libdcp::colour_matrix::srgb_to_xyz, 2.6).conversion);
++      set_colour_conversion (PresetColourConversion (_("sRGB"), 2.4, true, dcp::colour_matrix::srgb_to_xyz, 2.6).conversion);
  }
  
  void
index e88fb022720d0c91e13d875b36ff6589c1eec0ce,9aa3be521e48f8ee0187ce2907007c1fa4cb3fd6..3c8e5fefd5a587d7d57ef8f885031197f461e977
@@@ -89,10 -92,9 +89,12 @@@ public
        void set_bottom_crop (int);
  
        void set_scale (VideoContentScale);
+       void unset_colour_conversion ();
        void set_colour_conversion (ColourConversion);
+       void set_default_colour_conversion ();
 +
 +      void set_fade_in (ContentTime);
 +      void set_fade_out (ContentTime);
        
        VideoFrameType video_frame_type () const {
                boost::mutex::scoped_lock lm (_mutex);
@@@ -173,9 -162,7 +175,9 @@@ private
        VideoFrameType _video_frame_type;
        Crop _crop;
        VideoContentScale _scale;
-       ColourConversion _colour_conversion;
+       boost::optional<ColourConversion> _colour_conversion;
 +      ContentTime _fade_in;
 +      ContentTime _fade_out;
  };
  
  #endif
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 7f9461d940fb4ba6f4035707fc1f930c214c62f9,4b3898859686a6b1af2003ea2d57637daf1f6a7a..881317f3aa74cfd94128651a909a4c5ec79a5bdd
@@@ -88,11 -92,331 +88,9 @@@ FilmEditor::FilmEditor (wxWindow* paren
                bind (&FilmEditor::active_jobs_changed, this, _1)
                );
  
 -      Config::instance()->Changed.connect (boost::bind (&FilmEditor::config_changed, this));
 -
        set_film (shared_ptr<Film> ());
-       
--      SetSizerAndFit (s);
 -}
 -
 -void
 -FilmEditor::make_dcp_panel ()
 -{
 -      _dcp_panel = new wxPanel (_main_notebook);
 -      _dcp_sizer = new wxBoxSizer (wxVERTICAL);
 -      _dcp_panel->SetSizer (_dcp_sizer);
 -
 -      wxGridBagSizer* grid = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
 -      _dcp_sizer->Add (grid, 0, wxEXPAND | wxALL, 8);
 -
 -      int r = 0;
 -      
 -      add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Name"), true, wxGBPosition (r, 0));
 -      _name = new wxTextCtrl (_dcp_panel, wxID_ANY);
 -      grid->Add (_name, wxGBPosition(r, 1), wxDefaultSpan, wxEXPAND | wxLEFT | wxRIGHT);
 -      ++r;
 -      
 -      int flags = wxALIGN_CENTER_VERTICAL;
 -#ifdef __WXOSX__
 -      flags |= wxALIGN_RIGHT;
 -#endif        
 -
 -      _use_isdcf_name = new wxCheckBox (_dcp_panel, wxID_ANY, _("Use ISDCF name"));
 -      grid->Add (_use_isdcf_name, wxGBPosition (r, 0), wxDefaultSpan, flags);
 -      _edit_isdcf_button = new wxButton (_dcp_panel, wxID_ANY, _("Details..."));
 -      grid->Add (_edit_isdcf_button, wxGBPosition (r, 1), wxDefaultSpan);
 -      ++r;
 -
 -      add_label_to_grid_bag_sizer (grid, _dcp_panel, _("DCP Name"), true, wxGBPosition (r, 0));
 -      _dcp_name = new wxStaticText (_dcp_panel, wxID_ANY, wxT (""));
 -      grid->Add (_dcp_name, wxGBPosition(r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
 -      ++r;
 -
 -      add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Container"), true, wxGBPosition (r, 0));
 -      _container = new wxChoice (_dcp_panel, wxID_ANY);
 -      grid->Add (_container, wxGBPosition (r, 1), wxDefaultSpan, wxEXPAND);
 -      ++r;
 -
 -      add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Content Type"), true, wxGBPosition (r, 0));
 -      _dcp_content_type = new wxChoice (_dcp_panel, wxID_ANY);
 -      grid->Add (_dcp_content_type, wxGBPosition (r, 1));
 -      ++r;
 -
 -      {
 -              add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Frame Rate"), true, wxGBPosition (r, 0));
 -              _frame_rate_sizer = new wxBoxSizer (wxHORIZONTAL);
 -              _frame_rate_choice = new wxChoice (_dcp_panel, wxID_ANY);
 -              _frame_rate_sizer->Add (_frame_rate_choice, 1, wxALIGN_CENTER_VERTICAL);
 -              _frame_rate_spin = new wxSpinCtrl (_dcp_panel, wxID_ANY);
 -              _frame_rate_sizer->Add (_frame_rate_spin, 1, wxALIGN_CENTER_VERTICAL);
 -              setup_frame_rate_widget ();
 -              _best_frame_rate = new wxButton (_dcp_panel, wxID_ANY, _("Use best"));
 -              _frame_rate_sizer->Add (_best_frame_rate, 1, wxALIGN_CENTER_VERTICAL | wxEXPAND);
 -              grid->Add (_frame_rate_sizer, wxGBPosition (r, 1));
 -      }
 -      ++r;
 -
 -      _signed = new wxCheckBox (_dcp_panel, wxID_ANY, _("Signed"));
 -      grid->Add (_signed, wxGBPosition (r, 0), wxGBSpan (1, 2));
 -      ++r;
 -      
 -      _encrypted = new wxCheckBox (_dcp_panel, wxID_ANY, _("Encrypted"));
 -      grid->Add (_encrypted, wxGBPosition (r, 0), wxGBSpan (1, 2));
 -      ++r;
 -
 -      add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Audio channels"), true, wxGBPosition (r, 0));
 -      _audio_channels = new wxSpinCtrl (_dcp_panel, wxID_ANY);
 -      grid->Add (_audio_channels, wxGBPosition (r, 1));
 -      ++r;
 -
 -      _three_d = new wxCheckBox (_dcp_panel, wxID_ANY, _("3D"));
 -      grid->Add (_three_d, wxGBPosition (r, 0), wxGBSpan (1, 2));
 -      ++r;
 -
 -      add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Resolution"), true, wxGBPosition (r, 0));
 -      _resolution = new wxChoice (_dcp_panel, wxID_ANY);
 -      grid->Add (_resolution, wxGBPosition (r, 1));
 -      ++r;
 -
 -      {
 -              add_label_to_grid_bag_sizer (grid, _dcp_panel, _("JPEG2000 bandwidth"), true, wxGBPosition (r, 0));
 -              wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
 -              _j2k_bandwidth = new wxSpinCtrl (_dcp_panel, wxID_ANY);
 -              s->Add (_j2k_bandwidth, 1);
 -              add_label_to_sizer (s, _dcp_panel, _("Mbit/s"), false);
 -              grid->Add (s, wxGBPosition (r, 1));
 -      }
 -      ++r;
 -
 -      add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Standard"), true, wxGBPosition (r, 0));
 -      _standard = new wxChoice (_dcp_panel, wxID_ANY);
 -      grid->Add (_standard, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
 -      ++r;
 -
 -      add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Scaler"), true, wxGBPosition (r, 0));
 -      _scaler = new wxChoice (_dcp_panel, wxID_ANY);
 -      grid->Add (_scaler, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
 -      ++r;
 -
 -      vector<Scaler const *> const sc = Scaler::all ();
 -      for (vector<Scaler const *>::const_iterator i = sc.begin(); i != sc.end(); ++i) {
 -              _scaler->Append (std_to_wx ((*i)->name()));
 -      }
 -
 -      vector<Ratio const *> const ratio = Ratio::all ();
 -      for (vector<Ratio const *>::const_iterator i = ratio.begin(); i != ratio.end(); ++i) {
 -              _container->Append (std_to_wx ((*i)->nickname ()));
 -      }
 -
 -      vector<DCPContentType const *> const ct = DCPContentType::all ();
 -      for (vector<DCPContentType const *>::const_iterator i = ct.begin(); i != ct.end(); ++i) {
 -              _dcp_content_type->Append (std_to_wx ((*i)->pretty_name ()));
 -      }
 -
 -      list<int> const dfr = Config::instance()->allowed_dcp_frame_rates ();
 -      for (list<int>::const_iterator i = dfr.begin(); i != dfr.end(); ++i) {
 -              _frame_rate_choice->Append (std_to_wx (boost::lexical_cast<string> (*i)));
 -      }
 -
 -      _audio_channels->SetRange (0, MAX_DCP_AUDIO_CHANNELS);
 -      _j2k_bandwidth->SetRange (1, Config::instance()->maximum_j2k_bandwidth() / 1000000);
 -      _frame_rate_spin->SetRange (1, 480);
 -
 -      _resolution->Append (_("2K"));
 -      _resolution->Append (_("4K"));
 -
 -      _standard->Append (_("SMPTE"));
 -      _standard->Append (_("Interop"));
 -}
 -
 -void
 -FilmEditor::connect_to_widgets ()
 -{
 -      _name->Bind             (wxEVT_COMMAND_TEXT_UPDATED,          boost::bind (&FilmEditor::name_changed, this));
 -      _use_isdcf_name->Bind   (wxEVT_COMMAND_CHECKBOX_CLICKED,      boost::bind (&FilmEditor::use_isdcf_name_toggled, this));
 -      _edit_isdcf_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED,        boost::bind (&FilmEditor::edit_isdcf_button_clicked, this));
 -      _container->Bind        (wxEVT_COMMAND_CHOICE_SELECTED,       boost::bind (&FilmEditor::container_changed, this));
 -      _content->Bind          (wxEVT_COMMAND_LIST_ITEM_SELECTED,    boost::bind (&FilmEditor::content_selection_changed, this));
 -      _content->Bind          (wxEVT_COMMAND_LIST_ITEM_DESELECTED,  boost::bind (&FilmEditor::content_selection_changed, this));
 -      _content->Bind          (wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, boost::bind (&FilmEditor::content_right_click, this, _1));
 -      _content->Bind          (wxEVT_DROP_FILES,                    boost::bind (&FilmEditor::content_files_dropped, this, _1));
 -      _content_add_file->Bind (wxEVT_COMMAND_BUTTON_CLICKED,        boost::bind (&FilmEditor::content_add_file_clicked, this));
 -      _content_add_folder->Bind (wxEVT_COMMAND_BUTTON_CLICKED,      boost::bind (&FilmEditor::content_add_folder_clicked, this));
 -      _content_remove->Bind   (wxEVT_COMMAND_BUTTON_CLICKED,        boost::bind (&FilmEditor::content_remove_clicked, this));
 -      _content_earlier->Bind  (wxEVT_COMMAND_BUTTON_CLICKED,        boost::bind (&FilmEditor::content_earlier_clicked, this));
 -      _content_later->Bind    (wxEVT_COMMAND_BUTTON_CLICKED,        boost::bind (&FilmEditor::content_later_clicked, this));
 -      _content_timeline->Bind (wxEVT_COMMAND_BUTTON_CLICKED,        boost::bind (&FilmEditor::content_timeline_clicked, this));
 -      _scaler->Bind           (wxEVT_COMMAND_CHOICE_SELECTED,       boost::bind (&FilmEditor::scaler_changed, this));
 -      _dcp_content_type->Bind (wxEVT_COMMAND_CHOICE_SELECTED,       boost::bind (&FilmEditor::dcp_content_type_changed, this));
 -      _frame_rate_choice->Bind(wxEVT_COMMAND_CHOICE_SELECTED,       boost::bind (&FilmEditor::frame_rate_choice_changed, this));
 -      _frame_rate_spin->Bind  (wxEVT_COMMAND_SPINCTRL_UPDATED,      boost::bind (&FilmEditor::frame_rate_spin_changed, this));
 -      _best_frame_rate->Bind  (wxEVT_COMMAND_BUTTON_CLICKED,        boost::bind (&FilmEditor::best_frame_rate_clicked, this));
 -      _signed->Bind           (wxEVT_COMMAND_CHECKBOX_CLICKED,      boost::bind (&FilmEditor::signed_toggled, this));
 -      _encrypted->Bind        (wxEVT_COMMAND_CHECKBOX_CLICKED,      boost::bind (&FilmEditor::encrypted_toggled, this));
 -      _audio_channels->Bind   (wxEVT_COMMAND_SPINCTRL_UPDATED,      boost::bind (&FilmEditor::audio_channels_changed, this));
 -      _j2k_bandwidth->Bind    (wxEVT_COMMAND_SPINCTRL_UPDATED,      boost::bind (&FilmEditor::j2k_bandwidth_changed, this));
 -      _resolution->Bind       (wxEVT_COMMAND_CHOICE_SELECTED,       boost::bind (&FilmEditor::resolution_changed, this));
 -      _three_d->Bind          (wxEVT_COMMAND_CHECKBOX_CLICKED,      boost::bind (&FilmEditor::three_d_changed, this));
 -      _standard->Bind         (wxEVT_COMMAND_CHOICE_SELECTED,       boost::bind (&FilmEditor::standard_changed, this));
 -}
 -
 -void
 -FilmEditor::make_content_panel ()
 -{
 -      _content_panel = new wxPanel (_main_notebook);
 -      _content_sizer = new wxBoxSizer (wxVERTICAL);
 -      _content_panel->SetSizer (_content_sizer);
 -
 -      {
 -              wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
 -              
 -              _content = new wxListCtrl (_content_panel, wxID_ANY, wxDefaultPosition, wxSize (320, 160), wxLC_REPORT | wxLC_NO_HEADER);
 -              s->Add (_content, 1, wxEXPAND | wxTOP | wxBOTTOM, 6);
 -
 -              _content->InsertColumn (0, wxT(""));
 -              _content->SetColumnWidth (0, 512);
 -
 -              wxBoxSizer* b = new wxBoxSizer (wxVERTICAL);
 -
 -              _content_add_file = new wxButton (_content_panel, wxID_ANY, _("Add file(s)..."));
 -              _content_add_file->SetToolTip (_("Add video, image or sound files to the film."));
 -              b->Add (_content_add_file,   0, wxEXPAND | wxALL, DCPOMATIC_BUTTON_STACK_GAP);
 -              
 -              _content_add_folder = new wxButton (_content_panel, wxID_ANY, _("Add image\nsequence..."));
 -              _content_add_folder->SetToolTip (_("Add a directory of image files which will be used as a moving image sequence."));
 -              b->Add (_content_add_folder, 1, wxEXPAND | wxALL, DCPOMATIC_BUTTON_STACK_GAP);
 -              
 -              _content_remove = new wxButton (_content_panel, wxID_ANY, _("Remove"));
 -              _content_remove->SetToolTip (_("Remove the selected piece of content from the film."));
 -              b->Add (_content_remove, 0, wxEXPAND | wxALL, DCPOMATIC_BUTTON_STACK_GAP);
 -              
 -              _content_earlier = new wxButton (_content_panel, wxID_ANY, _("Up"));
 -              _content_earlier->SetToolTip (_("Move the selected piece of content earlier in the film."));
 -              b->Add (_content_earlier, 0, wxEXPAND | wxALL, DCPOMATIC_BUTTON_STACK_GAP);
 -              
 -              _content_later = new wxButton (_content_panel, wxID_ANY, _("Down"));
 -              _content_later->SetToolTip (_("Move the selected piece of content later in the film."));
 -              b->Add (_content_later, 0, wxEXPAND | wxALL, DCPOMATIC_BUTTON_STACK_GAP);
 -
 -              _content_timeline = new wxButton (_content_panel, wxID_ANY, _("Timeline..."));
 -              _content_timeline->SetToolTip (_("Open the timeline for the film."));
 -              b->Add (_content_timeline, 0, wxEXPAND | wxALL, DCPOMATIC_BUTTON_STACK_GAP);
 -
 -              s->Add (b, 0, wxALL, 4);
 -
 -              _content_sizer->Add (s, 0, wxEXPAND | wxALL, 6);
 -      }
 -
 -      _content_notebook = new wxNotebook (_content_panel, wxID_ANY);
 -      _content_sizer->Add (_content_notebook, 1, wxEXPAND | wxTOP, 6);
 -
 -      _video_panel = new VideoPanel (this);
 -      _panels.push_back (_video_panel);
 -      _audio_panel = new AudioPanel (this);
 -      _panels.push_back (_audio_panel);
 -      _subtitle_panel = new SubtitlePanel (this);
 -      _panels.push_back (_subtitle_panel);
 -      _timing_panel = new TimingPanel (this);
 -      _panels.push_back (_timing_panel);
 -
 -      _content->DragAcceptFiles (true);
 -}
 -
 -/** Called when the name widget has been changed */
 -void
 -FilmEditor::name_changed ()
 -{
 -      if (!_film) {
 -              return;
 -      }
 -
 -      _film->set_name (string (_name->GetValue().mb_str()));
 -}
 -
 -void
 -FilmEditor::j2k_bandwidth_changed ()
 -{
 -      if (!_film) {
 -              return;
 -      }
 -      
 -      _film->set_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
 -}
 -
 -void
 -FilmEditor::signed_toggled ()
 -{
 -      if (!_film) {
 -              return;
 -      }
 -
 -      _film->set_signed (_signed->GetValue ());
 -}
 -
 -void
 -FilmEditor::encrypted_toggled ()
 -{
 -      if (!_film) {
 -              return;
 -      }
 -
 -      _film->set_encrypted (_encrypted->GetValue ());
 -}
 -                             
 -/** Called when the frame rate choice widget has been changed */
 -void
 -FilmEditor::frame_rate_choice_changed ()
 -{
 -      if (!_film) {
 -              return;
 -      }
 -
 -      _film->set_video_frame_rate (
 -              boost::lexical_cast<int> (
 -                      wx_to_std (_frame_rate_choice->GetString (_frame_rate_choice->GetSelection ()))
 -                      )
 -              );
 -}
 -
 -/** Called when the frame rate spin widget has been changed */
 -void
 -FilmEditor::frame_rate_spin_changed ()
 -{
 -      if (!_film) {
 -              return;
 -      }
 -
 -      _film->set_video_frame_rate (_frame_rate_spin->GetValue ());
 -}
 -
 -void
 -FilmEditor::audio_channels_changed ()
 -{
 -      if (!_film) {
 -              return;
 -      }
 -
 -      _film->set_audio_channels (_audio_channels->GetValue ());
 -}
 -
 -void
 -FilmEditor::resolution_changed ()
 -{
 -      if (!_film) {
 -              return;
 -      }
 -
 -      _film->set_resolution (_resolution->GetSelection() == 0 ? RESOLUTION_2K : RESOLUTION_4K);
  }
  
 -void
 -FilmEditor::standard_changed ()
 -{
 -      if (!_film) {
 -              return;
 -      }
 -
 -      _film->set_interop (_standard->GetSelection() == 1);
 -}
  
  /** Called when the metadata stored in the Film object has changed;
   *  so that we can update the GUI.
index d7353e9144857dcf7a86933968607ae543bab77c,4b8b1fdf1c5fae7116946ac340386260495c6cb3..df095e8ce7e6d3496ff626d414d639f6aebbb22f
@@@ -110,11 -114,17 +119,17 @@@ msgstr "
  msgid "Add file(s)..."
  msgstr "Datei(en) hinzufügen..."
  
- #: src/wx/content_panel.cc:69
- msgid "Add folder..."
- msgstr "Ordner hinzufügen..."
+ #: src/wx/film_editor.cc:284
+ msgid ""
+ "Add image\n"
+ "sequence..."
+ msgstr ""
+ #: src/wx/film_editor.cc:281
+ msgid "Add video, image or sound files to the film."
+ msgstr ""
  
 -#: src/wx/editable_list.h:62
 +#: src/wx/config_dialog.cc:597 src/wx/editable_list.h:62
  msgid "Add..."
  msgstr "Hinzufügen..."
  
@@@ -799,18 -765,10 +835,22 @@@ msgstr "Kein
  msgid "Off"
  msgstr "Aus"
  
 +#: src/wx/config_dialog.cc:1167
 +msgid "Open console window"
 +msgstr ""
 +
 +#: src/wx/make_signer_chain_dialog.cc:25
 +msgid "Organisation"
 +msgstr ""
 +
 +#: src/wx/make_signer_chain_dialog.cc:27
 +msgid "Organisational unit"
 +msgstr ""
 +
+ #: src/wx/film_editor.cc:301
+ msgid "Open the timeline for the film."
+ msgstr ""
  #: src/wx/screen_dialog.cc:65
  msgid "Other"
  msgstr "Andere"
@@@ -1358,24 -1256,9 +1406,6 @@@ msgstr "mal
  msgid "video"
  msgstr "Bild"
  
- #~ msgid "1 channel"
- #~ msgstr "1 Kanal"
- #~ msgid "Audio channels"
- #~ msgstr "Ton Kanäle"
- #~ msgid "Could not decode video for view (%s)"
- #~ msgstr "Bild konnte nicht zur Vorschau dekodiert werden (%s)"
- #~ msgid "Hz"
- #~ msgstr "Hz"
- #~ msgid "With Subtitles"
- #~ msgstr "Mit Untertitelung"
- #~ msgid "channels"
- #~ msgstr "Kanäle"
 -#~ msgid "Add folder..."
 -#~ msgstr "Ordner hinzufügen..."
--
  #~ msgid "Default creator"
  #~ msgstr "Standard 'creator' (DCI)"
  
index 0191fc503fc9a800403257eb0b16c79bfebfe695,6aea49f52c2d6565a8909d694fb295fb9d70af15..415d539a191b4f6ec78f53860a75f3b61de8554a
@@@ -111,11 -115,17 +120,17 @@@ msgstr "
  msgid "Add file(s)..."
  msgstr "Añadir fichero(s)..."
  
- #: src/wx/content_panel.cc:69
- msgid "Add folder..."
- msgstr "Añadir carpeta..."
+ #: src/wx/film_editor.cc:284
+ msgid ""
+ "Add image\n"
+ "sequence..."
+ msgstr ""
+ #: src/wx/film_editor.cc:281
+ msgid "Add video, image or sound files to the film."
+ msgstr ""
  
 -#: src/wx/editable_list.h:62
 +#: src/wx/config_dialog.cc:597 src/wx/editable_list.h:62
  msgid "Add..."
  msgstr "Añadir..."
  
@@@ -806,19 -772,10 +842,23 @@@ msgstr "Ninguno
  msgid "Off"
  msgstr "Off"
  
 +#: src/wx/config_dialog.cc:1167
 +msgid "Open console window"
 +msgstr ""
 +
 +#: src/wx/make_signer_chain_dialog.cc:25
 +#, fuzzy
 +msgid "Organisation"
 +msgstr "Duración"
 +
 +#: src/wx/make_signer_chain_dialog.cc:27
 +msgid "Organisational unit"
 +msgstr ""
 +
+ #: src/wx/film_editor.cc:301
+ msgid "Open the timeline for the film."
+ msgstr ""
  #: src/wx/screen_dialog.cc:65
  msgid "Other"
  msgstr "Otros"
@@@ -1376,24 -1272,9 +1424,6 @@@ msgstr "veces
  msgid "video"
  msgstr "vídeo"
  
- #~ msgid "1 channel"
- #~ msgstr "1 canal"
- #~ msgid "Audio channels"
- #~ msgstr "Canales de audio"
- #~ msgid "Could not decode video for view (%s)"
- #~ msgstr "No se pudo decodificar el vídeo para mostrarlo (%s)"
- #~ msgid "Hz"
- #~ msgstr "Hz"
- #~ msgid "With Subtitles"
- #~ msgstr "Con subtítulos"
- #~ msgid "channels"
- #~ msgstr "canales"
 -#~ msgid "Add folder..."
 -#~ msgstr "Añadir carpeta..."
--
  #~ msgid "Default creator"
  #~ msgstr "Creador por defecto"
  
index 46c4822d62be04e774b03a59a0e69521685bae8f,a4d26fd01e3ea005bdd49f159279e1815ac789a9..0ba92f95b83bb5463682135cc1b90bd45e2acdc6
@@@ -110,11 -114,17 +119,17 @@@ msgstr "
  msgid "Add file(s)..."
  msgstr "Ajout fichier(s)..."
  
- #: src/wx/content_panel.cc:69
- msgid "Add folder..."
- msgstr "Ajout dossier..."
+ #: src/wx/film_editor.cc:284
+ msgid ""
+ "Add image\n"
+ "sequence..."
+ msgstr ""
+ #: src/wx/film_editor.cc:281
+ msgid "Add video, image or sound files to the film."
+ msgstr ""
  
 -#: src/wx/editable_list.h:62
 +#: src/wx/config_dialog.cc:597 src/wx/editable_list.h:62
  msgid "Add..."
  msgstr "Ajouter..."
  
@@@ -798,19 -765,10 +835,23 @@@ msgstr "Aucun
  msgid "Off"
  msgstr "Eteint"
  
 +#: src/wx/config_dialog.cc:1167
 +msgid "Open console window"
 +msgstr ""
 +
 +#: src/wx/make_signer_chain_dialog.cc:25
 +#, fuzzy
 +msgid "Organisation"
 +msgstr "Durée"
 +
 +#: src/wx/make_signer_chain_dialog.cc:27
 +msgid "Organisational unit"
 +msgstr ""
 +
+ #: src/wx/film_editor.cc:301
+ msgid "Open the timeline for the film."
+ msgstr ""
  #: src/wx/screen_dialog.cc:65
  msgid "Other"
  msgstr "Autre"
@@@ -1359,24 -1256,9 +1408,6 @@@ msgstr "fois
  msgid "video"
  msgstr "vidéo"
  
- #~ msgid "1 channel"
- #~ msgstr "1 canal"
- #~ msgid "Audio channels"
- #~ msgstr "Canaux audios"
- #~ msgid "Could not decode video for view (%s)"
- #~ msgstr "Décodage de la vidéo pour visualisation impossible (%s)"
- #~ msgid "Hz"
- #~ msgstr "Hz"
- #~ msgid "With Subtitles"
- #~ msgstr "Avec sous-titres"
- #~ msgid "channels"
- #~ msgstr "canaux"
 -#~ msgid "Add folder..."
 -#~ msgstr "Ajout dossier..."
--
  #~ msgid "Default creator"
  #~ msgstr "Créateur par défaut"
  
index 35cb8db88a54ac8b805f07f29e2e98dfb5783df2,9dcce02d18b53603cfade8872a67afffc167560f..875be0ddf1c8efdb300dd64a6c5f4a9e765ab767
@@@ -109,11 -113,17 +118,17 @@@ msgstr "
  msgid "Add file(s)..."
  msgstr "Aggiungi File"
  
- #: src/wx/content_panel.cc:69
- msgid "Add folder..."
- msgstr "Aggiungi cartella"
+ #: src/wx/film_editor.cc:284
+ msgid ""
+ "Add image\n"
+ "sequence..."
+ msgstr ""
+ #: src/wx/film_editor.cc:281
+ msgid "Add video, image or sound files to the film."
+ msgstr ""
  
 -#: src/wx/editable_list.h:62
 +#: src/wx/config_dialog.cc:597 src/wx/editable_list.h:62
  msgid "Add..."
  msgstr "Aggiungi..."
  
@@@ -815,19 -782,10 +852,23 @@@ msgstr "Nessuno
  msgid "Off"
  msgstr ""
  
 +#: src/wx/config_dialog.cc:1167
 +msgid "Open console window"
 +msgstr ""
 +
 +#: src/wx/make_signer_chain_dialog.cc:25
 +#, fuzzy
 +msgid "Organisation"
 +msgstr "Durata"
 +
 +#: src/wx/make_signer_chain_dialog.cc:27
 +msgid "Organisational unit"
 +msgstr ""
 +
+ #: src/wx/film_editor.cc:301
+ msgid "Open the timeline for the film."
+ msgstr ""
  #: src/wx/screen_dialog.cc:65
  msgid "Other"
  msgstr ""
@@@ -1387,24 -1285,9 +1436,6 @@@ msgstr "
  msgid "video"
  msgstr "Video"
  
- #~ msgid "1 channel"
- #~ msgstr "1 canale"
- #~ msgid "Audio channels"
- #~ msgstr "Canali audio"
- #~ msgid "Could not decode video for view (%s)"
- #~ msgstr "Non posso decodificare il video per guardarlo (%s)"
- #~ msgid "Hz"
- #~ msgstr "Hz"
- #~ msgid "With Subtitles"
- #~ msgstr "Con sottotitoli"
- #~ msgid "channels"
- #~ msgstr "canali"
 -#~ msgid "Add folder..."
 -#~ msgstr "Aggiungi cartella"
--
  #, fuzzy
  #~ msgid "Default creator"
  #~ msgstr "Contenitore predefinito"
index e792f84be5cc6662db4909f5d11b9415486dafd9,509179bfb499eef4f7511a649e6fd01022292ee4..c4d3a7c2b9a6cbd48a956ba144c64c13b9acb2f6
@@@ -110,11 -114,17 +119,17 @@@ msgstr "
  msgid "Add file(s)..."
  msgstr "Voeg bestande(n) toe..."
  
- #: src/wx/content_panel.cc:69
- msgid "Add folder..."
- msgstr "Voeg map toe..."
+ #: src/wx/film_editor.cc:284
+ msgid ""
+ "Add image\n"
+ "sequence..."
+ msgstr ""
+ #: src/wx/film_editor.cc:281
+ msgid "Add video, image or sound files to the film."
+ msgstr ""
  
 -#: src/wx/editable_list.h:62
 +#: src/wx/config_dialog.cc:597 src/wx/editable_list.h:62
  msgid "Add..."
  msgstr "Toevoegen.."
  
@@@ -808,18 -774,10 +844,22 @@@ msgstr "Geen
  msgid "Off"
  msgstr "Uit"
  
 +#: src/wx/config_dialog.cc:1167
 +msgid "Open console window"
 +msgstr ""
 +
 +#: src/wx/make_signer_chain_dialog.cc:25
 +msgid "Organisation"
 +msgstr ""
 +
 +#: src/wx/make_signer_chain_dialog.cc:27
 +msgid "Organisational unit"
 +msgstr ""
 +
+ #: src/wx/film_editor.cc:301
+ msgid "Open the timeline for the film."
+ msgstr ""
  #: src/wx/screen_dialog.cc:65
  msgid "Other"
  msgstr "Andere"
@@@ -1366,24 -1264,9 +1414,6 @@@ msgstr "tijden
  msgid "video"
  msgstr "video"
  
- #~ msgid "1 channel"
- #~ msgstr "1 channel"
- #~ msgid "Audio channels"
- #~ msgstr "Audio kanalen"
- #~ msgid "Could not decode video for view (%s)"
- #~ msgstr "Kan video niet decoderen voor preview (%s)"
- #~ msgid "Hz"
- #~ msgstr "Hz"
- #~ msgid "With Subtitles"
- #~ msgstr "Met ondertiteling"
- #~ msgid "channels"
- #~ msgstr "kanalen"
 -#~ msgid "Add folder..."
 -#~ msgstr "Voeg map toe..."
--
  #~ msgid "Default creator"
  #~ msgstr "Standaard maker"
  
index 441643ccef459df953af7a562da4336cb24e434a,5670fc4cbce8d9ddd7393e5600be9797bea67da0..e52360abd14ded5941f92b1e7773cfa948323960
@@@ -111,11 -115,17 +120,17 @@@ msgstr "
  msgid "Add file(s)..."
  msgstr "Lägg till fil(er)..."
  
- #: src/wx/content_panel.cc:69
- msgid "Add folder..."
- msgstr "Lägg till folder..."
+ #: src/wx/film_editor.cc:284
+ msgid ""
+ "Add image\n"
+ "sequence..."
+ msgstr ""
+ #: src/wx/film_editor.cc:281
+ msgid "Add video, image or sound files to the film."
+ msgstr ""
  
 -#: src/wx/editable_list.h:62
 +#: src/wx/config_dialog.cc:597 src/wx/editable_list.h:62
  msgid "Add..."
  msgstr "Lägg till..."
  
@@@ -783,8 -747,16 +812,16 @@@ msgstr "JPEG2000-bandbredd
  msgid "Mbit/s"
  msgstr ""
  
+ #: src/wx/film_editor.cc:293
+ msgid "Move the selected piece of content earlier in the film."
+ msgstr ""
+ #: src/wx/film_editor.cc:297
+ msgid "Move the selected piece of content later in the film."
+ msgstr ""
  # Låter mysko
 -#: src/wx/video_panel.cc:280
 +#: src/wx/video_panel.cc:301
  msgid "Multiple content selected"
  msgstr "Flera innehåll valda"
  
@@@ -826,19 -793,10 +863,23 @@@ msgstr "Inget
  msgid "Off"
  msgstr "Av"
  
 +#: src/wx/config_dialog.cc:1167
 +msgid "Open console window"
 +msgstr ""
 +
 +#: src/wx/make_signer_chain_dialog.cc:25
 +#, fuzzy
 +msgid "Organisation"
 +msgstr "Längd"
 +
 +#: src/wx/make_signer_chain_dialog.cc:27
 +msgid "Organisational unit"
 +msgstr ""
 +
+ #: src/wx/film_editor.cc:301
+ msgid "Open the timeline for the film."
+ msgstr ""
  #: src/wx/screen_dialog.cc:65
  msgid "Other"
  msgstr ""
index 13baef6b7bb0c143021aeb67a97fe7dcc714127e,2e368e57d7b6373740efc865e895f0a0538aae79..556e6f1b3e08ca44c2108c27cd001a4cb02c2c29
@@@ -712,22 -644,19 +712,22 @@@ Timeline::set_position_from_event (wxMo
                        
                        {
                                /* Snap starts to ends */
 -                              Time const d = abs (cv->content()->end() - new_position);
 +                              DCPTime const d = DCPTime (cv->content()->end() - new_position).abs ();
                                if (first || d < nearest_distance) {
                                        nearest_distance = d;
-                                       nearest_new_position = cv->content()->end();
 -                                      nearest_new_position = cv->content()->end() + 1;
++                                      nearest_new_position = cv->content()->end() + DCPTime::delta ();
                                }
                        }
                        
                        {
                                /* Snap ends to starts */
 -                              Time const d = abs (cv->content()->position() - (new_position + _down_view->content()->length_after_trim()));
 +                              DCPTime const d = DCPTime (
 +                                      cv->content()->position() - (new_position + _down_view->content()->length_after_trim())
 +                                      ).abs ();
 +                              
                                if (d < nearest_distance) {
                                        nearest_distance = d;
-                                       nearest_new_position = cv->content()->position() - _down_view->content()->length_after_trim ();
 -                                      nearest_new_position = cv->content()->position() - _down_view->content()->length_after_trim () - 1;
++                                      nearest_new_position = cv->content()->position() - _down_view->content()->length_after_trim () - DCPTime::delta();
                                }
                        }
                        
index 8ac90b8def6994d0e3f49e566d0f963c77c74de9,bc3e8db9931d45ae7de3b39787df38aa409633c6..2da375ecdca76886a680429e40cda753bd153958
@@@ -29,9 -28,10 +29,10 @@@ using std::list
  using std::cout;
  using boost::shared_ptr;
  
 -TimelineDialog::TimelineDialog (FilmEditor* ed, shared_ptr<Film> film)
 -      : wxDialog (ed, wxID_ANY, _("Timeline"), wxDefaultPosition, wxSize (640, 512), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxFULL_REPAINT_ON_RESIZE)
 +TimelineDialog::TimelineDialog (ContentPanel* cp, shared_ptr<Film> film)
 +      : wxDialog (cp->panel(), wxID_ANY, _("Timeline"), wxDefaultPosition, wxSize (640, 512), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxFULL_REPAINT_ON_RESIZE)
+       , _film (film)
 -      , _timeline (this, ed, film)
 +      , _timeline (this, cp, film)
  {
        wxBoxSizer* sizer = new wxBoxSizer (wxVERTICAL);
  
Simple merge
index a8510cbbab38d4b3dd9776d268ffff24c5b13da0,eb0b812a5dd194c99130b206650e51bcc51bc399..569da6c8be5ed529308ff1d4f00ba9d1c37ea2d1
@@@ -150,25 -139,42 +150,26 @@@ VideoPanel::VideoPanel (ContentPanel* p
                &index_to_scale,
                &scale_to_index
                );
 -      _scale->add (grid, wxGBPosition (r, 1));
 +      _scale->add (grid, wxGBPosition (r, 1), wxGBSpan (1, 2));
        ++r;
  
 -      {
 -              add_label_to_grid_bag_sizer (grid, this, _("Filters"), true, wxGBPosition (r, 0));
 -              wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
 -
 -              wxClientDC dc (this);
 -              wxSize size = dc.GetTextExtent (wxT ("A quite long-ish name"));
 -              size.SetHeight (-1);
 -              
 -              _filters = new wxStaticText (this, wxID_ANY, _("None"), wxDefaultPosition, size);
 -              s->Add (_filters, 1, wxEXPAND | wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM | wxRIGHT, 6);
 -              _filters_button = new wxButton (this, wxID_ANY, _("Edit..."));
 -              s->Add (_filters_button, 0, wxALIGN_CENTER_VERTICAL);
 -              grid->Add (s, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
 -      }
 +      wxClientDC dc (this);
 +      wxSize size = dc.GetTextExtent (wxT ("A quite long name"));
 +      size.SetHeight (-1);
 +      
 +      add_label_to_grid_bag_sizer (grid, this, _("Filters"), true, wxGBPosition (r, 0));
 +      _filters = new wxStaticText (this, wxID_ANY, _("None"), wxDefaultPosition, size);
 +      grid->Add (_filters, wxGBPosition (r, 1), wxGBSpan (1, 2), wxALIGN_CENTER_VERTICAL);
 +      _filters_button = new wxButton (this, wxID_ANY, _("Edit..."));
 +      grid->Add (_filters_button, wxGBPosition (r, 3), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
        ++r;
        
-       add_label_to_grid_bag_sizer (grid, this, _("Colour conversion"), true, wxGBPosition (r, 0));
 -      {
 -              _enable_colour_conversion = new wxCheckBox (this, wxID_ANY, _("Colour conversion"));
 -              grid->Add (_enable_colour_conversion, wxGBPosition (r, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
 -
 -              wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
 -
 -              wxClientDC dc (this);
 -              wxSize size = dc.GetTextExtent (wxT ("A quite long-ish name"));
 -              size.SetHeight (-1);
 -              
 -              _colour_conversion = new wxStaticText (this, wxID_ANY, wxT (""), wxDefaultPosition, size);
 -
 -              s->Add (_colour_conversion, 1, wxEXPAND | wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM | wxRIGHT, 6);
 -              _colour_conversion_button = new wxButton (this, wxID_ANY, _("Edit..."));
 -              s->Add (_colour_conversion_button, 0, wxALIGN_CENTER_VERTICAL);
 -              grid->Add (s, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
 -      }
++      _enable_colour_conversion = new wxCheckBox (this, wxID_ANY, _("Colour conversion"));
++      grid->Add (_enable_colour_conversion, wxGBPosition (r, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
 +      _colour_conversion = new wxStaticText (this, wxID_ANY, wxT (""), wxDefaultPosition, size);
 +      grid->Add (_colour_conversion, wxGBPosition (r, 1), wxGBSpan (1, 2), wxALIGN_CENTER_VERTICAL);
 +      _colour_conversion_button = new wxButton (this, wxID_ANY, _("Edit..."));
 +      grid->Add (_colour_conversion_button, wxGBPosition (r, 3), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
        ++r;
  
        _description = new wxStaticText (this, wxID_ANY, wxT ("\n \n \n \n \n"), wxDefaultPosition, wxDefaultSize);
        _frame_type->wrapped()->Append (_("3D left only"));
        _frame_type->wrapped()->Append (_("3D right only"));
  
 +      _fade_in->Changed.connect (boost::bind (&VideoPanel::fade_in_changed, this));
 +      _fade_out->Changed.connect (boost::bind (&VideoPanel::fade_out_changed, this));
 +      
        _filters_button->Bind           (wxEVT_COMMAND_BUTTON_CLICKED,   boost::bind (&VideoPanel::edit_filters_clicked, this));
+       _enable_colour_conversion->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&VideoPanel::enable_colour_conversion_clicked, this));
        _colour_conversion_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED,   boost::bind (&VideoPanel::edit_colour_conversion_clicked, this));
  }
  
@@@ -407,20 -403,17 +425,35 @@@ VideoPanel::content_selection_changed (
        film_content_changed (FFmpegContentProperty::FILTERS);
  }
  
 -      VideoContentList vc = _editor->selected_video_content ();
 +void
 +VideoPanel::fade_in_changed ()
 +{
 +      VideoContentList vc = _parent->selected_video ();
 +      for (VideoContentList::const_iterator i = vc.begin(); i != vc.end(); ++i) {
 +              (*i)->set_fade_in (_fade_in->get (_parent->film()->video_frame_rate ()));
 +      }
 +}
 +
 +void
 +VideoPanel::fade_out_changed ()
 +{
 +      VideoContentList vc = _parent->selected_video ();
 +      for (VideoContentList::const_iterator i = vc.begin(); i != vc.end(); ++i) {
 +              (*i)->set_fade_out (_fade_out->get (_parent->film()->video_frame_rate ()));
 +      }
 +}
++
+ void
+ VideoPanel::enable_colour_conversion_clicked ()
+ {
++      VideoContentList vc = _parent->selected_video ();
+       if (vc.size() != 1) {
+               return;
+       }
+       if (_enable_colour_conversion->GetValue()) {
+               vc.front()->set_default_colour_conversion ();
+       } else {
+               vc.front()->unset_colour_conversion ();
+       }
+ }
index aa0c6ed531af796a4fdc54df2c4f83e8b3957262,16ecb7e2ed6ecec629d65f7d471b38a4bdc51d4c..28d6aa4bbf6b6d8118cd88784ce799066bd7157c
@@@ -45,9 -37,8 +45,10 @@@ public
  
  private:
        void edit_filters_clicked ();
+       void enable_colour_conversion_clicked ();
        void edit_colour_conversion_clicked ();
 +      void fade_in_changed ();
 +      void fade_out_changed ();
  
        void setup_description ();