summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2015-10-13 11:30:30 +0100
committerCarl Hetherington <cth@carlh.net>2015-10-13 11:30:30 +0100
commit6f23b55a7783f93549115a133ca2e6e938bd0cd1 (patch)
tree6c674d088eb37dd9d91992366cfa6ddb3e0e69e5 /src
parentf9068dcbfbb09082e29e2a779ef1a7a2f6ee849e (diff)
Some attempts to block referencing of DCPs when it is not possible.
Diffstat (limited to 'src')
-rw-r--r--src/lib/dcp_content.cc69
-rw-r--r--src/lib/dcp_content.h8
-rw-r--r--src/lib/dcpomatic_time.h2
-rw-r--r--src/lib/overlaps.h39
-rw-r--r--src/lib/referenced_reel_asset.h32
-rw-r--r--src/wx/audio_panel.cc21
-rw-r--r--src/wx/subtitle_panel.cc27
-rw-r--r--src/wx/timeline.cc15
-rw-r--r--src/wx/video_panel.cc21
9 files changed, 211 insertions, 23 deletions
diff --git a/src/lib/dcp_content.cc b/src/lib/dcp_content.cc
index f39b2fb4a..747216f3c 100644
--- a/src/lib/dcp_content.cc
+++ b/src/lib/dcp_content.cc
@@ -22,6 +22,7 @@
#include "job.h"
#include "film.h"
#include "config.h"
+#include "overlaps.h"
#include "compose.hpp"
#include "dcp_decoder.h"
#include <dcp/dcp.h>
@@ -250,19 +251,75 @@ DCPContent::set_reference_subtitle (bool r)
signal_changed (DCPContentProperty::REFERENCE_SUBTITLE);
}
+list<DCPTimePeriod>
+DCPContent::reels () const
+{
+ list<DCPTimePeriod> p;
+ DCPDecoder decoder (shared_from_this(), false);
+
+ 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());
+ p.push_back (DCPTimePeriod (from, to));
+ from = to;
+ }
+
+ return p;
+}
+
list<DCPTime>
DCPContent::reel_split_points () const
{
list<DCPTime> s;
- DCPDecoder decoder (shared_from_this(), false);
- DCPTime t = position();
+ BOOST_FOREACH (DCPTimePeriod i, reels()) {
+ s.push_back (i.from);
+ }
+ return s;
+}
+template <class T>
+bool
+DCPContent::can_reference (string overlapping, list<string>& why_not) const
+{
shared_ptr<const Film> film = _film.lock ();
DCPOMATIC_ASSERT (film);
- BOOST_FOREACH (shared_ptr<dcp::Reel> k, decoder.reels()) {
- s.push_back (t);
- t += DCPTime::from_frames (k->main_picture()->duration(), film->video_frame_rate());
+
+ 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'."));
+ return false;
+ }
}
- return s;
+ 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;
+ }
+
+ return true;
+}
+
+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);
+}
+
+bool
+DCPContent::can_reference_audio (list<string>& why_not) const
+{
+ 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);
}
diff --git a/src/lib/dcp_content.h b/src/lib/dcp_content.h
index be12ba534..78c97bec5 100644
--- a/src/lib/dcp_content.h
+++ b/src/lib/dcp_content.h
@@ -104,6 +104,8 @@ public:
return _reference_video;
}
+ bool can_reference_video (std::list<std::string> &) const;
+
void set_reference_audio (bool r);
bool reference_audio () const {
@@ -111,6 +113,8 @@ public:
return _reference_audio;
}
+ bool can_reference_audio (std::list<std::string> &) const;
+
void set_reference_subtitle (bool r);
bool reference_subtitle () const {
@@ -118,11 +122,15 @@ public:
return _reference_subtitle;
}
+ bool can_reference_subtitle (std::list<std::string> &) const;
+
protected:
void add_properties (std::list<std::pair<std::string, std::string> >& p) const;
private:
void read_directory (boost::filesystem::path);
+ std::list<DCPTimePeriod> reels () const;
+ template <class T> bool can_reference (std::string overlapping, std::list<std::string>& why_not) const;
std::string _name;
bool _has_subtitles;
diff --git a/src/lib/dcpomatic_time.h b/src/lib/dcpomatic_time.h
index 496f54d8e..90e79de0a 100644
--- a/src/lib/dcpomatic_time.h
+++ b/src/lib/dcpomatic_time.h
@@ -258,7 +258,7 @@ public:
return (from <= other && other < to);
}
- bool operator== (TimePeriod<T> const & other) {
+ bool operator== (TimePeriod<T> const & other) const {
return from == other.from && to == other.to;
}
};
diff --git a/src/lib/overlaps.h b/src/lib/overlaps.h
new file mode 100644
index 000000000..6018af15f
--- /dev/null
+++ b/src/lib/overlaps.h
@@ -0,0 +1,39 @@
+/*
+ Copyright (C) 2013-2015 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.
+
+*/
+
+/** @return Pieces of content type C that overlap a specified time range in the given ContentList */
+template<class C>
+std::list<boost::shared_ptr<C> >
+overlaps (ContentList cl, DCPTime from, DCPTime to)
+{
+ std::list<boost::shared_ptr<C> > overlaps;
+ DCPTimePeriod period (from, to);
+ for (typename ContentList::const_iterator i = cl.begin(); i != cl.end(); ++i) {
+ boost::shared_ptr<C> c = boost::dynamic_pointer_cast<C> (*i);
+ if (!c) {
+ continue;
+ }
+
+ if (DCPTimePeriod(c->position(), c->end()).overlaps (period)) {
+ overlaps.push_back (c);
+ }
+ }
+
+ return overlaps;
+}
diff --git a/src/lib/referenced_reel_asset.h b/src/lib/referenced_reel_asset.h
new file mode 100644
index 000000000..5f5421283
--- /dev/null
+++ b/src/lib/referenced_reel_asset.h
@@ -0,0 +1,32 @@
+/*
+ Copyright (C) 2015 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.
+
+*/
+
+class ReferencedReelAsset
+{
+public:
+ ReferencedReelAsset (boost::shared_ptr<dcp::ReelAsset> asset_, DCPTimePeriod period_)
+ : asset (asset_)
+ , period (period_)
+ {}
+
+ /** The asset */
+ boost::shared_ptr<dcp::ReelAsset> asset;
+ /** Period that this asset covers in the DCP */
+ DCPTimePeriod period;
+};
diff --git a/src/wx/audio_panel.cc b/src/wx/audio_panel.cc
index a4976b8c1..9632b5235 100644
--- a/src/wx/audio_panel.cc
+++ b/src/wx/audio_panel.cc
@@ -141,6 +141,8 @@ AudioPanel::film_changed (Film::Property property)
case Film::VIDEO_FRAME_RATE:
setup_description ();
break;
+ case Film::REEL_TYPE:
+ setup_sensitivity ();
default:
break;
}
@@ -238,7 +240,24 @@ void
AudioPanel::setup_sensitivity ()
{
AudioContentList sel = _parent->selected_audio ();
- _reference->Enable (sel.size() == 1 && dynamic_pointer_cast<DCPContent> (sel.front ()));
+
+ shared_ptr<DCPContent> dcp;
+ if (sel.size() == 1) {
+ dcp = dynamic_pointer_cast<DCPContent> (sel.front ());
+ }
+
+ list<string> why_not;
+ bool const can_reference = dcp && dcp->can_reference_audio (why_not);
+ _reference->Enable (can_reference);
+
+ wxString s;
+ if (!can_reference) {
+ s = _("Cannot reference this DCP. ");
+ BOOST_FOREACH (string i, why_not) {
+ s += std_to_wx(i) + wxT(" ");
+ }
+ }
+ _reference->SetToolTip (s);
if (_reference->GetValue ()) {
_gain->wrapped()->Enable (false);
diff --git a/src/wx/subtitle_panel.cc b/src/wx/subtitle_panel.cc
index f3083b194..757a302a1 100644
--- a/src/wx/subtitle_panel.cc
+++ b/src/wx/subtitle_panel.cc
@@ -36,6 +36,7 @@
using std::vector;
using std::string;
+using std::list;
using boost::shared_ptr;
using boost::lexical_cast;
using boost::dynamic_pointer_cast;
@@ -133,7 +134,7 @@ SubtitlePanel::SubtitlePanel (ContentPanel* p)
void
SubtitlePanel::film_changed (Film::Property property)
{
- if (property == Film::CONTENT) {
+ if (property == Film::CONTENT || property == Film::REEL_TYPE) {
setup_sensitivity ();
}
}
@@ -219,7 +220,8 @@ SubtitlePanel::setup_sensitivity ()
int ffmpeg_subs = 0;
int subrip_or_dcp_subs = 0;
int image_subs = 0;
- BOOST_FOREACH (shared_ptr<SubtitleContent> i, _parent->selected_subtitle ()) {
+ SubtitleContentList sel = _parent->selected_subtitle ();
+ BOOST_FOREACH (shared_ptr<SubtitleContent> i, sel) {
shared_ptr<const FFmpegContent> fc = boost::dynamic_pointer_cast<const FFmpegContent> (i);
shared_ptr<const SubRipContent> sc = boost::dynamic_pointer_cast<const SubRipContent> (i);
shared_ptr<const DCPSubtitleContent> dsc = boost::dynamic_pointer_cast<const DCPSubtitleContent> (i);
@@ -242,6 +244,24 @@ SubtitlePanel::setup_sensitivity ()
}
}
+ shared_ptr<DCPContent> dcp;
+ if (sel.size() == 1) {
+ dcp = dynamic_pointer_cast<DCPContent> (sel.front ());
+ }
+
+ list<string> why_not;
+ bool const can_reference = dcp && dcp->can_reference_subtitle (why_not);
+ _reference->Enable (can_reference);
+
+ wxString s;
+ if (!can_reference) {
+ s = _("Cannot reference this DCP. ");
+ BOOST_FOREACH (string i, why_not) {
+ s += std_to_wx(i) + wxT(" ");
+ }
+ }
+ _reference->SetToolTip (s);
+
bool const reference = _reference->GetValue ();
_use->Enable (!reference && any_subs > 0);
@@ -255,9 +275,6 @@ SubtitlePanel::setup_sensitivity ()
_stream->Enable (!reference && ffmpeg_subs == 1);
_subtitle_view_button->Enable (!reference && subrip_or_dcp_subs == 1);
_fonts_dialog_button->Enable (!reference && subrip_or_dcp_subs == 1);
-
- ContentList sel = _parent->selected ();
- _reference->Enable (sel.size() == 1 && dynamic_pointer_cast<DCPContent> (sel.front ()));
}
void
diff --git a/src/wx/timeline.cc b/src/wx/timeline.cc
index c1afdd369..f91d2937f 100644
--- a/src/wx/timeline.cc
+++ b/src/wx/timeline.cc
@@ -168,6 +168,7 @@ Timeline::assign_tracks ()
}
shared_ptr<Content> content = cv->content();
+ DCPTimePeriod content_period (content->position(), content->end());
int t = 0;
while (true) {
@@ -182,11 +183,7 @@ Timeline::assign_tracks ()
shared_ptr<Content> test_content = test->content();
if (test && test->track() && test->track().get() == t) {
- bool const no_overlap =
- (content->position() < test_content->position() && content->end() < test_content->position()) ||
- (content->position() > test_content->end() && content->end() > test_content->end());
-
- if (!no_overlap) {
+ if (content_period.overlaps (DCPTimePeriod(test_content->position(), test_content->end()))) {
/* we have an overlap on track `t' */
++t;
break;
@@ -367,7 +364,7 @@ Timeline::set_position_from_event (wxMouseEvent& ev)
if (_snap) {
- DCPTime const new_end = new_position + _down_view->content()->length_after_trim () - DCPTime (1);
+ DCPTime const new_end = new_position + _down_view->content()->length_after_trim();
/* Signed `distance' to nearest thing (i.e. negative is left on the timeline,
positive is right).
*/
@@ -381,9 +378,9 @@ Timeline::set_position_from_event (wxMouseEvent& ev)
}
maybe_snap (cv->content()->position(), new_position, nearest_distance);
- maybe_snap (cv->content()->position(), new_end + DCPTime (1), nearest_distance);
- maybe_snap (cv->content()->end() + DCPTime (1), new_position, nearest_distance);
- maybe_snap (cv->content()->end() + DCPTime (1), new_end, nearest_distance);
+ maybe_snap (cv->content()->position(), new_end, nearest_distance);
+ maybe_snap (cv->content()->end(), new_position, nearest_distance);
+ maybe_snap (cv->content()->end(), new_end, nearest_distance);
}
if (nearest_distance) {
diff --git a/src/wx/video_panel.cc b/src/wx/video_panel.cc
index dd9bb5848..79ea9dbfa 100644
--- a/src/wx/video_panel.cc
+++ b/src/wx/video_panel.cc
@@ -246,6 +246,8 @@ VideoPanel::film_changed (Film::Property property)
case Film::RESOLUTION:
setup_description ();
break;
+ case Film::REEL_TYPE:
+ setup_sensitivity ();
default:
break;
}
@@ -434,7 +436,24 @@ void
VideoPanel::setup_sensitivity ()
{
ContentList sel = _parent->selected ();
- _reference->Enable (sel.size() == 1 && dynamic_pointer_cast<DCPContent> (sel.front ()));
+
+ shared_ptr<DCPContent> dcp;
+ if (sel.size() == 1) {
+ dcp = dynamic_pointer_cast<DCPContent> (sel.front ());
+ }
+
+ list<string> why_not;
+ bool const can_reference = dcp && dcp->can_reference_video(why_not);
+ _reference->Enable (can_reference);
+
+ wxString s;
+ if (!can_reference) {
+ s = _("Cannot reference this DCP. ");
+ BOOST_FOREACH (string i, why_not) {
+ s += std_to_wx(i) + wxT(" ");
+ }
+ }
+ _reference->SetToolTip (s);
if (_reference->GetValue ()) {
_frame_type->wrapped()->Enable (false);