+
+ for (int i = 0; i < audio_channels(); ++i) {
+ n.push_back (short_audio_channel_name (i));
+ }
+
+ return n;
+}
+
+void
+Film::repeat_content (ContentList c, int n)
+{
+ _playlist->repeat (c, n);
+}
+
+void
+Film::remove_content (ContentList c)
+{
+ _playlist->remove (c);
+}
+
+void
+Film::audio_analysis_finished ()
+{
+ /* XXX */
+}
+
+list<DCPTimePeriod>
+Film::reels () const
+{
+ list<DCPTimePeriod> p;
+ DCPTime const len = length();
+
+ switch (reel_type ()) {
+ case REELTYPE_SINGLE:
+ p.push_back (DCPTimePeriod (DCPTime (), len));
+ break;
+ case REELTYPE_BY_VIDEO_CONTENT:
+ {
+ optional<DCPTime> last_split;
+ shared_ptr<Content> last_video;
+ BOOST_FOREACH (shared_ptr<Content> c, content ()) {
+ if (c->video) {
+ BOOST_FOREACH (DCPTime t, c->reel_split_points()) {
+ if (last_split) {
+ p.push_back (DCPTimePeriod (last_split.get(), t));
+ }
+ last_split = t;
+ }
+ last_video = c;
+ }
+ }
+
+ DCPTime video_end = last_video ? last_video->end() : DCPTime(0);
+ if (last_split) {
+ /* Definitely go from the last split to the end of the video content */
+ p.push_back (DCPTimePeriod (last_split.get(), video_end));
+ }
+
+ if (video_end < len) {
+ /* And maybe go after that as well if there is any non-video hanging over the end */
+ p.push_back (DCPTimePeriod (video_end, len));
+ }
+ break;
+ }
+ case REELTYPE_BY_LENGTH:
+ {
+ DCPTime current;
+ /* Integer-divide reel length by the size of one frame to give the number of frames per reel */
+ Frame const reel_in_frames = _reel_length / ((j2k_bandwidth() / video_frame_rate()) / 8);
+ while (current < len) {
+ DCPTime end = min (len, current + DCPTime::from_frames (reel_in_frames, video_frame_rate ()));
+ p.push_back (DCPTimePeriod (current, end));
+ current = end;
+ }
+ break;
+ }
+ }
+
+ return p;
+}
+
+/** @param period A period within the DCP
+ * @return Name of the content which most contributes to the given period.
+ */
+string
+Film::content_summary (DCPTimePeriod period) const
+{
+ return _playlist->content_summary (period);
+}
+
+void
+Film::use_template (string name)
+{
+ _template_film.reset (new Film (optional<boost::filesystem::path>()));
+ _template_film->read_metadata (Config::instance()->template_path (name));
+ _use_isdcf_name = _template_film->_use_isdcf_name;
+ _dcp_content_type = _template_film->_dcp_content_type;
+ _container = _template_film->_container;
+ _resolution = _template_film->_resolution;
+ _j2k_bandwidth = _template_film->_j2k_bandwidth;
+ _video_frame_rate = _template_film->_video_frame_rate;
+ _signed = _template_film->_signed;
+ _encrypted = _template_film->_encrypted;
+ _audio_channels = _template_film->_audio_channels;
+ _sequence = _template_film->_sequence;
+ _three_d = _template_film->_three_d;
+ _interop = _template_film->_interop;
+ _audio_processor = _template_film->_audio_processor;
+ _reel_type = _template_film->_reel_type;
+ _reel_length = _template_film->_reel_length;
+ _upload_after_make_dcp = _template_film->_upload_after_make_dcp;
+ _isdcf_metadata = _template_film->_isdcf_metadata;
+}
+
+pair<double, double>
+Film::speed_up_range (int dcp_frame_rate) const
+{
+ return _playlist->speed_up_range (dcp_frame_rate);
+}
+
+void
+Film::copy_from (shared_ptr<const Film> film)
+{
+ read_metadata (film->file (metadata_file));
+}
+
+bool
+Film::references_dcp_video () const
+{
+ BOOST_FOREACH (shared_ptr<Content> i, _playlist->content()) {
+ shared_ptr<DCPContent> d = dynamic_pointer_cast<DCPContent>(i);
+ if (d && d->reference_video()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool
+Film::references_dcp_audio () const
+{
+ BOOST_FOREACH (shared_ptr<Content> i, _playlist->content()) {
+ shared_ptr<DCPContent> d = dynamic_pointer_cast<DCPContent>(i);
+ if (d && d->reference_audio()) {
+ return true;
+ }
+ }
+
+ return false;