using std::vector;
using std::setfill;
using std::min;
+using std::max;
using std::make_pair;
using std::endl;
using std::cout;
set_isdcf_date_today ();
_playlist_changed_connection = _playlist->Changed.connect (bind (&Film::playlist_changed, this));
- _playlist_content_changed_connection = _playlist->ContentChanged.connect (bind (&Film::playlist_content_changed, this, _1, _2));
-
+ _playlist_content_changed_connection = _playlist->ContentChanged.connect (bind (&Film::playlist_content_changed, this, _1, _2, _3));
+
/* Make state.directory a complete path without ..s (where possible)
(Code swiped from Adam Bowen on stackoverflow)
*/
-
+
boost::filesystem::path p (boost::filesystem::system_complete (dir));
boost::filesystem::path result;
for (boost::filesystem::path::iterator i = p.begin(); i != p.end(); ++i) {
for (list<boost::signals2::connection>::const_iterator i = _job_connections.begin(); i != _job_connections.end(); ++i) {
i->disconnect ();
}
-}
+}
string
Film::video_identifier () const
SafeStringStream s;
s.imbue (std::locale::classic ());
-
+
s << container()->id()
<< "_" << resolution_to_string (_resolution)
<< "_" << _playlist->video_identifier()
return s.str ();
}
-
+
/** @return The file to write video frame info to */
boost::filesystem::path
Film::info_file () const
}
boost::filesystem::path
-Film::audio_analysis_path (shared_ptr<const Playlist> playlist) const
+Film::audio_analysis_path () const
{
boost::filesystem::path p = dir ("analysis");
MD5Digester digester;
- BOOST_FOREACH (shared_ptr<Content> i, playlist->content ()) {
+ BOOST_FOREACH (shared_ptr<Content> i, content ()) {
shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> (i);
if (!ac) {
continue;
}
-
+
digester.add (ac->digest ());
digester.add (ac->audio_mapping().digest ());
digester.add (ac->audio_gain ());
Film::make_dcp ()
{
set_isdcf_date_today ();
-
+
if (dcp_name().find ("/") != string::npos) {
throw BadSettingError (_("name"), _("cannot contain slashes"));
}
LOG_GENERAL ("DCP video rate %1 fps", video_frame_rate());
LOG_GENERAL ("%1 threads", Config::instance()->num_local_encoding_threads());
LOG_GENERAL ("J2K bandwidth %1", j2k_bandwidth());
-
+
if (container() == 0) {
throw MissingSettingError (_("container"));
}
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");
if (_state_version >= 9) {
_use_isdcf_name = f.bool_child ("UseISDCFName");
boost::filesystem::path p;
p /= _directory;
p /= d;
-
+
boost::filesystem::create_directories (p);
-
+
return p;
}
p /= f;
boost::filesystem::create_directories (p.parent_path ());
-
+
return p;
}
split (words, raw_name, is_any_of (" "));
string fixed_name;
-
+
/* Add each word to fixed_name */
for (vector<string>::const_iterator i = words.begin(); i != words.end(); ++i) {
string w = *i;
++caps;
}
}
-
+
/* If w is all caps make the rest of it lower case, otherwise
leave it alone.
*/
if (dm.temp_version) {
d << "-Temp";
}
-
+
if (dm.pre_release) {
d << "-Pre";
}
-
+
if (dm.red_band) {
d << "-RedBand";
}
-
+
if (!dm.chain.empty ()) {
d << "-" << dm.chain;
}
if (video_frame_rate() != 24) {
d << "-" << video_frame_rate();
}
-
+
if (container()) {
d << "_" << container()->isdcf_name();
}
ContentList cl = content ();
-
+
/* XXX: this uses the first bit of content only */
/* The standard says we don't do this for trailers, for some strange reason */
break;
}
}
-
+
if (content_ratio && content_ratio != container()) {
d << "-" << content_ratio->isdcf_name();
}
/* Find all mapped channels */
- list<int> mapped;
- for (ContentList::const_iterator i = cl.begin(); i != cl.end(); ++i) {
- shared_ptr<const AudioContent> ac = dynamic_pointer_cast<const AudioContent> (*i);
- if (ac) {
- list<int> c = ac->audio_mapping().mapped_output_channels ();
- copy (c.begin(), c.end(), back_inserter (mapped));
- }
- }
-
- mapped.sort ();
- mapped.unique ();
-
- /* Count them */
-
int non_lfe = 0;
int lfe = 0;
- for (list<int>::const_iterator i = mapped.begin(); i != mapped.end(); ++i) {
- if (*i >= audio_channels()) {
- /* This channel is mapped but is not included in the DCP */
- continue;
- }
-
- if (static_cast<dcp::Channel> (*i) == dcp::LFE) {
+
+ if (audio_processor ()) {
+ /* Processors are mapped 1:1 to DCP outputs so we can guess the number of LFE/
+ non-LFE from the channel counts.
+ */
+ non_lfe = audio_processor()->out_channels ();
+ if (non_lfe >= 4) {
+ --non_lfe;
++lfe;
- } else {
- ++non_lfe;
+ }
+ } else {
+ list<int> mapped;
+ for (ContentList::const_iterator i = cl.begin(); i != cl.end(); ++i) {
+ shared_ptr<const AudioContent> ac = dynamic_pointer_cast<const AudioContent> (*i);
+ if (ac) {
+ list<int> c = ac->audio_mapping().mapped_output_channels ();
+ copy (c.begin(), c.end(), back_inserter (mapped));
+ }
+ }
+
+ mapped.sort ();
+ mapped.unique ();
+
+ /* Count them */
+
+ for (list<int>::const_iterator i = mapped.begin(); i != mapped.end(); ++i) {
+ if (*i >= audio_channels()) {
+ /* This channel is mapped but is not included in the DCP */
+ continue;
+ }
+
+ if (static_cast<dcp::Channel> (*i) == dcp::LFE) {
+ ++lfe;
+ } else {
+ ++non_lfe;
+ }
}
}
/* XXX: HI/VI */
d << "_" << resolution_to_string (_resolution);
-
+
if (!dm.studio.empty ()) {
d << "_" << dm.studio;
}
} else {
d << "_SMPTE";
}
-
+
if (three_d ()) {
d << "-3D";
}
filtered += unfiltered[i];
}
}
-
+
return filtered;
}
{
_audio_processor = processor;
signal_changed (AUDIO_PROCESSOR);
+ signal_changed (AUDIO_CHANNELS);
}
void
} else if (e == EYES_RIGHT) {
s << ".R";
}
-
+
s << ".j2c";
if (t) {
Film::cpls () const
{
vector<CPLSummary> out;
-
+
boost::filesystem::path const dir = directory ();
for (boost::filesystem::directory_iterator i = boost::filesystem::directory_iterator(dir); i != boost::filesystem::directory_iterator(); ++i) {
if (
}
}
}
-
- return out;
-}
-shared_ptr<Player>
-Film::make_player () const
-{
- return shared_ptr<Player> (new Player (shared_from_this (), _playlist));
+ return out;
}
void
signal_changed (KEY);
}
-shared_ptr<Playlist>
-Film::playlist () const
-{
- return _playlist;
-}
-
ContentList
Film::content () const
{
if (dynamic_pointer_cast<FFmpegContent> (c)) {
run_ffprobe (c->path(0), file ("ffprobe.log"), _log);
}
-
+
shared_ptr<Job> j (new ExamineContentJob (shared_from_this(), c));
_job_connections.push_back (
j->Finished.connect (bind (&Film::maybe_add_content, this, boost::weak_ptr<Job> (j), boost::weak_ptr<Content> (c)))
);
-
+
JobManager::instance()->add (j);
}
if (!job || !job->finished_ok ()) {
return;
}
-
+
shared_ptr<Content> content = c.lock ();
if (content) {
add_content (content);
}
void
-Film::playlist_content_changed (boost::weak_ptr<Content> c, int p)
+Film::playlist_content_changed (boost::weak_ptr<Content> c, int p, bool frequent)
{
if (p == VideoContentProperty::VIDEO_FRAME_RATE) {
set_video_frame_rate (_playlist->best_dcp_frame_rate ());
signal_changed (NAME);
}
- emit (boost::bind (boost::ref (ContentChanged), c, p));
+ emit (boost::bind (boost::ref (ContentChanged), c, p, frequent));
}
void
{
signal_changed (CONTENT);
signal_changed (NAME);
-}
+}
int
Film::audio_frame_rate () const
if (!signer->valid ()) {
throw InvalidSignerError ();
}
-
+
return dcp::DecryptedKDM (
cpl, key(), from, until, "DCP-o-matic", cpl->content_title_text(), dcp::LocalTime().as_string()
).encrypt (signer, target, formulation);
Film::subtitle_language () const
{
set<string> languages;
-
+
ContentList cl = content ();
BOOST_FOREACH (shared_ptr<Content>& c, cl) {
shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (c);
if (audio_processor ()) {
return audio_processor()->input_names ();
}
-
+
vector<string> n;
n.push_back (_("L"));
n.push_back (_("R"));
return vector<string> (n.begin(), n.begin() + audio_channels ());
}
+
+void
+Film::repeat_content (ContentList c, int n)
+{
+ _playlist->repeat (c, n);
+}
+
+void
+Film::remove_content (ContentList c)
+{
+ _playlist->remove (c);
+}