Merge branch 'master' into 2.0
authorCarl Hetherington <cth@carlh.net>
Wed, 5 Mar 2014 16:20:23 +0000 (16:20 +0000)
committerCarl Hetherington <cth@carlh.net>
Wed, 5 Mar 2014 16:20:23 +0000 (16:20 +0000)
1  2 
src/lib/film.cc
src/lib/job.cc
src/lib/util.cc
src/lib/util.h
src/lib/wscript
src/wx/audio_mapping_view.cc
wscript

diff --combined src/lib/film.cc
index aecb389fd5e67b4a7b2cb9a01a1572196e4d7cd9,1b724b27edc025d60c549c9e5e2ad1b6ca54a605..21e7383bf94fcfbfd0635c7d1c0efe3c90ee2741
  #include <boost/date_time.hpp>
  #include <libxml++/libxml++.h>
  #include <libcxml/cxml.h>
 -#include <libdcp/signer_chain.h>
 -#include <libdcp/cpl.h>
 -#include <libdcp/signer.h>
 -#include <libdcp/util.h>
 -#include <libdcp/kdm.h>
 +#include <dcp/signer_chain.h>
 +#include <dcp/cpl.h>
 +#include <dcp/signer.h>
 +#include <dcp/util.h>
 +#include <dcp/kdm.h>
  #include "film.h"
  #include "job.h"
  #include "util.h"
@@@ -78,8 -78,8 +78,8 @@@ using boost::to_upper_copy
  using boost::ends_with;
  using boost::starts_with;
  using boost::optional;
 -using libdcp::Size;
 -using libdcp::Signer;
 +using dcp::Size;
 +using dcp::Signer;
  
  /* 5 -> 6
   * AudioMapping XML changed.
@@@ -397,6 -397,9 +397,9 @@@ Film::read_metadata (
        f.read_file (file ("metadata.xml"));
  
        _state_version = f.number_child<int> ("Version");
+       if (_state_version > current_state_version) {
+               throw StringError (_("This film was created with a newer version of DCP-o-matic, and it cannot be loaded into this version.  Sorry!"));
+       }
        
        _name = f.string_child ("Name");
        _use_dci_name = f.bool_child ("UseDCIName");
        _sequence_video = f.bool_child ("SequenceVideo");
        _three_d = f.bool_child ("ThreeD");
        _interop = f.bool_child ("Interop");
 -      _key = libdcp::Key (f.string_child ("Key"));
 +      _key = dcp::Key (f.string_child ("Key"));
        _playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist"), _state_version);
  
        _dirty = false;
@@@ -754,7 -757,7 +757,7 @@@ Film::j2c_path (int f, Eyes e, bool t) 
        return file (p);
  }
  
 -/** @return List of subdirectories (not full paths) containing DCPs that can be successfully libdcp::DCP::read() */
 +/** @return List of subdirectories (not full paths) containing DCPs that can be successfully dcp::DCP::read() */
  list<boost::filesystem::path>
  Film::dcps () const
  {
                        ) {
  
                        try {
 -                              libdcp::DCP dcp (*i);
 +                              dcp::DCP dcp (*i);
                                dcp.read ();
                                out.push_back (i->path().leaf ());
                        } catch (...) {
@@@ -863,7 -866,7 +866,7 @@@ Film::move_content_later (shared_ptr<Co
        _playlist->move_later (c);
  }
  
 -Time
 +DCPTime
  Film::length () const
  {
        return _playlist->length ();
@@@ -875,18 -878,12 +878,18 @@@ Film::has_subtitles () cons
        return _playlist->has_subtitles ();
  }
  
 -OutputVideoFrame
 +int
  Film::best_video_frame_rate () const
  {
        return _playlist->best_dcp_frame_rate ();
  }
  
 +FrameRateChange
 +Film::active_frame_rate_change (DCPTime t) const
 +{
 +      return _playlist->active_frame_rate_change (t, video_frame_rate ());
 +}
 +
  void
  Film::playlist_content_changed (boost::weak_ptr<Content> c, int p)
  {
@@@ -905,7 -902,31 +908,7 @@@ Film::playlist_changed (
        signal_changed (CONTENT);
  }     
  
 -OutputAudioFrame
 -Film::time_to_audio_frames (Time t) const
 -{
 -      return divide_with_round (t * audio_frame_rate (), TIME_HZ);
 -}
 -
 -OutputVideoFrame
 -Film::time_to_video_frames (Time t) const
 -{
 -      return divide_with_round (t * video_frame_rate (), TIME_HZ);
 -}
 -
 -Time
 -Film::audio_frames_to_time (OutputAudioFrame f) const
 -{
 -      return divide_with_round (f * TIME_HZ, audio_frame_rate ());
 -}
 -
 -Time
 -Film::video_frames_to_time (OutputVideoFrame f) const
 -{
 -      return divide_with_round (f * TIME_HZ, video_frame_rate ());
 -}
 -
 -OutputAudioFrame
 +int
  Film::audio_frame_rate () const
  {
        /* XXX */
@@@ -920,23 -941,23 +923,23 @@@ Film::set_sequence_video (bool s
        signal_changed (SEQUENCE_VIDEO);
  }
  
 -libdcp::Size
 +dcp::Size
  Film::full_frame () const
  {
        switch (_resolution) {
        case RESOLUTION_2K:
 -              return libdcp::Size (2048, 1080);
 +              return dcp::Size (2048, 1080);
        case RESOLUTION_4K:
 -              return libdcp::Size (4096, 2160);
 +              return dcp::Size (4096, 2160);
        }
  
        assert (false);
 -      return libdcp::Size ();
 +      return dcp::Size ();
  }
  
 -libdcp::KDM
 +dcp::KDM
  Film::make_kdm (
 -      shared_ptr<libdcp::Certificate> target,
 +      shared_ptr<dcp::Certificate> target,
        boost::filesystem::path dcp_dir,
        boost::posix_time::ptime from,
        boost::posix_time::ptime until
  {
        shared_ptr<const Signer> signer = make_signer ();
  
 -      libdcp::DCP dcp (dir (dcp_dir.string ()));
 +      dcp::DCP dcp (dir (dcp_dir.string ()));
        
        try {
                dcp.read ();
        
        time_t now = time (0);
        struct tm* tm = localtime (&now);
 -      string const issue_date = libdcp::tm_to_string (tm);
 +      string const issue_date = dcp::tm_to_string (tm);
        
        dcp.cpls().front()->set_mxf_keys (key ());
        
 -      return libdcp::KDM (dcp.cpls().front(), signer, target, from, until, "DCP-o-matic", issue_date);
 +      return dcp::KDM (dcp.cpls().front(), signer, target, from, until, "DCP-o-matic", issue_date);
  }
  
 -list<libdcp::KDM>
 +list<dcp::KDM>
  Film::make_kdms (
        list<shared_ptr<Screen> > screens,
        boost::filesystem::path dcp,
        boost::posix_time::ptime until
        ) const
  {
 -      list<libdcp::KDM> kdms;
 +      list<dcp::KDM> kdms;
  
        for (list<shared_ptr<Screen> >::iterator i = screens.begin(); i != screens.end(); ++i) {
                kdms.push_back (make_kdm ((*i)->certificate, dcp, from, until));
  uint64_t
  Film::required_disk_space () const
  {
 -      return uint64_t (j2k_bandwidth() / 8) * length() / TIME_HZ;
 +      return uint64_t (j2k_bandwidth() / 8) * length().seconds();
  }
  
  /** This method checks the disk that the Film is on and tries to decide whether or not
diff --combined src/lib/job.cc
index 01df2c570611cf90c2fa38a7aee41f142391725d,db9a9b215bdf74f3a6153dc7629516131ae00551..2ac8c60771b1c960850b4805ff1ca550fbb1cd3a
@@@ -23,7 -23,7 +23,7 @@@
  
  #include <boost/thread.hpp>
  #include <boost/filesystem.hpp>
 -#include <libdcp/exceptions.h>
 +#include <dcp/exceptions.h>
  #include "job.h"
  #include "util.h"
  #include "cross.h"
@@@ -66,7 -66,7 +66,7 @@@ Job::run_wrapper (
  
                run ();
  
 -      } catch (libdcp::FileError& e) {
 +      } catch (dcp::FileError& e) {
                
                string m = String::compose (_("An error occurred whilst handling the file %1."), boost::filesystem::path (e.filename()).leaf());
  
@@@ -186,25 -186,36 +186,36 @@@ Job::paused () cons
  void
  Job::set_state (State s)
  {
-       bool finished = false;
+       bool const finished = (s == FINISHED_OK || s == FINISHED_ERROR || s == FINISHED_CANCELLED);
        
+       /* Do this first, so that we handle things that should happen on finish before the
+        * job is actually marked as such.  This is important for callers that do:
+        *
+        * while (JobManager::work_to_do ()) {
+        *   ui_signaller->ui_idle ();
+        * }
+        *
+        * as otherwise this loop can finish before the Finished handler has been executed
+        * (job finishes, calls set_state(), this sets the state and sets a pending signal
+        * for Finished, but this is never called as a ui_idle() never happens as work_to_do()
+        * is now false).
+        */
+       if (finished && ui_signaller) {
+               ui_signaller->emit (boost::bind (boost::ref (Finished)));
+       }
        {
                boost::mutex::scoped_lock lm (_state_mutex);
                _state = s;
  
-               if (_state == FINISHED_OK || _state == FINISHED_ERROR || _state == FINISHED_CANCELLED) {
+               if (finished) {
                        _ran_for = elapsed_time ();
-                       finished = true;
                        _sub_name.clear ();
                }
        }
-       if (finished && ui_signaller) {
-               ui_signaller->emit (boost::bind (boost::ref (Finished)));
-       }
  }
  
 -/** @return Time (in seconds) that this sub-job has been running */
 +/** @return DCPTime (in seconds) that this sub-job has been running */
  int
  Job::elapsed_time () const
  {
diff --combined src/lib/util.cc
index e8f83d4e4d45a21fc524006b7f155addb683799f,35385ab40be03ff67260993352629ec84ab1f1b3..15109eee05c442f0dab35982703e20e788148f79
  #include <openssl/md5.h>
  #include <magick/MagickCore.h>
  #include <magick/version.h>
 -#include <libdcp/version.h>
 -#include <libdcp/util.h>
 -#include <libdcp/signer_chain.h>
 -#include <libdcp/signer.h>
 +#include <pangomm/init.h>
 +#include <dcp/version.h>
 +#include <dcp/util.h>
 +#include <dcp/signer_chain.h>
 +#include <dcp/signer.h>
  extern "C" {
  #include <libavcodec/avcodec.h>
  #include <libavformat/avformat.h>
@@@ -103,7 -102,7 +103,7 @@@ using boost::shared_ptr
  using boost::thread;
  using boost::lexical_cast;
  using boost::optional;
 -using libdcp::Size;
 +using dcp::Size;
  
  static boost::thread::id ui_thread;
  static boost::filesystem::path backtrace_file;
@@@ -253,7 -252,7 +253,7 @@@ dependency_version_summary (
          << N_("libswscale ") << ffmpeg_version_to_string (swscale_version()) << N_(", ")
          << MagickVersion << N_(", ")
          << N_("libssh ") << ssh_version (0) << N_(", ")
 -        << N_("libdcp ") << libdcp::version << N_(" git ") << libdcp::git_commit;
 +        << N_("libdcp ") << dcp::version << N_(" git ") << dcp::git_commit;
  
        return s.str ();
  }
@@@ -344,8 -343,7 +344,8 @@@ dcpomatic_setup (
  
        set_terminate (terminate);
  
 -      libdcp::init ();
 +      Pango::init ();
 +      dcp::init ();
        
        Ratio::setup_ratios ();
        VideoContentScale::setup_scales ();
@@@ -494,6 -492,33 +494,6 @@@ md5_digest (vector<boost::filesystem::p
        return s.str ();
  }
  
 -static bool
 -about_equal (float a, float b)
 -{
 -      /* A film of F seconds at f FPS will be Ff frames;
 -         Consider some delta FPS d, so if we run the same
 -         film at (f + d) FPS it will last F(f + d) seconds.
 -
 -         Hence the difference in length over the length of the film will
 -         be F(f + d) - Ff frames
 -          = Ff + Fd - Ff frames
 -          = Fd frames
 -          = Fd/f seconds
 - 
 -         So if we accept a difference of 1 frame, ie 1/f seconds, we can
 -         say that
 -
 -         1/f = Fd/f
 -      ie 1 = Fd
 -      ie d = 1/F
 - 
 -         So for a 3hr film, ie F = 3 * 60 * 60 = 10800, the acceptable
 -         FPS error is 1/F ~= 0.0001 ~= 10-e4
 -      */
 -
 -      return (fabs (a - b) < 1e-4);
 -}
 -
  /** @param An arbitrary audio frame rate.
   *  @return The appropriate DCP-approved frame rate (48kHz or 96kHz).
   */
@@@ -753,10 -778,21 +753,10 @@@ ensure_ui_thread (
        assert (boost::this_thread::get_id() == ui_thread);
  }
  
 -/** @param v Content video frame.
 - *  @param audio_sample_rate Source audio sample rate.
 - *  @param frames_per_second Number of video frames per second.
 - *  @return Equivalent number of audio frames for `v'.
 - */
 -int64_t
 -video_frames_to_audio_frames (VideoContent::Frame v, float audio_sample_rate, float frames_per_second)
 -{
 -      return ((int64_t) v * audio_sample_rate / frames_per_second);
 -}
 -
  string
  audio_channel_name (int c)
  {
-       assert (MAX_AUDIO_CHANNELS == 8);
+       assert (MAX_AUDIO_CHANNELS == 12);
  
        /* TRANSLATORS: these are the names of audio channels; Lfe (sub) is the low-frequency
           enhancement channel (sub-woofer).  HI is the hearing-impaired audio track and
                _("Lfe (sub)"),
                _("Left surround"),
                _("Right surround"),
-               _("HI"),
-               _("VI")
+               _("Hearing impaired"),
+               _("Visually impaired"),
+               _("Left centre"),
+               _("Right centre"),
+               _("Left rear surround"),
+               _("Right rear surround"),
        };
  
        return channels[c];
  }
  
 -FrameRateConversion::FrameRateConversion (float source, int dcp)
 -      : skip (false)
 -      , repeat (1)
 -      , change_speed (false)
 -{
 -      if (fabs (source / 2.0 - dcp) < fabs (source - dcp)) {
 -              /* The difference between source and DCP frame rate will be lower
 -                 (i.e. better) if we skip.
 -              */
 -              skip = true;
 -      } else if (fabs (source * 2 - dcp) < fabs (source - dcp)) {
 -              /* The difference between source and DCP frame rate would be better
 -                 if we repeated each frame once; it may be better still if we
 -                 repeated more than once.  Work out the required repeat.
 -              */
 -              repeat = round (dcp / source);
 -      }
 -
 -      change_speed = !about_equal (source * factor(), dcp);
 -
 -      if (!skip && repeat == 1 && !change_speed) {
 -              description = _("Content and DCP have the same rate.\n");
 -      } else {
 -              if (skip) {
 -                      description = _("DCP will use every other frame of the content.\n");
 -              } else if (repeat == 2) {
 -                      description = _("Each content frame will be doubled in the DCP.\n");
 -              } else if (repeat > 2) {
 -                      description = String::compose (_("Each content frame will be repeated %1 more times in the DCP.\n"), repeat - 1);
 -              }
 -
 -              if (change_speed) {
 -                      float const pc = dcp * 100 / (source * factor());
 -                      description += String::compose (_("DCP will run at %1%% of the content speed.\n"), pc);
 -              }
 -      }
 -}
 -
  LocaleGuard::LocaleGuard ()
        : _old (0)
  {
@@@ -818,7 -896,7 +822,7 @@@ tidy_for_filename (string f
        return t;
  }
  
 -shared_ptr<const libdcp::Signer>
 +shared_ptr<const dcp::Signer>
  make_signer ()
  {
        boost::filesystem::path const sd = Config::instance()->signer_chain_directory ();
                if (!boost::filesystem::exists (p)) {
                        boost::filesystem::remove_all (sd);
                        boost::filesystem::create_directories (sd);
 -                      libdcp::make_signer_chain (sd, openssl_path ());
 +                      dcp::make_signer_chain (sd, openssl_path ());
                        break;
                }
  
                ++i;
        }
        
 -      libdcp::CertificateChain chain;
 +      dcp::CertificateChain chain;
  
        {
                boost::filesystem::path p (sd);
                p /= "ca.self-signed.pem";
 -              chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (p)));
 +              chain.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (p)));
        }
  
        {
                boost::filesystem::path p (sd);
                p /= "intermediate.signed.pem";
 -              chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (p)));
 +              chain.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (p)));
        }
  
        {
                boost::filesystem::path p (sd);
                p /= "leaf.signed.pem";
 -              chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (p)));
 +              chain.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (p)));
        }
  
        boost::filesystem::path signer_key (sd);
        signer_key /= "leaf.key";
  
 -      return shared_ptr<const libdcp::Signer> (new libdcp::Signer (chain, signer_key));
 +      return shared_ptr<const dcp::Signer> (new dcp::Signer (chain, signer_key));
  }
  
  map<string, string>
@@@ -917,14 -995,14 +921,14 @@@ split_get_request (string url
        return r;
  }
  
 -libdcp::Size
 -fit_ratio_within (float ratio, libdcp::Size full_frame)
 +dcp::Size
 +fit_ratio_within (float ratio, dcp::Size full_frame)
  {
        if (ratio < full_frame.ratio ()) {
 -              return libdcp::Size (rint (full_frame.height * ratio), full_frame.height);
 +              return dcp::Size (rint (full_frame.height * ratio), full_frame.height);
        }
        
 -      return libdcp::Size (full_frame.width, rint (full_frame.width / ratio));
 +      return dcp::Size (full_frame.width, rint (full_frame.width / ratio));
  }
  
  void *
diff --combined src/lib/util.h
index d91a6b435d55843522d538657a544314f98bb7ca,c056808596438567d708c8335889ad2fe521c927..2ae97814cf77726377a4f187c6e2e32d9c186435
@@@ -31,8 -31,7 +31,8 @@@
  #include <boost/asio.hpp>
  #include <boost/optional.hpp>
  #include <boost/filesystem.hpp>
 -#include <libdcp/util.h>
 +#include <dcp/util.h>
 +#include <dcp/signer.h>
  extern "C" {
  #include <libavcodec/avcodec.h>
  #include <libavfilter/avfilter.h>
@@@ -50,7 -49,7 +50,7 @@@
  #undef check
  
  /** The maximum number of audio channels that we can cope with */
- #define MAX_AUDIO_CHANNELS 8
+ #define MAX_AUDIO_CHANNELS 12
  
  #define DCPOMATIC_HELLO "Boys, you gotta learn not to talk to nuns that way"
  
@@@ -77,10 -76,44 +77,10 @@@ extern bool valid_image_file (boost::fi
  extern boost::filesystem::path mo_path ();
  #endif
  extern std::string tidy_for_filename (std::string);
 -extern boost::shared_ptr<const libdcp::Signer> make_signer ();
 -extern libdcp::Size fit_ratio_within (float ratio, libdcp::Size);
 +extern boost::shared_ptr<const dcp::Signer> make_signer ();
 +extern dcp::Size fit_ratio_within (float ratio, dcp::Size);
  extern std::string entities_to_text (std::string e);
  extern std::map<std::string, std::string> split_get_request (std::string url);
 -
 -struct FrameRateConversion
 -{
 -      FrameRateConversion (float, int);
 -
 -      /** @return factor by which to multiply a source frame rate
 -          to get the effective rate after any skip or repeat has happened.
 -      */
 -      float factor () const {
 -              if (skip) {
 -                      return 0.5;
 -              }
 -
 -              return repeat;
 -      }
 -
 -      /** true to skip every other frame */
 -      bool skip;
 -      /** number of times to use each frame (e.g. 1 is normal, 2 means repeat each frame once, and so on) */
 -      int repeat;
 -      /** true if this DCP will run its video faster or slower than the source
 -       *  without taking into account `repeat' nor `skip'.
 -       *  (e.g. change_speed will be true if
 -       *          source is 29.97fps, DCP is 30fps
 -       *          source is 14.50fps, DCP is 30fps
 -       *  but not if
 -       *          source is 15.00fps, DCP is 30fps
 -       *          source is 12.50fps, DCP is 25fps)
 -       */
 -      bool change_speed;
 -
 -      std::string description;
 -};
 -
  extern int dcp_audio_frame_rate (int);
  extern int stride_round_up (int, int const *, int);
  extern std::multimap<std::string, std::string> read_key_value (std::istream& s);
@@@ -131,6 -164,8 +131,6 @@@ private
        int _timeout;
  };
  
 -extern int64_t video_frames_to_audio_frames (VideoContent::Frame v, float audio_sample_rate, float frames_per_second);
 -
  class LocaleGuard
  {
  public:
diff --combined src/lib/wscript
index 16b5aafe4d2c7c9e684db7c80f17cb60f8d9bede,7c9712ff8f74c3f7f4b83144ac0bb69a3dd23839..5d27cfe45317d68df9c8e27dda6ea07bb2a0d173
@@@ -8,7 -8,6 +8,7 @@@ sources = ""
            audio_content.cc
            audio_decoder.cc
            audio_mapping.cc
 +          audio_merger.cc
            cinema.cc
            colour_conversion.cc
            config.cc
@@@ -18,7 -17,6 +18,7 @@@
            dci_metadata.cc
            dcp_content_type.cc
            dcp_video_frame.cc
 +          dcpomatic_time.cc
            decoder.cc
            dolby_cp750.cc
            encoder.cc
@@@ -32,7 -30,6 +32,7 @@@
            ffmpeg_examiner.cc
            film.cc
            filter.cc
 +          frame_rate_change.cc
            image.cc
            image_content.cc
            image_decoder.cc
@@@ -45,7 -42,6 +45,7 @@@
            player.cc
            playlist.cc
            ratio.cc
 +          render_subtitles.cc
            resampler.cc
            scp_dcp_job.cc
            scaler.cc
@@@ -55,9 -51,6 +55,9 @@@
            sndfile_content.cc
            sndfile_decoder.cc
            sound_processor.cc
 +          subrip.cc
 +          subrip_content.cc
 +          subrip_decoder.cc
            subtitle_content.cc
            subtitle_decoder.cc
            timer.cc
@@@ -84,9 -77,12 +84,12 @@@ def build(bld)
                   AVCODEC AVUTIL AVFORMAT AVFILTER SWSCALE SWRESAMPLE 
                   BOOST_FILESYSTEM BOOST_THREAD BOOST_DATETIME BOOST_SIGNALS2
                   SNDFILE OPENJPEG POSTPROC TIFF MAGICK SSH DCP CXML GLIB LZMA XML++
 -                 CURL ZIP QUICKMAIL
 +                 CURL ZIP QUICKMAIL PANGOMM CAIROMM
                   """
  
+     if bld.env.TARGET_OSX:
+         obj.framework = ['IOKit', 'Foundation']
      obj.source = sources + ' version.cc'
  
      if bld.env.TARGET_WINDOWS:
index 0b28b12fb641201ca438c71fff61330951666f15,7fdecb8d52a8dc9d3cee8ff54e8781b68b3ca422..52303ac14b2e9b94996bbf8950f42e3bf4458abc
@@@ -20,7 -20,7 +20,7 @@@
  #include <wx/wx.h>
  #include <wx/renderer.h>
  #include <wx/grid.h>
 -#include <libdcp/types.h>
 +#include <dcp/types.h>
  #include "lib/audio_mapping.h"
  #include "lib/util.h"
  #include "audio_mapping_view.h"
@@@ -34,7 -34,7 +34,7 @@@ using std::max
  using boost::shared_ptr;
  using boost::lexical_cast;
  
- #define INDICATOR_SIZE 20
+ #define INDICATOR_SIZE 16
  
  enum {
        ID_off = 1,
@@@ -156,7 -156,7 +156,7 @@@ AudioMappingView::left_click (wxGridEve
                return;
        }
  
 -      libdcp::Channel d = static_cast<libdcp::Channel> (ev.GetCol() - 1);
 +      dcp::Channel d = static_cast<dcp::Channel> (ev.GetCol() - 1);
        
        if (_map.get (ev.GetRow(), d) > 0) {
                _map.set (ev.GetRow(), d, 0);
@@@ -182,28 -182,28 +182,28 @@@ AudioMappingView::right_click (wxGridEv
  void
  AudioMappingView::off ()
  {
 -      _map.set (_menu_row, static_cast<libdcp::Channel> (_menu_column - 1), 0);
 +      _map.set (_menu_row, static_cast<dcp::Channel> (_menu_column - 1), 0);
        map_changed ();
  }
  
  void
  AudioMappingView::full ()
  {
 -      _map.set (_menu_row, static_cast<libdcp::Channel> (_menu_column - 1), 1);
 +      _map.set (_menu_row, static_cast<dcp::Channel> (_menu_column - 1), 1);
        map_changed ();
  }
  
  void
  AudioMappingView::minus3dB ()
  {
 -      _map.set (_menu_row, static_cast<libdcp::Channel> (_menu_column - 1), 1 / sqrt (2));
 +      _map.set (_menu_row, static_cast<dcp::Channel> (_menu_column - 1), 1 / sqrt (2));
        map_changed ();
  }
  
  void
  AudioMappingView::edit ()
  {
 -      libdcp::Channel d = static_cast<libdcp::Channel> (_menu_column - 1);
 +      dcp::Channel d = static_cast<dcp::Channel> (_menu_column - 1);
        
        AudioGainDialog* dialog = new AudioGainDialog (this, _menu_row, _menu_column - 1, _map.get (_menu_row, d));
        if (dialog->ShowModal () == wxID_OK) {
@@@ -242,7 -242,7 +242,7 @@@ AudioMappingView::update_cells (
                _grid->SetCellValue (i, 0, wxString::Format (wxT("%d"), i + 1));
  
                for (int j = 1; j < _grid->GetNumberCols(); ++j) {
 -                      _grid->SetCellValue (i, j, std_to_wx (lexical_cast<string> (_map.get (i, static_cast<libdcp::Channel> (j - 1)))));
 +                      _grid->SetCellValue (i, j, std_to_wx (lexical_cast<string> (_map.get (i, static_cast<dcp::Channel> (j - 1)))));
                }
        }
  
@@@ -270,9 -270,9 +270,9 @@@ AudioMappingView::set_column_labels (
  {
        int const c = _grid->GetNumberCols ();
        
-       _grid->SetColLabelValue (0, _("Content channel"));
+       _grid->SetColLabelValue (0, _("Content"));
  
- #if MAX_AUDIO_CHANNELS != 8
+ #if MAX_AUDIO_CHANNELS != 12
  #warning AudioMappingView::set_column_labels() is expecting the wrong MAX_AUDIO_CHANNELS
  #endif        
        
        if (c > 7) {
                _grid->SetColLabelValue (8, _("VI"));
        }
-       
+       if (c > 8) {
+               _grid->SetColLabelValue (9, _("Lc"));
+       }
+       if (c > 9) {
+               _grid->SetColLabelValue (10, _("Rc"));
+       }
+       if (c > 10) {
+               _grid->SetColLabelValue (11, _("BsL"));
+       }
+       if (c > 11) {
+               _grid->SetColLabelValue (12, _("BsR"));
+       }
        _grid->AutoSize ();
  }
  
@@@ -330,7 -346,7 +346,7 @@@ AudioMappingView::mouse_moved (wxMouseE
        if (row != _last_tooltip_row || column != _last_tooltip_column) {
  
                wxString s;
 -              float const gain = _map.get (row, static_cast<libdcp::Channel> (column - 1));
 +              float const gain = _map.get (row, static_cast<dcp::Channel> (column - 1));
                if (gain == 0) {
                        s = wxString::Format (_("No audio will be passed from content channel %d to DCP channel %d."), row + 1, column);
                } else if (gain == 1) {
diff --combined wscript
index 8027ea88c086f8d93a6501737a8ce8fddedb3934,28de19e9c37b1730e5f04cac18451d03939dd408..3a7920bd7989585f3508056e7073f09dd41c76e5
+++ b/wscript
@@@ -3,11 -3,7 +3,11 @@@ import o
  import sys
  
  APPNAME = 'dcpomatic'
 +<<<<<<< HEAD
 +VERSION = '2.0.0devel'
 +=======
  VERSION = '1.64.18devel'
 +>>>>>>> master
  
  def options(opt):
      opt.load('compiler_cxx')
@@@ -59,9 -55,9 +59,9 @@@ def dynamic_openjpeg(conf)
      conf.check_cfg(package='libopenjpeg', args='--cflags --libs', max_version='1.5.1', mandatory=True)
  
  def static_dcp(conf, static_boost, static_xmlpp, static_xmlsec, static_ssh):
 -    conf.check_cfg(package='libdcp', atleast_version='0.92', args='--cflags', uselib_store='DCP', mandatory=True)
 +    conf.check_cfg(package='libdcp-1.0', atleast_version='0.92', args='--cflags', uselib_store='DCP', mandatory=True)
      conf.env.DEFINES_DCP = [f.replace('\\', '') for f in conf.env.DEFINES_DCP]
 -    conf.env.STLIB_DCP = ['dcp', 'asdcp-libdcp', 'kumu-libdcp']
 +    conf.env.STLIB_DCP = ['dcp-1.0', 'asdcp-libdcp', 'kumu-libdcp']
      conf.env.LIB_DCP = ['glibmm-2.4', 'ssl', 'crypto', 'bz2', 'xslt']
  
      if static_boost:
@@@ -85,7 -81,7 +85,7 @@@
          conf.env.LIB_DCP.append('ssh')
  
  def dynamic_dcp(conf):
 -    conf.check_cfg(package='libdcp', atleast_version='0.92', args='--cflags --libs', uselib_store='DCP', mandatory=True)
 +    conf.check_cfg(package='libdcp-1.0', atleast_version='0.92', args='--cflags --libs', uselib_store='DCP', mandatory=True)
      conf.env.DEFINES_DCP = [f.replace('\\', '') for f in conf.env.DEFINES_DCP]
  
  def dynamic_ssh(conf):
@@@ -179,7 -175,7 +179,7 @@@ def configure(conf)
          conf.env.INSTALL_PREFIX = conf.options.install_prefix
  
      # Common CXXFLAGS
-     conf.env.append_value('CXXFLAGS', ['-D__STDC_CONSTANT_MACROS', '-D__STDC_LIMIT_MACROS', '-msse', '-mfpmath=sse', '-ffast-math', '-fno-strict-aliasing',
+     conf.env.append_value('CXXFLAGS', ['-D__STDC_CONSTANT_MACROS', '-D__STDC_LIMIT_MACROS', '-msse', '-ffast-math', '-fno-strict-aliasing',
                                         '-Wall', '-Wno-attributes', '-Wextra', '-D_FILE_OFFSET_BITS=64'])
  
      if conf.options.enable_debug:
  
      # Windows
      if conf.env.TARGET_WINDOWS:
-         conf.env.append_value('CXXFLAGS', ['-DDCPOMATIC_WINDOWS', '-DWIN32_LEAN_AND_MEAN', '-DBOOST_USE_WINDOWS_H', '-DUNICODE', '-DBOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN'])
+         conf.env.append_value('CXXFLAGS', '-DDCPOMATIC_WINDOWS')
+         conf.env.append_value('CXXFLAGS', '-DWIN32_LEAN_AND_MEAN')
+         conf.env.append_value('CXXFLAGS', '-DBOOST_USE_WINDOWS_H')
+         conf.env.append_value('CXXFLAGS', '-DUNICODE')
+         conf.env.append_value('CXXFLAGS', '-DBOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN')
+         conf.env.append_value('CXXFLAGS', '-mfpmath=sse')
          wxrc = os.popen('wx-config --rescomp').read().split()[1:]
          conf.env.append_value('WINRCFLAGS', wxrc)
          if conf.options.enable_debug:
  
      # Linux
      if conf.env.TARGET_LINUX:
+         conf.env.append_value('CXXFLAGS', '-mfpmath=sse')
          conf.env.append_value('CXXFLAGS', '-DDCPOMATIC_LINUX')
  
      if conf.env.TARGET_DEBIAN:
  
      # OSX
      if conf.env.TARGET_OSX:
-         conf.env.append_value('CXXFLAGS', '-DDCPOMATIC_OSX')
+         conf.env.append_value('CXXFLAGS', ['-DDCPOMATIC_OSX', '-Wno-unused-function', '-Wno-unused-parameter'])
          conf.env.append_value('LINKFLAGS', '-headerpad_max_install_names')
  
      #
      conf.check_cfg(package='glib-2.0', args='--cflags --libs', uselib_store='GLIB', mandatory=True)
      conf.check_cfg(package= '', path=conf.options.magickpp_config, args='--cppflags --cxxflags --libs', uselib_store='MAGICK', mandatory=True)
      conf.check_cfg(package='libzip', args='--cflags --libs', uselib_store='ZIP', mandatory=True)
 +    conf.check_cfg(package='pangomm-1.4', args='--cflags --libs', uselib_store='PANGOMM', mandatory=True)
 +    conf.check_cfg(package='cairomm-1.0', args='--cflags --libs', uselib_store='CAIROMM', mandatory=True)
  
      conf.check_cc(fragment="""
                             #include <glib.h>