diff options
| author | Carl Hetherington <cth@carlh.net> | 2015-10-13 11:30:30 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2015-10-13 11:30:30 +0100 |
| commit | 6f23b55a7783f93549115a133ca2e6e938bd0cd1 (patch) | |
| tree | 6c674d088eb37dd9d91992366cfa6ddb3e0e69e5 /src | |
| parent | f9068dcbfbb09082e29e2a779ef1a7a2f6ee849e (diff) | |
Some attempts to block referencing of DCPs when it is not possible.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/dcp_content.cc | 69 | ||||
| -rw-r--r-- | src/lib/dcp_content.h | 8 | ||||
| -rw-r--r-- | src/lib/dcpomatic_time.h | 2 | ||||
| -rw-r--r-- | src/lib/overlaps.h | 39 | ||||
| -rw-r--r-- | src/lib/referenced_reel_asset.h | 32 | ||||
| -rw-r--r-- | src/wx/audio_panel.cc | 21 | ||||
| -rw-r--r-- | src/wx/subtitle_panel.cc | 27 | ||||
| -rw-r--r-- | src/wx/timeline.cc | 15 | ||||
| -rw-r--r-- | src/wx/video_panel.cc | 21 |
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); |
