#include <stdexcept>
#include <iostream>
+#include <algorithm>
#include <fstream>
#include <cstdlib>
#include <sstream>
#include "scaler.h"
#include "decoder_factory.h"
#include "config.h"
+#include "check_hashes_job.h"
+#include "version.h"
using namespace std;
using namespace boost;
filesystem::path p (filesystem::system_complete (d));
filesystem::path result;
- for(filesystem::path::iterator i = p.begin(); i != p.end(); ++i) {
+ for (filesystem::path::iterator i = p.begin(); i != p.end(); ++i) {
if (*i == "..") {
if (filesystem::is_symlink (result) || result.filename() == "..") {
result /= *i;
_state.directory = result.string ();
- if (must_exist && !filesystem::exists (_state.directory)) {
- throw OpenFileError (_state.directory);
+ if (!filesystem::exists (_state.directory)) {
+ if (must_exist) {
+ throw OpenFileError (_state.directory);
+ } else {
+ filesystem::create_directory (_state.directory);
+ }
}
read_metadata ();
- _log = new Log (_state.file ("log"));
+ _log = new FileLog (_state.file ("log"));
}
/** Copy constructor */
continue;
}
+ if (line[line.size() - 1] == '\r') {
+ line = line.substr (0, line.size() - 1);
+ }
+
size_t const s = line.find (' ');
if (s == string::npos) {
continue;
void
Film::set_content (string c)
{
- if (filesystem::path(c).has_root_directory () && starts_with (c, _state.directory)) {
+ string check = _state.directory;
+
+#if BOOST_FILESYSTEM_VERSION == 3
+ filesystem::path slash ("/");
+ string platform_slash = slash.make_preferred().string ();
+#else
+#ifdef DVDOMATIC_WINDOWS
+ string platform_slash = "\\";
+#else
+ string platform_slash = "/";
+#endif
+#endif
+
+ if (!ends_with (check, platform_slash)) {
+ check += platform_slash;
+ }
+
+ if (filesystem::path(c).has_root_directory () && starts_with (c, check)) {
c = c.substr (_state.directory.length() + 1);
}
_state.audio_sample_rate = d->audio_sample_rate ();
_state.audio_sample_format = d->audio_sample_format ();
+ _state.content_digest = md5_digest (s->content_path ());
_state.content = c;
signal_changed (SIZE);
void
Film::set_left_crop (int c)
{
- if (c == _state.left_crop) {
+ if (c == _state.crop.left) {
return;
}
- _state.left_crop = c;
- signal_changed (LEFT_CROP);
+ _state.crop.left = c;
+ signal_changed (CROP);
}
/** Set the number of pixels by which to crop the right of the source video */
void
Film::set_right_crop (int c)
{
- if (c == _state.right_crop) {
+ if (c == _state.crop.right) {
return;
}
- _state.right_crop = c;
- signal_changed (RIGHT_CROP);
+ _state.crop.right = c;
+ signal_changed (CROP);
}
/** Set the number of pixels by which to crop the top of the source video */
void
Film::set_top_crop (int c)
{
- if (c == _state.top_crop) {
+ if (c == _state.crop.top) {
return;
}
- _state.top_crop = c;
- signal_changed (TOP_CROP);
+ _state.crop.top = c;
+ signal_changed (CROP);
}
/** Set the number of pixels by which to crop the bottom of the source video */
void
Film::set_bottom_crop (int c)
{
- if (c == _state.bottom_crop) {
+ if (c == _state.crop.bottom) {
return;
}
- _state.bottom_crop = c;
- signal_changed (BOTTOM_CROP);
+ _state.crop.bottom = c;
+ signal_changed (CROP);
}
/** Set the filters to apply to the image when generating thumbnails
{
assert (format());
- stringstream s;
+ filesystem::path p;
/* Start with j2c */
- s << "j2c/";
+ p /= "j2c";
pair<string, string> f = Filter::ffmpeg_strings (filters ());
so that we don't get confused about J2K files generated using different
settings.
*/
- s << _state.format->nickname()
- << "_" << _state.content
- << "_" << left_crop() << "_" << right_crop() << "_" << top_crop() << "_" << bottom_crop()
+ stringstream s;
+ s << _state.format->id()
+ << "_" << _state.content_digest
+ << "_" << crop().left << "_" << crop().right << "_" << crop().top << "_" << crop().bottom
<< "_" << f.first << "_" << f.second
<< "_" << _state.scaler->id();
+ p /= s.str ();
+
/* Similarly for the A/B case */
if (dcp_ab()) {
+ stringstream s;
pair<string, string> fa = Filter::ffmpeg_strings (Config::instance()->reference_filters());
- s << "/ab_" << Config::instance()->reference_scaler()->id() << "_" << fa.first << "_" << fa.second;
+ s << "ab_" << Config::instance()->reference_scaler()->id() << "_" << fa.first << "_" << fa.second;
+ p /= s.str ();
}
- return _state.dir (s.str ());
+ return _state.dir (p.string ());
}
/** Handle a change to the Film's metadata */
throw BadSettingError ("name", "cannot contain slashes");
}
- {
- stringstream s;
- s << "DVD-o-matic " << DVDOMATIC_VERSION << " using " << dependency_version_summary ();
- log()->log (s.str ());
- }
+ log()->log (String::compose ("DVD-o-matic %1 git %2 using %3", dvdomatic_version, dvdomatic_git_commit, dependency_version_summary()));
{
char buffer[128];
gethostname (buffer, sizeof (buffer));
- stringstream s;
- s << "Starting to make a DCP on " << buffer;
- log()->log (s.str ());
+ log()->log (String::compose ("Starting to make DCP on %1", buffer));
}
if (format() == 0) {
o->out_size = format()->dcp_size ();
if (dcp_frames() == 0) {
/* Decode the whole film, no blacking */
- o->num_frames = 0;
o->black_after = 0;
} else {
switch (dcp_trim_action()) {
case CUT:
/* Decode only part of the film, no blacking */
- o->num_frames = dcp_frames ();
o->black_after = 0;
break;
case BLACK_OUT:
/* Decode the whole film, but black some frames out */
- o->num_frames = 0;
o->black_after = dcp_frames ();
}
}
o->decode_video_frequency = freq;
- o->padding = format()->dcp_padding ();
- o->ratio = format()->ratio_as_float ();
+ o->padding = format()->dcp_padding (this);
+ o->ratio = format()->ratio_as_float (this);
+
+ shared_ptr<Job> r;
if (transcode) {
if (_state.dcp_ab) {
- JobManager::instance()->add (shared_ptr<Job> (new ABTranscodeJob (fs, o, log ())));
+ r = JobManager::instance()->add (shared_ptr<Job> (new ABTranscodeJob (fs, o, log(), shared_ptr<Job> ())));
} else {
- JobManager::instance()->add (shared_ptr<Job> (new TranscodeJob (fs, o, log ())));
+ r = JobManager::instance()->add (shared_ptr<Job> (new TranscodeJob (fs, o, log(), shared_ptr<Job> ())));
}
}
-
- JobManager::instance()->add (shared_ptr<Job> (new MakeDCPJob (fs, o, log ())));
+
+ r = JobManager::instance()->add (shared_ptr<Job> (new CheckHashesJob (fs, o, log(), r)));
+ JobManager::instance()->add (shared_ptr<Job> (new MakeDCPJob (fs, o, log(), r)));
}
shared_ptr<FilmState>
return;
}
- _examine_content_job.reset (new ExamineContentJob (state_copy (), log ()));
+ _examine_content_job.reset (new ExamineContentJob (state_copy (), log(), shared_ptr<Job> ()));
_examine_content_job->Finished.connect (sigc::mem_fun (*this, &Film::examine_content_post_gui));
JobManager::instance()->add (_examine_content_job);
}
signal_changed (SCALER);
}
-void
-Film::set_frames_per_second (float f)
-{
- _state.frames_per_second = f;
- signal_changed (FRAMES_PER_SECOND);
-}
-
/** @return full paths to any audio files that this Film has */
vector<string>
Film::audio_files () const
void
Film::send_dcp_to_tms ()
{
- shared_ptr<Job> j (new SCPDCPJob (state_copy (), log ()));
+ shared_ptr<Job> j (new SCPDCPJob (state_copy (), log(), shared_ptr<Job> ()));
JobManager::instance()->add (j);
}
void
Film::copy_from_dvd ()
{
- shared_ptr<Job> j (new CopyFromDVDJob (state_copy (), log ()));
+ shared_ptr<Job> j (new CopyFromDVDJob (state_copy (), log(), shared_ptr<Job> ()));
j->Finished.connect (sigc::mem_fun (*this, &Film::copy_from_dvd_post_gui));
JobManager::instance()->add (j);
}
+int
+Film::encoded_frames () const
+{
+ if (format() == 0) {
+ return 0;
+ }
+
+ int N = 0;
+ for (filesystem::directory_iterator i = filesystem::directory_iterator (j2k_dir ()); i != filesystem::directory_iterator(); ++i) {
+ ++N;
+ this_thread::interruption_point ();
+ }
+
+ return N;
+}