using libdcp::Size;
using libdcp::Signer;
-int const Film::state_version = 5;
+/* 5 -> 6
+ * AudioMapping XML changed.
+ * 6 -> 7
+ * Subtitle offset changed to subtitle y offset, and subtitle x offset added.
+ * 7 -> 8
+ * Use <Scale> tag in <VideoContent> rather than <Ratio>.
+ */
+int const Film::current_state_version = 8;
/** Construct a Film object in a given directory.
*
* @param dir Film directory.
*/
-Film::Film (boost::filesystem::path dir)
+Film::Film (boost::filesystem::path dir, bool log)
: _playlist (new Playlist)
, _use_dci_name (true)
, _dcp_content_type (Config::instance()->default_dcp_content_type ())
, _resolution (RESOLUTION_2K)
, _scaler (Scaler::from_id ("bicubic"))
, _with_subtitles (false)
+ , _signed (true)
, _encrypted (false)
, _j2k_bandwidth (Config::instance()->default_j2k_bandwidth ())
, _dci_metadata (Config::instance()->default_dci_metadata ())
, _video_frame_rate (24)
- , _audio_channels (MAX_AUDIO_CHANNELS)
+ , _audio_channels (6)
, _three_d (false)
, _sequence_video (true)
, _interop (false)
+ , _state_version (current_state_version)
, _dirty (false)
{
set_dci_date_today ();
}
set_directory (result);
- _log.reset (new FileLog (file ("log")));
+ if (log) {
+ _log.reset (new FileLog (file ("log")));
+ } else {
+ _log.reset (new NullLog);
+ }
_playlist->set_sequence_video (_sequence_video);
}
}
boost::filesystem::path
-Film::audio_analysis_path (shared_ptr<const AudioContent> c) const
+Film::audio_analysis_dir () const
{
- boost::filesystem::path p = dir ("analysis");
- p /= c->digest();
- return p;
+ return dir ("analysis");
}
/** Add suitable Jobs to the JobManager to create a DCP for this Film */
#else
log()->log ("libdcp built in optimised mode.");
#endif
+
+#ifdef DCPOMATIC_WINDOWS
+ OSVERSIONINFO info;
+ info.dwOSVersionInfoSize = sizeof (info);
+ GetVersionEx (&info);
+ log()->log (String::compose ("Windows version %1.%2.%3 SP %4", info.dwMajorVersion, info.dwMinorVersion, info.dwBuildNumber, info.szCSDVersion));
+#endif
+
log()->log (String::compose ("CPU: %1, %2 processors", cpu_info(), boost::thread::hardware_concurrency ()));
list<pair<string, string> > const m = mount_info ();
for (list<pair<string, string> >::const_iterator i = m.begin(); i != m.end(); ++i) {
return N;
}
-/** Write state to our `metadata' file */
-void
-Film::write_metadata () const
+shared_ptr<xmlpp::Document>
+Film::metadata () const
{
- if (!boost::filesystem::exists (directory ())) {
- boost::filesystem::create_directory (directory ());
- }
-
LocaleGuard lg;
- boost::filesystem::create_directories (directory ());
-
- xmlpp::Document doc;
- xmlpp::Element* root = doc.create_root_node ("Metadata");
+ shared_ptr<xmlpp::Document> doc (new xmlpp::Document);
+ xmlpp::Element* root = doc->create_root_node ("Metadata");
- root->add_child("Version")->add_child_text (lexical_cast<string> (state_version));
+ root->add_child("Version")->add_child_text (lexical_cast<string> (current_state_version));
root->add_child("Name")->add_child_text (_name);
root->add_child("UseDCIName")->add_child_text (_use_dci_name ? "1" : "0");
root->add_child("ThreeD")->add_child_text (_three_d ? "1" : "0");
root->add_child("SequenceVideo")->add_child_text (_sequence_video ? "1" : "0");
root->add_child("Interop")->add_child_text (_interop ? "1" : "0");
+ root->add_child("Signed")->add_child_text (_signed ? "1" : "0");
root->add_child("Encrypted")->add_child_text (_encrypted ? "1" : "0");
root->add_child("Key")->add_child_text (_key.hex ());
_playlist->as_xml (root->add_child ("Playlist"));
- doc.write_to_file_formatted (file("metadata.xml").string ());
-
+ return doc;
+}
+
+/** Write state to our `metadata' file */
+void
+Film::write_metadata () const
+{
+ boost::filesystem::create_directories (directory ());
+ shared_ptr<xmlpp::Document> doc = metadata ();
+ doc->write_to_file_formatted (file("metadata.xml").string ());
_dirty = false;
}
cxml::Document f ("Metadata");
f.read_file (file ("metadata.xml"));
- int const version = f.number_child<int> ("Version");
+ _state_version = f.number_child<int> ("Version");
+ if (_state_version > current_state_version) {
+ throw StringError (_("This film was created with a newer version of DCP-o-matic, and it cannot be loaded into this version. Sorry!"));
+ }
_name = f.string_child ("Name");
_use_dci_name = f.bool_child ("UseDCIName");
_dci_metadata = DCIMetadata (f.node_child ("DCIMetadata"));
_video_frame_rate = f.number_child<int> ("VideoFrameRate");
_dci_date = boost::gregorian::from_undelimited_string (f.string_child ("DCIDate"));
+ _signed = f.optional_bool_child("Signed").get_value_or (true);
_encrypted = f.bool_child ("Encrypted");
_audio_channels = f.number_child<int> ("AudioChannels");
_sequence_video = f.bool_child ("SequenceVideo");
_three_d = f.bool_child ("ThreeD");
_interop = f.bool_child ("Interop");
_key = libdcp::Key (f.string_child ("Key"));
- _playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist"), version);
+ _playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist"), _state_version);
_dirty = false;
}
return shared_ptr<Player> (new Player (shared_from_this (), _playlist));
}
+void
+Film::set_signed (bool s)
+{
+ _signed = s;
+ signal_changed (SIGNED);
+}
+
void
Film::set_encrypted (bool e)
{
return _playlist->best_dcp_frame_rate ();
}
-bool
-Film::content_paths_valid () const
-{
- return _playlist->content_paths_valid ();
-}
-
void
Film::playlist_content_changed (boost::weak_ptr<Content> c, int p)
{
OutputAudioFrame
Film::time_to_audio_frames (Time t) const
{
- return t * audio_frame_rate () / TIME_HZ;
+ return divide_with_round (t * audio_frame_rate (), TIME_HZ);
}
OutputVideoFrame
Film::time_to_video_frames (Time t) const
{
- return t * video_frame_rate () / TIME_HZ;
+ return divide_with_round (t * video_frame_rate (), TIME_HZ);
}
Time
Film::audio_frames_to_time (OutputAudioFrame f) const
{
- return f * TIME_HZ / audio_frame_rate ();
+ return divide_with_round (f * TIME_HZ, audio_frame_rate ());
}
Time
Film::video_frames_to_time (OutputVideoFrame f) const
{
- return f * TIME_HZ / video_frame_rate ();
+ return divide_with_round (f * TIME_HZ, video_frame_rate ());
}
OutputAudioFrame
return kdms;
}
+
+/** @return The approximate disk space required to encode a DCP of this film with the
+ * current settings, in bytes.
+ */
+uint64_t
+Film::required_disk_space () const
+{
+ return uint64_t (j2k_bandwidth() / 8) * length() / TIME_HZ;
+}
+
+/** This method checks the disk that the Film is on and tries to decide whether or not
+ * there will be enough space to make a DCP for it. If so, true is returned; if not,
+ * false is returned and required and availabe are filled in with the amount of disk space
+ * required and available respectively (in Gb).
+ *
+ * Note: the decision made by this method isn't, of course, 100% reliable.
+ */
+bool
+Film::should_be_enough_disk_space (double& required, double& available) const
+{
+ boost::filesystem::space_info s = boost::filesystem::space (internal_video_mxf_dir ());
+ required = double (required_disk_space ()) / 1073741824.0f;
+ available = double (s.available) / 1073741824.0f;
+ return (available - required) > 1;
+}