#include "safe_stringstream.h"
#include "environment_info.h"
#include "raw_convert.h"
+#include "audio_processor.h"
+#include "md5_digester.h"
#include <libcxml/cxml.h>
#include <dcp/cpl.h>
#include <dcp/signer.h>
, _sequence_video (true)
, _interop (false)
, _burn_subtitles (false)
+ , _audio_processor (0)
, _state_version (current_state_version)
, _dirty (false)
{
}
boost::filesystem::path
-Film::audio_analysis_dir () const
+Film::audio_analysis_path (shared_ptr<const Playlist> playlist) const
{
- return dir ("analysis");
+ boost::filesystem::path p = dir ("analysis");
+
+ MD5Digester digester;
+ BOOST_FOREACH (shared_ptr<Content> i, playlist->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 ());
+ }
+
+ if (audio_processor ()) {
+ digester.add (audio_processor()->id ());
+ }
+
+ p /= digester.get ();
+ return p;
}
/** Add suitable Jobs to the JobManager to create a DCP for this Film */
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 ());
+ if (_audio_processor) {
+ root->add_child("AudioProcessor")->add_child_text (_audio_processor->id ());
+ }
_playlist->as_xml (root->add_child ("Playlist"));
return doc;
}
_key = dcp::Key (f.string_child ("Key"));
+ if (f.optional_string_child ("AudioProcessor")) {
+ _audio_processor = AudioProcessor::from_id (f.string_child ("AudioProcessor"));
+ } else {
+ _audio_processor = 0;
+ }
+
list<string> notes;
/* This method is the only one that can return notes (so far) */
_playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist"), _state_version, notes);
/* Find all mapped channels */
- list<dcp::Channel> mapped;
+ 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<dcp::Channel> c = ac->audio_mapping().mapped_dcp_channels ();
+ list<int> c = ac->audio_mapping().mapped_output_channels ();
copy (c.begin(), c.end(), back_inserter (mapped));
}
}
int non_lfe = 0;
int lfe = 0;
- for (list<dcp::Channel>::const_iterator i = mapped.begin(); i != mapped.end(); ++i) {
- if (static_cast<int> (*i) >= audio_channels()) {
+ 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 ((*i) == dcp::LFE) {
+ if (static_cast<dcp::Channel> (*i) == dcp::LFE) {
++lfe;
} else {
++non_lfe;
signal_changed (BURN_SUBTITLES);
}
+void
+Film::set_audio_processor (AudioProcessor const * processor)
+{
+ _audio_processor = processor;
+ signal_changed (AUDIO_PROCESSOR);
+}
+
void
Film::signal_changed (Property p)
{
{
if (p == VideoContentProperty::VIDEO_FRAME_RATE) {
set_video_frame_rate (_playlist->best_dcp_frame_rate ());
- } else if (
- p == AudioContentProperty::AUDIO_MAPPING ||
- p == AudioContentProperty::AUDIO_CHANNELS) {
+ } else if (p == AudioContentProperty::AUDIO_STREAMS) {
signal_changed (NAME);
}
return all;
}
+
+/** Change the gains of the supplied AudioMapping to make it a default
+ * for this film. The defaults are guessed based on what processor (if any)
+ * is in use and the number of input channels.
+ */
+void
+Film::make_audio_mapping_default (AudioMapping& mapping) const
+{
+ if (audio_processor ()) {
+ audio_processor()->make_audio_mapping_default (mapping);
+ } else {
+ mapping.make_zero ();
+ if (mapping.input_channels() == 1) {
+ /* Mono -> Centre */
+ mapping.set (0, static_cast<int> (dcp::CENTRE), 1);
+ } else {
+ /* 1:1 mapping */
+ for (int i = 0; i < min (mapping.input_channels(), mapping.output_channels()); ++i) {
+ mapping.set (i, i, 1);
+ }
+ }
+ }
+}
+
+/** @return The names of the channels that audio contents' outputs are passed into;
+ * this is either the DCP or a AudioProcessor.
+ */
+vector<string>
+Film::audio_output_names () const
+{
+ if (audio_processor ()) {
+ return audio_processor()->input_names ();
+ }
+
+ vector<string> n;
+ n.push_back (_("L"));
+ n.push_back (_("R"));
+ n.push_back (_("C"));
+ n.push_back (_("Lfe"));
+ n.push_back (_("Ls"));
+ n.push_back (_("Rs"));
+ n.push_back (_("HI"));
+ n.push_back (_("VI"));
+ n.push_back (_("Lc"));
+ n.push_back (_("Rc"));
+ n.push_back (_("BsL"));
+ n.push_back (_("BsR"));
+
+ return vector<string> (n.begin(), n.begin() + audio_channels ());
+}