Reasonably straightforward stuff; main things are adding
[dcpomatic.git] / src / lib / video_content.cc
index 514ecae2eaa7a12fd6e3f542e89c05d046bdf476..708edee76a031e4ea8fe90624388564b173d77a0 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-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 "video_content.h"
+#include "content.h"
 #include "video_examiner.h"
 #include "compose.hpp"
 #include "ratio.h"
@@ -38,7 +39,7 @@
 
 #include "i18n.h"
 
-#define LOG_GENERAL(...) film()->log()->log (String::compose (__VA_ARGS__), LogEntry::TYPE_GENERAL);
+#define LOG_GENERAL(...) film->log()->log (String::compose (__VA_ARGS__), LogEntry::TYPE_GENERAL);
 
 int const VideoContentProperty::VIDEO_SIZE       = 0;
 int const VideoContentProperty::VIDEO_FRAME_RATE  = 1;
@@ -63,8 +64,9 @@ using boost::shared_ptr;
 using boost::optional;
 using boost::dynamic_pointer_cast;
 
-VideoContent::VideoContent (shared_ptr<const Film> film)
-       : Content (film)
+VideoContent::VideoContent (Content* parent, shared_ptr<const Film> film)
+       : _parent (parent)
+       , _film (film)
        , _video_length (0)
        , _video_frame_type (VIDEO_FRAME_TYPE_2D)
        , _scale (VideoContentScale (Ratio::from_id ("178")))
@@ -72,35 +74,12 @@ VideoContent::VideoContent (shared_ptr<const Film> film)
        , _fade_in (0)
        , _fade_out (0)
 {
-       set_default_colour_conversion ();
-}
 
-VideoContent::VideoContent (shared_ptr<const Film> film, DCPTime s, Frame len)
-       : Content (film, s)
-       , _video_length (len)
-       , _video_frame_type (VIDEO_FRAME_TYPE_2D)
-       , _scale (VideoContentScale (Ratio::from_id ("178")))
-       , _yuv (true)
-       , _fade_in (0)
-       , _fade_out (0)
-{
-       set_default_colour_conversion ();
 }
 
-VideoContent::VideoContent (shared_ptr<const Film> film, boost::filesystem::path p)
-       : Content (film, p)
-       , _video_length (0)
-       , _video_frame_type (VIDEO_FRAME_TYPE_2D)
-       , _scale (VideoContentScale (Ratio::from_id ("178")))
-       , _yuv (true)
-       , _fade_in (0)
-       , _fade_out (0)
-{
-       set_default_colour_conversion ();
-}
-
-VideoContent::VideoContent (shared_ptr<const Film> film, cxml::ConstNodePtr node, int version)
-       : Content (film, node)
+VideoContent::VideoContent (Content* parent, shared_ptr<const Film> film, cxml::ConstNodePtr node, int version)
+       : _parent (parent)
+       , _film (film)
 {
        _video_size.width = node->number_child<int> ("VideoWidth");
        _video_size.height = node->number_child<int> ("VideoHeight");
@@ -137,8 +116,9 @@ VideoContent::VideoContent (shared_ptr<const Film> film, cxml::ConstNodePtr node
        }
 }
 
-VideoContent::VideoContent (shared_ptr<const Film> film, vector<shared_ptr<Content> > c)
-       : Content (film, c)
+VideoContent::VideoContent (Content* parent, shared_ptr<const Film> film, vector<shared_ptr<Content> > c)
+       : _parent (parent)
+       , _film (film)
        , _video_length (0)
        , _yuv (false)
 {
@@ -249,14 +229,14 @@ VideoContent::take_from_video_examiner (shared_ptr<VideoExaminer> d)
                        );
        }
 
+       shared_ptr<const Film> film = _film.lock ();
+       DCPOMATIC_ASSERT (film);
        LOG_GENERAL ("Video length obtained from header as %1 frames", _video_length);
 
-       set_default_colour_conversion ();
-
-       signal_changed (VideoContentProperty::VIDEO_SIZE);
-       signal_changed (VideoContentProperty::VIDEO_FRAME_RATE);
-       signal_changed (VideoContentProperty::VIDEO_SCALE);
-       signal_changed (ContentProperty::LENGTH);
+       _parent->signal_changed (VideoContentProperty::VIDEO_SIZE);
+       _parent->signal_changed (VideoContentProperty::VIDEO_FRAME_RATE);
+       _parent->signal_changed (VideoContentProperty::VIDEO_SCALE);
+       _parent->signal_changed (ContentProperty::LENGTH);
 }
 
 void
@@ -272,7 +252,7 @@ VideoContent::set_left_crop (int c)
                _crop.left = c;
        }
 
-       signal_changed (VideoContentProperty::VIDEO_CROP);
+       _parent->signal_changed (VideoContentProperty::VIDEO_CROP);
 }
 
 void
@@ -287,7 +267,7 @@ VideoContent::set_right_crop (int c)
                _crop.right = c;
        }
 
-       signal_changed (VideoContentProperty::VIDEO_CROP);
+       _parent->signal_changed (VideoContentProperty::VIDEO_CROP);
 }
 
 void
@@ -302,7 +282,7 @@ VideoContent::set_top_crop (int c)
                _crop.top = c;
        }
 
-       signal_changed (VideoContentProperty::VIDEO_CROP);
+       _parent->signal_changed (VideoContentProperty::VIDEO_CROP);
 }
 
 void
@@ -317,7 +297,7 @@ VideoContent::set_bottom_crop (int c)
                _crop.bottom = c;
        }
 
-       signal_changed (VideoContentProperty::VIDEO_CROP);
+       _parent->signal_changed (VideoContentProperty::VIDEO_CROP);
 }
 
 void
@@ -332,7 +312,7 @@ VideoContent::set_scale (VideoContentScale s)
                _scale = s;
        }
 
-       signal_changed (VideoContentProperty::VIDEO_SCALE);
+       _parent->signal_changed (VideoContentProperty::VIDEO_SCALE);
 }
 
 /** @return string which includes everything about how this content looks */
@@ -340,8 +320,7 @@ string
 VideoContent::identifier () const
 {
        SafeStringStream s;
-       s << Content::identifier()
-         << "_" << crop().left
+       s << crop().left
          << "_" << crop().right
          << "_" << crop().top
          << "_" << crop().bottom
@@ -364,7 +343,7 @@ VideoContent::set_video_frame_type (VideoFrameType t)
                _video_frame_type = t;
        }
 
-       signal_changed (VideoContentProperty::VIDEO_FRAME_TYPE);
+       _parent->signal_changed (VideoContentProperty::VIDEO_FRAME_TYPE);
 }
 
 string
@@ -412,7 +391,7 @@ VideoContent::unset_colour_conversion ()
                _colour_conversion = boost::optional<ColourConversion> ();
        }
 
-       signal_changed (VideoContentProperty::COLOUR_CONVERSION);
+       _parent->signal_changed (VideoContentProperty::COLOUR_CONVERSION);
 }
 
 void
@@ -423,7 +402,7 @@ VideoContent::set_colour_conversion (ColourConversion c)
                _colour_conversion = c;
        }
 
-       signal_changed (VideoContentProperty::COLOUR_CONVERSION);
+       _parent->signal_changed (VideoContentProperty::COLOUR_CONVERSION);
 }
 
 void
@@ -434,7 +413,7 @@ VideoContent::set_fade_in (Frame t)
                _fade_in = t;
        }
 
-       signal_changed (VideoContentProperty::VIDEO_FADE_IN);
+       _parent->signal_changed (VideoContentProperty::VIDEO_FADE_IN);
 }
 
 void
@@ -445,7 +424,7 @@ VideoContent::set_fade_out (Frame t)
                _fade_out = t;
        }
 
-       signal_changed (VideoContentProperty::VIDEO_FADE_OUT);
+       _parent->signal_changed (VideoContentProperty::VIDEO_FADE_OUT);
 }
 
 /** @return Video size after 3D split and crop */
@@ -458,9 +437,11 @@ VideoContent::video_size_after_crop () const
 void
 VideoContent::scale_and_crop_to_fit_width ()
 {
-       set_scale (VideoContentScale (film()->container ()));
+       shared_ptr<const Film> film = _film.lock ();
+       DCPOMATIC_ASSERT (film);
+       set_scale (VideoContentScale (film->container ()));
 
-       int const crop = max (0, int (video_size().height - double (film()->frame_size().height) * video_size().width / film()->frame_size().width));
+       int const crop = max (0, int (video_size().height - double (film->frame_size().height) * video_size().width / film->frame_size().width));
        set_left_crop (0);
        set_right_crop (0);
        set_top_crop (crop / 2);
@@ -470,9 +451,11 @@ VideoContent::scale_and_crop_to_fit_width ()
 void
 VideoContent::scale_and_crop_to_fit_height ()
 {
-       set_scale (VideoContentScale (film()->container ()));
+       shared_ptr<const Film> film = _film.lock ();
+       DCPOMATIC_ASSERT (film);
+       set_scale (VideoContentScale (film->container ()));
 
-       int const crop = max (0, int (video_size().width - double (film()->frame_size().width) * video_size().height / film()->frame_size().height));
+       int const crop = max (0, int (video_size().width - double (film->frame_size().width) * video_size().height / film->frame_size().height));
        set_left_crop (crop / 2);
        set_right_crop (crop / 2);
        set_top_crop (0);
@@ -491,7 +474,7 @@ VideoContent::set_video_frame_rate (double r)
                _video_frame_rate = r;
        }
 
-       signal_changed (VideoContentProperty::VIDEO_FRAME_RATE);
+       _parent->signal_changed (VideoContentProperty::VIDEO_FRAME_RATE);
 }
 
 /** @param f Frame index within the whole (untrimmed) content */
@@ -500,12 +483,12 @@ VideoContent::fade (Frame f) const
 {
        DCPOMATIC_ASSERT (f >= 0);
 
-       Frame const ts = trim_start().frames_round(video_frame_rate());
+       Frame const ts = _parent->trim_start().frames_round(video_frame_rate());
        if ((f - ts) < fade_in()) {
                return double (f - ts) / fade_in();
        }
 
-       Frame fade_out_start = video_length() - trim_end().frames_round(video_frame_rate()) - fade_out();
+       Frame fade_out_start = video_length() - _parent->trim_end().frames_round(video_frame_rate()) - fade_out();
        if (f >= fade_out_start) {
                return 1 - double (f - fade_out_start) / fade_out();
        }
@@ -547,8 +530,10 @@ VideoContent::processing_description () const
                d << " (" << fixed << setprecision(2) << cropped.ratio () << ":1)\n";
        }
 
-       dcp::Size const container_size = film()->frame_size ();
-       dcp::Size const scaled = scale().size (dynamic_pointer_cast<const VideoContent> (shared_from_this ()), container_size, container_size);
+       shared_ptr<const Film> film = _film.lock ();
+       DCPOMATIC_ASSERT (film);
+       dcp::Size const container_size = film->frame_size ();
+       dcp::Size const scaled = scale().size (shared_from_this(), container_size, container_size);
 
        if (scaled != video_size_after_crop ()) {
                d << String::compose (
@@ -562,7 +547,7 @@ VideoContent::processing_description () const
        if (scaled != container_size) {
                d << String::compose (
                        _("Padded with black to fit container %1 (%2x%3)"),
-                       film()->container()->nickname (),
+                       film->container()->nickname (),
                        container_size.width, container_size.height
                        );
 
@@ -572,23 +557,36 @@ VideoContent::processing_description () const
        d << _("Content frame rate");
        d << " " << fixed << setprecision(4) << video_frame_rate() << "\n";
 
-       FrameRateChange frc (video_frame_rate(), film()->video_frame_rate ());
+       FrameRateChange frc (video_frame_rate(), film->video_frame_rate ());
        d << frc.description () << "\n";
 
        return d.str ();
 }
 
 void
-VideoContent::add_properties (list<pair<string, string> >& p) const
+VideoContent::add_properties (list<UserProperty>& p) const
 {
-       p.push_back (make_pair (_("Video length"), raw_convert<string> (video_length ()) + " " + _("video frames")));
-       p.push_back (make_pair (_("Video size"), raw_convert<string> (video_size().width) + "x" + raw_convert<string> (video_size().height)));
-       p.push_back (make_pair (_("Video frame rate"), raw_convert<string> (video_frame_rate()) + " " + _("frames per second")));
+       p.push_back (UserProperty (_("Video"), _("Length"), raw_convert<string> (video_length ()), _("video frames")));
+       p.push_back (UserProperty (_("Video"), _("Size"), raw_convert<string> (video_size().width) + "x" + raw_convert<string> (video_size().height)));
+       p.push_back (UserProperty (_("Video"), _("Frame rate"), raw_convert<string> (video_frame_rate(), 5), _("frames per second")));
 }
 
 double
 VideoContent::video_frame_rate () const
 {
        boost::mutex::scoped_lock lm (_mutex);
-       return _video_frame_rate.get_value_or (film()->video_frame_rate ());
+       shared_ptr<const Film> film = _film.lock ();
+       DCPOMATIC_ASSERT (film);
+       return _video_frame_rate.get_value_or (film->video_frame_rate ());
+}
+
+void
+VideoContent::set_video_length (Frame len)
+{
+       {
+               boost::mutex::scoped_lock lm (_mutex);
+               _video_length = len;
+       }
+
+       _parent->signal_changed (ContentProperty::LENGTH);
 }