Basics of subtitle split.
[dcpomatic.git] / src / lib / dcp_content.cc
index c072dfa3d115a50b3774efaecf76ff536f9bac41..81068262b9fc87a5e312d12bfe95a9c4348c7ac8 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2014-2015 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2014-2016 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
@@ -18,6 +18,7 @@
 */
 
 #include "dcp_content.h"
+#include "video_content.h"
 #include "dcp_examiner.h"
 #include "job.h"
 #include "film.h"
@@ -25,6 +26,7 @@
 #include "overlaps.h"
 #include "compose.hpp"
 #include "dcp_decoder.h"
+#include "subtitle_content.h"
 #include <dcp/dcp.h>
 #include <dcp/exceptions.h>
 #include <dcp/reel_picture_asset.h>
@@ -52,9 +54,7 @@ int const DCPContentProperty::REFERENCE_SUBTITLE = 603;
 
 DCPContent::DCPContent (shared_ptr<const Film> film, boost::filesystem::path p)
        : Content (film)
-       , VideoContent (film)
        , SingleStreamAudioContent (film)
-       , SubtitleContent (film)
        , _has_subtitles (false)
        , _encrypted (false)
        , _kdm_valid (false)
@@ -62,15 +62,20 @@ DCPContent::DCPContent (shared_ptr<const Film> film, boost::filesystem::path p)
        , _reference_audio (false)
        , _reference_subtitle (false)
 {
+       video.reset (new VideoContent (this, film));
+       subtitle.reset (new SubtitleContent (this, film));
+
        read_directory (p);
+       set_default_colour_conversion ();
 }
 
 DCPContent::DCPContent (shared_ptr<const Film> film, cxml::ConstNodePtr node, int version)
        : Content (film, node)
-       , VideoContent (film, node, version)
        , SingleStreamAudioContent (film, node, version)
-       , SubtitleContent (film, node, version)
 {
+       video.reset (new VideoContent (this, film, node, version));
+       subtitle.reset (new SubtitleContent (this, film, node, version));
+
        _name = node->string_child ("Name");
        _has_subtitles = node->bool_child ("HasSubtitles");
        _encrypted = node->bool_child ("Encrypted");
@@ -104,7 +109,8 @@ DCPContent::examine (shared_ptr<Job> job)
        Content::examine (job);
 
        shared_ptr<DCPExaminer> examiner (new DCPExaminer (shared_from_this ()));
-       take_from_video_examiner (examiner);
+       video->take_from_video_examiner (examiner);
+       set_default_colour_conversion ();
        take_from_audio_examiner (examiner);
 
        {
@@ -131,7 +137,7 @@ string
 DCPContent::technical_summary () const
 {
        return Content::technical_summary() + " - "
-               + VideoContent::technical_summary() + " - "
+               + video->technical_summary() + " - "
                + AudioContent::technical_summary() + " - ";
 }
 
@@ -141,9 +147,9 @@ DCPContent::as_xml (xmlpp::Node* node) const
        node->add_child("Type")->add_child_text ("DCP");
 
        Content::as_xml (node);
-       VideoContent::as_xml (node);
+       video->as_xml (node);
        SingleStreamAudioContent::as_xml (node);
-       SubtitleContent::as_xml (node);
+       subtitle->as_xml (node);
 
        boost::mutex::scoped_lock lm (_mutex);
        node->add_child("Name")->add_child_text (_name);
@@ -161,17 +167,15 @@ DCPContent::as_xml (xmlpp::Node* node) const
 DCPTime
 DCPContent::full_length () const
 {
-       shared_ptr<const Film> film = _film.lock ();
-       DCPOMATIC_ASSERT (film);
-       FrameRateChange const frc (video_frame_rate (), film->video_frame_rate ());
-       return DCPTime::from_frames (llrint (video_length () * frc.factor ()), film->video_frame_rate ());
+       FrameRateChange const frc (video->video_frame_rate (), film()->video_frame_rate ());
+       return DCPTime::from_frames (llrint (video->video_length () * frc.factor ()), film()->video_frame_rate ());
 }
 
 string
 DCPContent::identifier () const
 {
        SafeStringStream s;
-       s << VideoContent::identifier() << "_" << SubtitleContent::identifier () << " "
+       s << Content::identifier() << "_" << video->identifier() << "_" << subtitle->identifier () << " "
          << (_reference_video ? "1" : "0")
          << (_reference_subtitle ? "1" : "0");
        return s.str ();
@@ -207,7 +211,7 @@ DCPContent::directory () const
 }
 
 void
-DCPContent::add_properties (list<pair<string, string> >& p) const
+DCPContent::add_properties (list<UserProperty>& p) const
 {
        SingleStreamAudioContent::add_properties (p);
 }
@@ -216,7 +220,7 @@ void
 DCPContent::set_default_colour_conversion ()
 {
        /* Default to no colour conversion for DCPs */
-       unset_colour_conversion ();
+       video->unset_colour_conversion ();
 }
 
 void
@@ -258,7 +262,7 @@ DCPContent::reels () const
        list<DCPTimePeriod> p;
        scoped_ptr<DCPDecoder> decoder;
        try {
-               decoder.reset (new DCPDecoder (shared_from_this(), false));
+               decoder.reset (new DCPDecoder (shared_from_this(), film()->log(), false));
        } catch (...) {
                /* Could not load the DCP; guess reels */
                list<DCPTimePeriod> p;
@@ -266,11 +270,9 @@ DCPContent::reels () const
                return p;
        }
 
-       shared_ptr<const Film> film = _film.lock ();
-       DCPOMATIC_ASSERT (film);
        DCPTime from = position ();
        BOOST_FOREACH (shared_ptr<dcp::Reel> i, decoder->reels()) {
-               DCPTime const to = from + DCPTime::from_frames (i->main_picture()->duration(), film->video_frame_rate());
+               DCPTime const to = from + DCPTime::from_frames (i->main_picture()->duration(), film()->video_frame_rate());
                p.push_back (DCPTimePeriod (from, to));
                from = to;
        }
@@ -292,21 +294,18 @@ template <class T>
 bool
 DCPContent::can_reference (string overlapping, list<string>& why_not) const
 {
-       shared_ptr<const Film> film = _film.lock ();
-       DCPOMATIC_ASSERT (film);
-
-       list<DCPTimePeriod> const fr = film->reels ();
+       list<DCPTimePeriod> const fr = film()->reels ();
        /* fr must contain reels().  It can also contain other reels, but it must at
           least contain reels().
        */
        BOOST_FOREACH (DCPTimePeriod i, reels()) {
                if (find (fr.begin(), fr.end(), i) == fr.end ()) {
-                       why_not.push_back (_("Reel lengths in the project differ from those in the DCP; set the reel mode to `split by video content'."));
+                       why_not.push_back (_("Reel lengths in the project differ from those in the DCP; set the reel mode to 'split by video content'."));
                        return false;
                }
        }
 
-       list<shared_ptr<T> > a = overlaps<T> (film->content(), position(), end());
+       list<shared_ptr<T> > a = overlaps<T> (film()->content(), position(), end());
        if (a.size() != 1 || a.front().get() != this) {
                why_not.push_back (overlapping);
                return false;
@@ -318,17 +317,33 @@ DCPContent::can_reference (string overlapping, list<string>& why_not) const
 bool
 DCPContent::can_reference_video (list<string>& why_not) const
 {
-       return can_reference<VideoContent> (_("There is other video content overlapping this DCP; remove it."), why_not);
+       /* XXX: this needs to be fixed */
+       return true;
 }
 
 bool
 DCPContent::can_reference_audio (list<string>& why_not) const
 {
+       DCPDecoder decoder (shared_from_this(), film()->log(), false);
+       BOOST_FOREACH (shared_ptr<dcp::Reel> i, decoder.reels()) {
+               if (!i->main_sound()) {
+                       why_not.push_back (_("The DCP does not have sound in all reels."));
+                       return false;
+               }
+       }
+
        return can_reference<AudioContent> (_("There is other audio content overlapping this DCP; remove it."), why_not);
 }
 
 bool
 DCPContent::can_reference_subtitle (list<string>& why_not) const
 {
-       return can_reference<SubtitleContent> (_("There is other subtitle content overlapping this DCP; remove it."), why_not);
+       /* XXX: this needs to be fixed */
+       return true;
+}
+
+double
+DCPContent::subtitle_video_frame_rate () const
+{
+       return video->video_frame_rate ();
 }