#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/date_time.hpp>
+#include <libxml++/libxml++.h>
+#include <libcxml/cxml.h>
#include "film.h"
#include "format.h"
#include "job.h"
#include "filter.h"
-#include "transcoder.h"
#include "util.h"
#include "job_manager.h"
#include "ab_transcode_job.h"
#include "transcode_job.h"
#include "scp_dcp_job.h"
#include "log.h"
-#include "options.h"
#include "exceptions.h"
#include "examine_content_job.h"
#include "scaler.h"
-#include "decoder_factory.h"
#include "config.h"
#include "version.h"
#include "ui_signaller.h"
-#include "video_decoder.h"
-#include "audio_decoder.h"
-#include "sndfile_decoder.h"
#include "analyse_audio_job.h"
+#include "playlist.h"
+#include "player.h"
+#include "ffmpeg_content.h"
+#include "imagemagick_content.h"
+#include "sndfile_content.h"
+#include "dcp_content_type.h"
#include "i18n.h"
using std::min;
using std::make_pair;
using std::endl;
+using std::cout;
+using std::list;
using boost::shared_ptr;
using boost::lexical_cast;
using boost::to_upper_copy;
*/
Film::Film (string d, bool must_exist)
- : _use_dci_name (true)
- , _trust_content_header (true)
+ : _playlist (new Playlist)
+ , _use_dci_name (true)
+ , _trust_content_headers (true)
, _dcp_content_type (0)
- , _format (0)
+ , _format (Format::from_id ("185"))
, _scaler (Scaler::from_id ("bicubic"))
, _trim_start (0)
, _trim_end (0)
- , _dcp_ab (false)
- , _use_content_audio (true)
+ , _trim_type (CPL)
+ , _ab (false)
, _audio_gain (0)
, _audio_delay (0)
- , _still_duration (10)
, _with_subtitles (false)
, _subtitle_offset (0)
, _subtitle_scale (1)
, _j2k_bandwidth (200000000)
, _dci_metadata (Config::instance()->default_dci_metadata ())
, _dcp_frame_rate (0)
- , _source_frame_rate (0)
, _dirty (false)
{
set_dci_date_today ();
+
+ _playlist->ContentChanged.connect (bind (&Film::content_changed, this, _1, _2));
/* Make state.directory a complete path without ..s (where possible)
(Code swiped from Adam Bowen on stackoverflow)
}
}
- _sndfile_stream = SndfileStream::create ();
-
if (must_exist) {
read_metadata ();
}
: boost::enable_shared_from_this<Film> (o)
/* note: the copied film shares the original's log */
, _log (o._log)
+ , _playlist (new Playlist)
, _directory (o._directory)
, _name (o._name)
, _use_dci_name (o._use_dci_name)
- , _content (o._content)
- , _trust_content_header (o._trust_content_header)
+ , _trust_content_headers (o._trust_content_headers)
, _dcp_content_type (o._dcp_content_type)
, _format (o._format)
, _crop (o._crop)
, _scaler (o._scaler)
, _trim_start (o._trim_start)
, _trim_end (o._trim_end)
- , _dcp_ab (o._dcp_ab)
- , _content_audio_stream (o._content_audio_stream)
- , _external_audio (o._external_audio)
- , _use_content_audio (o._use_content_audio)
+ , _trim_type (o._trim_type)
+ , _ab (o._ab)
, _audio_gain (o._audio_gain)
, _audio_delay (o._audio_delay)
- , _still_duration (o._still_duration)
- , _subtitle_stream (o._subtitle_stream)
, _with_subtitles (o._with_subtitles)
, _subtitle_offset (o._subtitle_offset)
, _subtitle_scale (o._subtitle_scale)
, _colour_lut (o._colour_lut)
, _j2k_bandwidth (o._j2k_bandwidth)
, _dci_metadata (o._dci_metadata)
- , _dci_date (o._dci_date)
, _dcp_frame_rate (o._dcp_frame_rate)
- , _size (o._size)
- , _length (o._length)
- , _content_digest (o._content_digest)
- , _content_audio_streams (o._content_audio_streams)
- , _sndfile_stream (o._sndfile_stream)
- , _subtitle_streams (o._subtitle_streams)
- , _source_frame_rate (o._source_frame_rate)
+ , _dci_date (o._dci_date)
, _dirty (o._dirty)
{
+ for (ContentList::const_iterator i = o._content.begin(); i != o._content.end(); ++i) {
+ _content.push_back ((*i)->clone ());
+ }
-}
-
-Film::~Film ()
-{
-
+ _playlist->ContentChanged.connect (bind (&Film::content_changed, this, _1, _2));
+
+ _playlist->setup (_content);
}
string
stringstream s;
s << format()->id()
- << "_" << content_digest()
+ << "_" << _playlist->video_digest()
<< "_" << crop().left << "_" << crop().right << "_" << crop().top << "_" << crop().bottom
<< "_" << _dcp_frame_rate
<< "_" << f.first << "_" << f.second
<< "_" << j2k_bandwidth()
<< "_" << boost::lexical_cast<int> (colour_lut());
- if (dcp_ab()) {
+ if (ab()) {
pair<string, string> fa = Filter::ffmpeg_strings (Config::instance()->reference_filters());
s << "ab_" << Config::instance()->reference_scaler()->id() << "_" << fa.first << "_" << fa.second;
}
}
string
- Film::video_mxf_dir () const
+ Film::internal_video_mxf_dir () const
{
boost::filesystem::path p;
return dir ("video");
}
string
- Film::video_mxf_filename () const
+ Film::internal_video_mxf_filename () const
{
return video_state_identifier() + ".mxf";
}
+ string
+ Film::dcp_video_mxf_filename () const
+ {
+ return filename_safe_name() + "_video.mxf";
+ }
+
+ string
+ Film::dcp_audio_mxf_filename () const
+ {
+ return filename_safe_name() + "_audio.mxf";
+ }
+
+ string
+ Film::filename_safe_name () const
+ {
+ string const n = name ();
+ string o;
+ for (size_t i = 0; i < n.length(); ++i) {
+ if (isalnum (n[i])) {
+ o += n[i];
+ } else {
+ o += "_";
+ }
+ }
+
+ return o;
+ }
+
string
Film::audio_analysis_path () const
{
boost::filesystem::path p;
p /= "analysis";
- p /= content_digest();
+ p /= _playlist->audio_digest();
return file (p.string ());
}
throw BadSettingError (_("name"), _("cannot contain slashes"));
}
- log()->log (String::compose ("DVD-o-matic %1 git %2 using %3", dvdomatic_version, dvdomatic_git_commit, dependency_version_summary()));
+ log()->log (String::compose ("DCP-o-matic %1 git %2 using %3", dcpomatic_version, dcpomatic_git_commit, dependency_version_summary()));
{
char buffer[128];
log()->log (String::compose ("Starting to make DCP on %1", buffer));
}
- log()->log (String::compose ("Content is %1; type %2", content_path(), (content_type() == STILL ? _("still") : _("video"))));
- if (length()) {
- log()->log (String::compose ("Content length %1", length().get()));
- }
- log()->log (String::compose ("Content digest %1", content_digest()));
- log()->log (String::compose ("Content at %1 fps, DCP at %2 fps", source_frame_rate(), dcp_frame_rate()));
+// log()->log (String::compose ("Content is %1; type %2", content_path(), (content_type() == STILL ? _("still") : _("video"))));
+// if (length()) {
+// log()->log (String::compose ("Content length %1", length().get()));
+// }
+// log()->log (String::compose ("Content digest %1", content_digest()));
+// log()->log (String::compose ("Content at %1 fps, DCP at %2 fps", source_frame_rate(), dcp_frame_rate()));
log()->log (String::compose ("%1 threads", Config::instance()->num_local_encoding_threads()));
log()->log (String::compose ("J2K bandwidth %1", j2k_bandwidth()));
-#ifdef DVDOMATIC_DEBUG
- log()->log ("DVD-o-matic built in debug mode.");
+#ifdef DCPOMATIC_DEBUG
+ log()->log ("DCP-o-matic built in debug mode.");
#else
- log()->log ("DVD-o-matic built in optimised mode.");
+ log()->log ("DCP-o-matic built in optimised mode.");
#endif
#ifdef LIBDCP_DEBUG
log()->log ("libdcp built in debug mode.");
throw MissingSettingError (_("name"));
}
- DecodeOptions od;
- od.decode_subtitles = with_subtitles ();
-
shared_ptr<Job> r;
- if (dcp_ab()) {
- r = JobManager::instance()->add (shared_ptr<Job> (new ABTranscodeJob (shared_from_this(), od)));
+ if (ab()) {
+ r = JobManager::instance()->add (shared_ptr<Job> (new ABTranscodeJob (shared_from_this())));
} else {
- r = JobManager::instance()->add (shared_ptr<Job> (new TranscodeJob (shared_from_this(), od)));
+ r = JobManager::instance()->add (shared_ptr<Job> (new TranscodeJob (shared_from_this())));
}
}
-/** Start a job to analyse the audio of our content file */
+/** Start a job to analyse the audio in our Playlist */
void
Film::analyse_audio ()
{
JobManager::instance()->add (_analyse_audio_job);
}
-/** Start a job to examine our content file */
+/** Start a job to examine a piece of content */
void
-Film::examine_content ()
+Film::examine_content (shared_ptr<Content> c)
{
- if (_examine_content_job) {
- return;
- }
-
- _examine_content_job.reset (new ExamineContentJob (shared_from_this()));
- _examine_content_job->Finished.connect (bind (&Film::examine_content_finished, this));
- JobManager::instance()->add (_examine_content_job);
+ shared_ptr<Job> j (new ExamineContentJob (shared_from_this(), c, trust_content_headers ()));
+ JobManager::instance()->add (j);
}
void
_analyse_audio_job.reset ();
}
-void
-Film::examine_content_finished ()
-{
- _examine_content_job.reset ();
-}
-
/** Start a job to send our DCP to the configured TMS */
void
Film::send_dcp_to_tms ()
void
Film::write_metadata () const
{
+ ContentList the_content = content ();
+
boost::mutex::scoped_lock lm (_state_mutex);
boost::filesystem::create_directories (directory());
- string const m = file ("metadata");
- ofstream f (m.c_str ());
- if (!f.good ()) {
- throw CreateFileError (m);
- }
+ xmlpp::Document doc;
+ xmlpp::Element* root = doc.create_root_node ("Metadata");
- f << "version " << state_version << endl;
+ root->add_child("Version")->add_child_text (boost::lexical_cast<string> (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("TrustContentHeaders")->add_child_text (_trust_content_headers ? "1" : "0");
+
- /* User stuff */
- f << "name " << _name << endl;
- f << "use_dci_name " << _use_dci_name << endl;
- f << "content " << _content << endl;
- f << "trust_content_header " << (_trust_content_header ? "1" : "0") << endl;
if (_dcp_content_type) {
- f << "dcp_content_type " << _dcp_content_type->dci_name () << endl;
+ root->add_child("DCPContentType")->add_child_text (_dcp_content_type->dci_name ());
}
++
if (_format) {
- f << "format " << _format->as_metadata () << endl;
- }
- f << "left_crop " << _crop.left << endl;
- f << "right_crop " << _crop.right << endl;
- f << "top_crop " << _crop.top << endl;
- f << "bottom_crop " << _crop.bottom << endl;
- for (vector<Filter const *>::const_iterator i = _filters.begin(); i != _filters.end(); ++i) {
- f << "filter " << (*i)->id () << endl;
+ root->add_child("Format")->add_child_text (_format->id ());
}
- f << "scaler " << _scaler->id () << endl;
- f << "trim_start " << _trim_start << endl;
- f << "trim_end " << _trim_end << endl;
++
+ switch (_trim_type) {
+ case CPL:
- f << "trim_type cpl\n";
++ root->add_child("TrimType")->add_child_text ("CPL");
+ break;
+ case ENCODE:
- f << "trim_type encode\n";
- break;
- }
- f << "dcp_ab " << (_dcp_ab ? "1" : "0") << endl;
- if (_content_audio_stream) {
- f << "selected_content_audio_stream " << _content_audio_stream->to_string() << endl;
++ root->add_child("TrimType")->add_child_text ("Encode");
+ }
- for (vector<string>::const_iterator i = _external_audio.begin(); i != _external_audio.end(); ++i) {
- f << "external_audio " << *i << endl;
- }
- f << "use_content_audio " << (_use_content_audio ? "1" : "0") << endl;
- f << "audio_gain " << _audio_gain << endl;
- f << "audio_delay " << _audio_delay << endl;
- f << "still_duration " << _still_duration << endl;
- if (_subtitle_stream) {
- f << "selected_subtitle_stream " << _subtitle_stream->to_string() << endl;
- }
- f << "with_subtitles " << _with_subtitles << endl;
- f << "subtitle_offset " << _subtitle_offset << endl;
- f << "subtitle_scale " << _subtitle_scale << endl;
- f << "colour_lut " << _colour_lut << endl;
- f << "j2k_bandwidth " << _j2k_bandwidth << endl;
- _dci_metadata.write (f);
- f << "dci_date " << boost::gregorian::to_iso_string (_dci_date) << endl;
- f << "dcp_frame_rate " << _dcp_frame_rate << endl;
- f << "width " << _size.width << endl;
- f << "height " << _size.height << endl;
- f << "length " << _length.get_value_or(0) << endl;
- f << "content_digest " << _content_digest << endl;
-
- for (vector<shared_ptr<AudioStream> >::const_iterator i = _content_audio_streams.begin(); i != _content_audio_streams.end(); ++i) {
- f << "content_audio_stream " << (*i)->to_string () << endl;
- }
-
- f << "external_audio_stream " << _sndfile_stream->to_string() << endl;
++
+ root->add_child("LeftCrop")->add_child_text (boost::lexical_cast<string> (_crop.left));
+ root->add_child("RightCrop")->add_child_text (boost::lexical_cast<string> (_crop.right));
+ root->add_child("TopCrop")->add_child_text (boost::lexical_cast<string> (_crop.top));
+ root->add_child("BottomCrop")->add_child_text (boost::lexical_cast<string> (_crop.bottom));
- for (vector<shared_ptr<SubtitleStream> >::const_iterator i = _subtitle_streams.begin(); i != _subtitle_streams.end(); ++i) {
- f << "subtitle_stream " << (*i)->to_string () << endl;
+ for (vector<Filter const *>::const_iterator i = _filters.begin(); i != _filters.end(); ++i) {
+ root->add_child("Filter")->add_child_text ((*i)->id ());
}
-
- f << "source_frame_rate " << _source_frame_rate << endl;
+
+ root->add_child("Scaler")->add_child_text (_scaler->id ());
+ root->add_child("TrimStart")->add_child_text (boost::lexical_cast<string> (_trim_start));
+ root->add_child("TrimEnd")->add_child_text (boost::lexical_cast<string> (_trim_end));
+ root->add_child("AB")->add_child_text (_ab ? "1" : "0");
+ root->add_child("AudioGain")->add_child_text (boost::lexical_cast<string> (_audio_gain));
+ root->add_child("AudioDelay")->add_child_text (boost::lexical_cast<string> (_audio_delay));
+ root->add_child("WithSubtitles")->add_child_text (_with_subtitles ? "1" : "0");
+ root->add_child("SubtitleOffset")->add_child_text (boost::lexical_cast<string> (_subtitle_offset));
+ root->add_child("SubtitleScale")->add_child_text (boost::lexical_cast<string> (_subtitle_scale));
+ root->add_child("ColourLUT")->add_child_text (boost::lexical_cast<string> (_colour_lut));
+ root->add_child("J2KBandwidth")->add_child_text (boost::lexical_cast<string> (_j2k_bandwidth));
+ _dci_metadata.as_xml (root->add_child ("DCIMetadata"));
+ root->add_child("DCPFrameRate")->add_child_text (boost::lexical_cast<string> (_dcp_frame_rate));
+ root->add_child("DCIDate")->add_child_text (boost::gregorian::to_iso_string (_dci_date));
+ _audio_mapping.as_xml (root->add_child("AudioMapping"));
+
+ for (ContentList::iterator i = the_content.begin(); i != the_content.end(); ++i) {
+ (*i)->as_xml (root->add_child ("Content"));
+ }
+
+ doc.write_to_file_formatted (file ("metadata.xml"));
_dirty = false;
}
{
boost::mutex::scoped_lock lm (_state_mutex);
- _external_audio.clear ();
- _content_audio_streams.clear ();
- _subtitle_streams.clear ();
-
- boost::optional<int> version;
-
- /* Backward compatibility things */
- boost::optional<int> audio_sample_rate;
- boost::optional<int> audio_stream_index;
- boost::optional<int> subtitle_stream_index;
-
- ifstream f (file ("metadata").c_str());
- if (!f.good()) {
- throw OpenFileError (file ("metadata"));
+ if (boost::filesystem::exists (file ("metadata")) && !boost::filesystem::exists (file ("metadata.xml"))) {
+ throw StringError (_("This film was created with an older version of DCP-o-matic, and unfortunately it cannot be loaded into this version. You will need to create a new Film, re-add your content and set it up again. Sorry!"));
}
-
- multimap<string, string> kv = read_key_value (f);
- /* We need version before anything else */
- multimap<string, string>::iterator v = kv.find ("version");
- if (v != kv.end ()) {
- version = atoi (v->second.c_str());
- }
+ cxml::File f (file ("metadata.xml"), "Metadata");
- for (multimap<string, string>::const_iterator i = kv.begin(); i != kv.end(); ++i) {
- string const k = i->first;
- string const v = i->second;
+ _name = f.string_child ("Name");
+ _use_dci_name = f.bool_child ("UseDCIName");
+ _trust_content_headers = f.bool_child ("TrustContentHeaders");
- if (k == "audio_sample_rate") {
- audio_sample_rate = atoi (v.c_str());
+ {
+ optional<string> c = f.optional_string_child ("DCPContentType");
+ if (c) {
+ _dcp_content_type = DCPContentType::from_dci_name (c.get ());
}
+ }
- /* User-specified stuff */
- if (k == "name") {
- _name = v;
- } else if (k == "use_dci_name") {
- _use_dci_name = (v == "1");
- } else if (k == "content") {
- _content = v;
- } else if (k == "trust_content_header") {
- _trust_content_header = (v == "1");
- } else if (k == "dcp_content_type") {
- if (version < 3) {
- _dcp_content_type = DCPContentType::from_pretty_name (v);
- } else {
- _dcp_content_type = DCPContentType::from_dci_name (v);
- }
- } else if (k == "format") {
- _format = Format::from_metadata (v);
- } else if (k == "left_crop") {
- _crop.left = atoi (v.c_str ());
- } else if (k == "right_crop") {
- _crop.right = atoi (v.c_str ());
- } else if (k == "top_crop") {
- _crop.top = atoi (v.c_str ());
- } else if (k == "bottom_crop") {
- _crop.bottom = atoi (v.c_str ());
- } else if (k == "filter") {
- _filters.push_back (Filter::from_id (v));
- } else if (k == "scaler") {
- _scaler = Scaler::from_id (v);
- } else if ( ((!version || version < 2) && k == "dcp_trim_start") || k == "trim_start") {
- _trim_start = atoi (v.c_str ());
- } else if ( ((!version || version < 2) && k == "dcp_trim_end") || k == "trim_end") {
- _trim_end = atoi (v.c_str ());
- } else if (k == "trim_type") {
- if (v == "cpl") {
- _trim_type = CPL;
- } else if (v == "encode") {
- _trim_type = ENCODE;
- }
- } else if (k == "dcp_ab") {
- _dcp_ab = (v == "1");
- } else if (k == "selected_content_audio_stream" || (!version && k == "selected_audio_stream")) {
- if (!version) {
- audio_stream_index = atoi (v.c_str ());
- } else {
- _content_audio_stream = audio_stream_factory (v, version);
- }
- } else if (k == "external_audio") {
- _external_audio.push_back (v);
- } else if (k == "use_content_audio") {
- _use_content_audio = (v == "1");
- } else if (k == "audio_gain") {
- _audio_gain = atof (v.c_str ());
- } else if (k == "audio_delay") {
- _audio_delay = atoi (v.c_str ());
- } else if (k == "still_duration") {
- _still_duration = atoi (v.c_str ());
- } else if (k == "selected_subtitle_stream") {
- if (!version) {
- subtitle_stream_index = atoi (v.c_str ());
- } else {
- _subtitle_stream = subtitle_stream_factory (v, version);
- }
- } else if (k == "with_subtitles") {
- _with_subtitles = (v == "1");
- } else if (k == "subtitle_offset") {
- _subtitle_offset = atoi (v.c_str ());
- } else if (k == "subtitle_scale") {
- _subtitle_scale = atof (v.c_str ());
- } else if (k == "colour_lut") {
- _colour_lut = atoi (v.c_str ());
- } else if (k == "j2k_bandwidth") {
- _j2k_bandwidth = atoi (v.c_str ());
- } else if (k == "dci_date") {
- _dci_date = boost::gregorian::from_undelimited_string (v);
- } else if (k == "dcp_frame_rate") {
- _dcp_frame_rate = atoi (v.c_str ());
+ {
+ optional<string> c = f.optional_string_child ("Format");
+ if (c) {
+ _format = Format::from_id (c.get ());
}
+ }
- _dci_metadata.read (k, v);
-
- /* Cached stuff */
- if (k == "width") {
- _size.width = atoi (v.c_str ());
- } else if (k == "height") {
- _size.height = atoi (v.c_str ());
- } else if (k == "length") {
- int const vv = atoi (v.c_str ());
- if (vv) {
- _length = vv;
- }
- } else if (k == "content_digest") {
- _content_digest = v;
- } else if (k == "content_audio_stream" || (!version && k == "audio_stream")) {
- _content_audio_streams.push_back (audio_stream_factory (v, version));
- } else if (k == "external_audio_stream") {
- _sndfile_stream = audio_stream_factory (v, version);
- } else if (k == "subtitle_stream") {
- _subtitle_streams.push_back (subtitle_stream_factory (v, version));
- } else if (k == "source_frame_rate") {
- _source_frame_rate = atof (v.c_str ());
- } else if (version < 4 && k == "frames_per_second") {
- _source_frame_rate = atof (v.c_str ());
- /* Fill in what would have been used for DCP frame rate by the older version */
- _dcp_frame_rate = best_dcp_frame_rate (_source_frame_rate);
++ {
++ optional<string> c = f.optional_string_child ("TrimType");
++ if (!c || c.get() == "CPL") {
++ _trim_type = CPL;
++ } else if (c && c.get() == "Encode") {
++ _trim_type = ENCODE;
+ }
+ }
+
- if (!version) {
- if (audio_sample_rate) {
- /* version < 1 didn't specify sample rate in the audio streams, so fill it in here */
- for (vector<shared_ptr<AudioStream> >::iterator i = _content_audio_streams.begin(); i != _content_audio_streams.end(); ++i) {
- (*i)->set_sample_rate (audio_sample_rate.get());
- }
- }
+ _crop.left = f.number_child<int> ("LeftCrop");
+ _crop.right = f.number_child<int> ("RightCrop");
+ _crop.top = f.number_child<int> ("TopCrop");
+ _crop.bottom = f.number_child<int> ("BottomCrop");
- /* also the selected stream was specified as an index */
- if (audio_stream_index && audio_stream_index.get() >= 0 && audio_stream_index.get() < (int) _content_audio_streams.size()) {
- _content_audio_stream = _content_audio_streams[audio_stream_index.get()];
+ {
+ list<shared_ptr<cxml::Node> > c = f.node_children ("Filter");
+ for (list<shared_ptr<cxml::Node> >::iterator i = c.begin(); i != c.end(); ++i) {
+ _filters.push_back (Filter::from_id ((*i)->content ()));
}
+ }
- /* similarly the subtitle */
- if (subtitle_stream_index && subtitle_stream_index.get() >= 0 && subtitle_stream_index.get() < (int) _subtitle_streams.size()) {
- _subtitle_stream = _subtitle_streams[subtitle_stream_index.get()];
+ _scaler = Scaler::from_id (f.string_child ("Scaler"));
+ _trim_start = f.number_child<int> ("TrimStart");
+ _trim_end = f.number_child<int> ("TrimEnd");
+ _ab = f.bool_child ("AB");
+ _audio_gain = f.number_child<float> ("AudioGain");
+ _audio_delay = f.number_child<int> ("AudioDelay");
+ _with_subtitles = f.bool_child ("WithSubtitles");
+ _subtitle_offset = f.number_child<float> ("SubtitleOffset");
+ _subtitle_scale = f.number_child<float> ("SubtitleScale");
+ _colour_lut = f.number_child<int> ("ColourLUT");
+ _j2k_bandwidth = f.number_child<int> ("J2KBandwidth");
+ _dci_metadata = DCIMetadata (f.node_child ("DCIMetadata"));
+ _dcp_frame_rate = f.number_child<int> ("DCPFrameRate");
+ _dci_date = boost::gregorian::from_undelimited_string (f.string_child ("DCIDate"));
+
+ list<shared_ptr<cxml::Node> > c = f.node_children ("Content");
+ for (list<shared_ptr<cxml::Node> >::iterator i = c.begin(); i != c.end(); ++i) {
+
+ string const type = (*i)->string_child ("Type");
+ boost::shared_ptr<Content> c;
+
+ if (type == "FFmpeg") {
+ c.reset (new FFmpegContent (*i));
+ } else if (type == "ImageMagick") {
+ c.reset (new ImageMagickContent (*i));
+ } else if (type == "Sndfile") {
+ c.reset (new SndfileContent (*i));
}
+
+ _content.push_back (c);
}
-
+
+ /* This must come after we've loaded the content, as we're looking things up in _content */
+ _audio_mapping.set_from_xml (_content, f.node_child ("AudioMapping"));
+
_dirty = false;
+
+ _playlist->setup (_content);
}
libdcp::Size
return p.string ();
}
-/** @return full path of the content (actual video) file
- * of the Film.
- */
-string
-Film::content_path () const
-{
- boost::mutex::scoped_lock lm (_state_mutex);
- if (boost::filesystem::path(_content).has_root_directory ()) {
- return _content;
- }
-
- return file (_content);
-}
-
-ContentType
-Film::content_type () const
-{
- if (boost::filesystem::is_directory (_content)) {
- /* Directory of images, we assume */
- return VIDEO;
- }
-
- if (still_image_file (_content)) {
- return STILL;
- }
-
- return VIDEO;
-}
-
/** @return The sampling rate that we will resample the audio to */
int
Film::target_audio_sample_rate () const
{
- if (!audio_stream()) {
+ if (!has_audio ()) {
return 0;
}
/* Resample to a DCI-approved sample rate */
- double t = dcp_audio_sample_rate (audio_stream()->sample_rate());
+ double t = dcp_audio_sample_rate (audio_frame_rate());
- FrameRateConversion frc (source_frame_rate(), dcp_frame_rate());
+ FrameRateConversion frc (video_frame_rate(), dcp_frame_rate());
/* Compensate if the DCP is being run at a different frame rate
to the source; that is, if the video is run such that it will
*/
if (frc.change_speed) {
- t *= source_frame_rate() * frc.factor() / dcp_frame_rate();
+ t *= video_frame_rate() * frc.factor() / dcp_frame_rate();
}
return rint (t);
}
-int
-Film::still_duration_in_frames () const
-{
- return still_duration() * source_frame_rate();
-}
-
/** @return a DCI-compliant name for a DCP of this film */
string
Film::dci_name (bool if_created_now) const
}
}
- switch (audio_channels()) {
+ switch (audio_channels ()) {
case 1:
d << "_10";
break;
}
void
-Film::set_content (string c)
-{
- string check = directory ();
-
- boost::filesystem::path slash ("/");
- string platform_slash = slash.make_preferred().string ();
-
- if (!ends_with (check, platform_slash)) {
- check += platform_slash;
- }
-
- if (boost::filesystem::path(c).has_root_directory () && starts_with (c, check)) {
- c = c.substr (_directory.length() + 1);
- }
-
- string old_content;
-
- {
- boost::mutex::scoped_lock lm (_state_mutex);
- if (c == _content) {
- return;
- }
-
- old_content = _content;
- _content = c;
- }
-
- /* Reset streams here in case the new content doesn't have one or the other */
- _content_audio_stream = shared_ptr<AudioStream> ();
- _subtitle_stream = shared_ptr<SubtitleStream> ();
-
- /* Start off using content audio */
- set_use_content_audio (true);
-
- /* Create a temporary decoder so that we can get information
- about the content.
- */
-
- try {
- Decoders d = decoder_factory (shared_from_this(), DecodeOptions());
-
- set_size (d.video->native_size ());
- set_source_frame_rate (d.video->frames_per_second ());
- set_dcp_frame_rate (best_dcp_frame_rate (source_frame_rate ()));
- set_subtitle_streams (d.video->subtitle_streams ());
- if (d.audio) {
- set_content_audio_streams (d.audio->audio_streams ());
- }
-
- {
- boost::mutex::scoped_lock lm (_state_mutex);
- _content = c;
- }
-
- signal_changed (CONTENT);
-
- /* Start off with the first audio and subtitle streams */
- if (d.audio && !d.audio->audio_streams().empty()) {
- set_content_audio_stream (d.audio->audio_streams().front());
- }
-
- if (!d.video->subtitle_streams().empty()) {
- set_subtitle_stream (d.video->subtitle_streams().front());
- }
-
- examine_content ();
-
- } catch (...) {
-
- boost::mutex::scoped_lock lm (_state_mutex);
- _content = old_content;
- throw;
-
- }
-
- /* Default format */
- switch (content_type()) {
- case STILL:
- set_format (Format::from_id ("var-185"));
- break;
- case VIDEO:
- set_format (Format::from_id ("185"));
- break;
- }
-
- /* Still image DCPs must use external audio */
- if (content_type() == STILL) {
- set_use_content_audio (false);
- }
-}
-
-void
-Film::set_trust_content_header (bool t)
+Film::set_trust_content_headers (bool t)
{
{
boost::mutex::scoped_lock lm (_state_mutex);
- _trust_content_header = t;
+ _trust_content_headers = t;
}
- signal_changed (TRUST_CONTENT_HEADER);
+ signal_changed (TRUST_CONTENT_HEADERS);
- if (!_trust_content_header && !content().empty()) {
+ if (!_trust_content_headers && !content().empty()) {
/* We just said that we don't trust the content's header */
- examine_content ();
+ ContentList c = content ();
+ for (ContentList::iterator i = c.begin(); i != c.end(); ++i) {
+ examine_content (*i);
+ }
}
}
signal_changed (TRIM_END);
}
+ void
+ Film::set_trim_type (TrimType t)
+ {
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _trim_type = t;
+ }
+ signal_changed (TRIM_TYPE);
+ }
+
void
-Film::set_dcp_ab (bool a)
-{
- {
- boost::mutex::scoped_lock lm (_state_mutex);
- _dcp_ab = a;
- }
- signal_changed (DCP_AB);
-}
-
-void
-Film::set_content_audio_stream (shared_ptr<AudioStream> s)
-{
- {
- boost::mutex::scoped_lock lm (_state_mutex);
- _content_audio_stream = s;
- }
- signal_changed (CONTENT_AUDIO_STREAM);
-}
-
-void
-Film::set_external_audio (vector<string> a)
-{
- {
- boost::mutex::scoped_lock lm (_state_mutex);
- _external_audio = a;
- }
-
- shared_ptr<SndfileDecoder> decoder (new SndfileDecoder (shared_from_this(), DecodeOptions()));
- if (decoder->audio_stream()) {
- _sndfile_stream = decoder->audio_stream ();
- }
-
- signal_changed (EXTERNAL_AUDIO);
-}
-
-void
-Film::set_use_content_audio (bool e)
+Film::set_ab (bool a)
{
{
boost::mutex::scoped_lock lm (_state_mutex);
- _use_content_audio = e;
+ _ab = a;
}
-
- signal_changed (USE_CONTENT_AUDIO);
+ signal_changed (AB);
}
void
signal_changed (AUDIO_DELAY);
}
-void
-Film::set_still_duration (int d)
-{
- {
- boost::mutex::scoped_lock lm (_state_mutex);
- _still_duration = d;
- }
- signal_changed (STILL_DURATION);
-}
-
-void
-Film::set_subtitle_stream (shared_ptr<SubtitleStream> s)
-{
- {
- boost::mutex::scoped_lock lm (_state_mutex);
- _subtitle_stream = s;
- }
- signal_changed (SUBTITLE_STREAM);
-}
-
void
Film::set_with_subtitles (bool w)
{
}
void
-Film::set_size (libdcp::Size s)
+Film::signal_changed (Property p)
{
{
boost::mutex::scoped_lock lm (_state_mutex);
- _size = s;
+ _dirty = true;
+ }
+
+ switch (p) {
+ case Film::CONTENT:
+ _playlist->setup (content ());
+ set_dcp_frame_rate (best_dcp_frame_rate (video_frame_rate ()));
+ set_audio_mapping (_playlist->default_audio_mapping ());
+ break;
+ default:
+ break;
+ }
+
+ if (ui_signaller) {
+ ui_signaller->emit (boost::bind (boost::ref (Changed), p));
}
- signal_changed (SIZE);
}
void
-Film::set_length (SourceFrame l)
+Film::set_dci_date_today ()
{
- {
- boost::mutex::scoped_lock lm (_state_mutex);
- _length = l;
- }
- signal_changed (LENGTH);
+ _dci_date = boost::gregorian::day_clock::local_day ();
}
-void
-Film::unset_length ()
+string
+Film::info_path (int f) const
{
- {
- boost::mutex::scoped_lock lm (_state_mutex);
- _length = boost::none;
+ boost::filesystem::path p;
+ p /= info_dir ();
+
+ stringstream s;
+ s.width (8);
+ s << setfill('0') << f << ".md5";
+
+ p /= s.str();
+
+ /* info_dir() will already have added any initial bit of the path,
+ so don't call file() on this.
+ */
+ return p.string ();
+}
+
+string
+Film::j2c_path (int f, bool t) const
+{
+ boost::filesystem::path p;
+ p /= "j2c";
+ p /= video_state_identifier ();
+
+ stringstream s;
+ s.width (8);
+ s << setfill('0') << f << ".j2c";
+
+ if (t) {
+ s << ".tmp";
}
- signal_changed (LENGTH);
+
+ p /= s.str();
+ return file (p.string ());
}
-void
-Film::set_content_digest (string d)
+/** Make an educated guess as to whether we have a complete DCP
+ * or not.
+ * @return true if we do.
+ */
+
+bool
+Film::have_dcp () const
{
- {
- boost::mutex::scoped_lock lm (_state_mutex);
- _content_digest = d;
+ try {
+ libdcp::DCP dcp (dir (dcp_name()));
+ dcp.read ();
+ } catch (...) {
+ return false;
}
- _dirty = true;
+
+ return true;
+}
+
+shared_ptr<Player>
+Film::player () const
+{
+ boost::mutex::scoped_lock lm (_state_mutex);
+ return shared_ptr<Player> (new Player (shared_from_this (), _playlist));
}
void
-Film::set_content_audio_streams (vector<shared_ptr<AudioStream> > s)
+Film::add_content (shared_ptr<Content> c)
{
{
boost::mutex::scoped_lock lm (_state_mutex);
- _content_audio_streams = s;
+ _content.push_back (c);
}
- signal_changed (CONTENT_AUDIO_STREAMS);
+
+ signal_changed (CONTENT);
+
+ examine_content (c);
}
void
-Film::set_subtitle_streams (vector<shared_ptr<SubtitleStream> > s)
+Film::remove_content (shared_ptr<Content> c)
{
{
boost::mutex::scoped_lock lm (_state_mutex);
- _subtitle_streams = s;
+ ContentList::iterator i = find (_content.begin(), _content.end(), c);
+ if (i != _content.end ()) {
+ _content.erase (i);
+ }
}
- signal_changed (SUBTITLE_STREAMS);
+
+ signal_changed (CONTENT);
}
void
-Film::set_source_frame_rate (float f)
+Film::move_content_earlier (shared_ptr<Content> c)
{
{
boost::mutex::scoped_lock lm (_state_mutex);
- _source_frame_rate = f;
+ ContentList::iterator i = find (_content.begin(), _content.end(), c);
+ if (i == _content.begin () || i == _content.end()) {
+ return;
+ }
+
+ ContentList::iterator j = i;
+ --j;
+
+ swap (*i, *j);
}
- signal_changed (SOURCE_FRAME_RATE);
+
+ signal_changed (CONTENT);
}
-
+
void
-Film::signal_changed (Property p)
+Film::move_content_later (shared_ptr<Content> c)
{
{
boost::mutex::scoped_lock lm (_state_mutex);
- _dirty = true;
- }
+ ContentList::iterator i = find (_content.begin(), _content.end(), c);
+ if (i == _content.end()) {
+ return;
+ }
- if (ui_signaller) {
- ui_signaller->emit (boost::bind (boost::ref (Changed), p));
+ ContentList::iterator j = i;
+ ++j;
+ if (j == _content.end ()) {
+ return;
+ }
+
+ swap (*i, *j);
}
+
+ signal_changed (CONTENT);
+
+}
+
+ContentAudioFrame
+Film::audio_length () const
+{
+ return _playlist->audio_length ();
}
int
Film::audio_channels () const
{
- shared_ptr<AudioStream> s = audio_stream ();
- if (!s) {
- return 0;
- }
-
- return s->channels ();
+ return _playlist->audio_channels ();
}
-void
-Film::set_dci_date_today ()
+int
+Film::audio_frame_rate () const
{
- _dci_date = boost::gregorian::day_clock::local_day ();
+ return _playlist->audio_frame_rate ();
}
-boost::shared_ptr<AudioStream>
-Film::audio_stream () const
+bool
+Film::has_audio () const
{
- if (use_content_audio()) {
- return _content_audio_stream;
- }
+ return _playlist->has_audio ();
+}
- return _sndfile_stream;
+float
+Film::video_frame_rate () const
+{
+ return _playlist->video_frame_rate ();
}
-string
-Film::info_path (int f) const
+libdcp::Size
+Film::video_size () const
{
- boost::filesystem::path p;
- p /= info_dir ();
+ return _playlist->video_size ();
+}
- stringstream s;
- s.width (8);
- s << setfill('0') << f << ".md5";
+ContentVideoFrame
+Film::video_length () const
+{
+ return _playlist->video_length ();
+}
- p /= s.str();
+/** Unfortunately this is needed as the GUI has FFmpeg-specific controls */
+shared_ptr<FFmpegContent>
+Film::ffmpeg () const
+{
+ boost::mutex::scoped_lock lm (_state_mutex);
+
+ for (ContentList::const_iterator i = _content.begin (); i != _content.end(); ++i) {
+ shared_ptr<FFmpegContent> f = boost::dynamic_pointer_cast<FFmpegContent> (*i);
+ if (f) {
+ return f;
+ }
+ }
- /* info_dir() will already have added any initial bit of the path,
- so don't call file() on this.
- */
- return p.string ();
+ return shared_ptr<FFmpegContent> ();
}
-string
-Film::j2c_path (int f, bool t) const
+vector<FFmpegSubtitleStream>
+Film::ffmpeg_subtitle_streams () const
{
- boost::filesystem::path p;
- p /= "j2c";
- p /= video_state_identifier ();
+ shared_ptr<FFmpegContent> f = ffmpeg ();
+ if (f) {
+ return f->subtitle_streams ();
+ }
- stringstream s;
- s.width (8);
- s << setfill('0') << f << ".j2c";
+ return vector<FFmpegSubtitleStream> ();
+}
- if (t) {
- s << ".tmp";
+boost::optional<FFmpegSubtitleStream>
+Film::ffmpeg_subtitle_stream () const
+{
+ shared_ptr<FFmpegContent> f = ffmpeg ();
+ if (f) {
+ return f->subtitle_stream ();
}
- p /= s.str();
- return file (p.string ());
+ return boost::none;
}
-/** Make an educated guess as to whether we have a complete DCP
- * or not.
- * @return true if we do.
- */
+vector<FFmpegAudioStream>
+Film::ffmpeg_audio_streams () const
+{
+ shared_ptr<FFmpegContent> f = ffmpeg ();
+ if (f) {
+ return f->audio_streams ();
+ }
-bool
-Film::have_dcp () const
+ return vector<FFmpegAudioStream> ();
+}
+
+boost::optional<FFmpegAudioStream>
+Film::ffmpeg_audio_stream () const
{
- try {
- libdcp::DCP dcp (dir (dcp_name()));
- dcp.read ();
- } catch (...) {
- return false;
+ shared_ptr<FFmpegContent> f = ffmpeg ();
+ if (f) {
+ return f->audio_stream ();
}
- return true;
+ return boost::none;
}
-bool
-Film::has_audio () const
+void
+Film::set_ffmpeg_subtitle_stream (FFmpegSubtitleStream s)
{
- if (use_content_audio()) {
- return audio_stream();
+ shared_ptr<FFmpegContent> f = ffmpeg ();
+ if (f) {
+ f->set_subtitle_stream (s);
}
+}
- vector<string> const e = external_audio ();
- for (vector<string>::const_iterator i = e.begin(); i != e.end(); ++i) {
- if (!i->empty ()) {
- return true;
- }
+void
+Film::set_ffmpeg_audio_stream (FFmpegAudioStream s)
+{
+ shared_ptr<FFmpegContent> f = ffmpeg ();
+ if (f) {
+ f->set_audio_stream (s);
+ }
+}
+
+void
+Film::set_audio_mapping (AudioMapping m)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _audio_mapping = m;
}
- return false;
+ signal_changed (AUDIO_MAPPING);
}
+void
+Film::content_changed (boost::weak_ptr<Content> c, int p)
+{
+ if (p == VideoContentProperty::VIDEO_FRAME_RATE) {
+ set_dcp_frame_rate (best_dcp_frame_rate (video_frame_rate ()));
+ } else if (p == AudioContentProperty::AUDIO_CHANNELS) {
+ set_audio_mapping (_playlist->default_audio_mapping ());
+ }
+
+ if (ui_signaller) {
+ ui_signaller->emit (boost::bind (boost::ref (ContentChanged), c, p));
+ }
+}
*/
/** @file src/film.h
- * @brief A representation of a piece of video (with sound), including naming,
- * the source content file, and how it should be presented in a DCP.
+ * @brief A representation of some audio and video content, and details of
+ * how they should be presented in a DCP.
*/
-#ifndef DVDOMATIC_FILM_H
-#define DVDOMATIC_FILM_H
+#ifndef DCPOMATIC_FILM_H
+#define DCPOMATIC_FILM_H
#include <string>
#include <vector>
#include <boost/thread.hpp>
#include <boost/signals2.hpp>
#include <boost/enable_shared_from_this.hpp>
-extern "C" {
-#include <libavcodec/avcodec.h>
-}
-#include "dcp_content_type.h"
#include "util.h"
-#include "stream.h"
#include "dci_metadata.h"
+#include "types.h"
+#include "ffmpeg_content.h"
+#include "audio_mapping.h"
+class DCPContentType;
class Format;
class Job;
class Filter;
class ExamineContentJob;
class AnalyseAudioJob;
class ExternalAudioStream;
+class Content;
+class Player;
+class Playlist;
/** @class Film
- * @brief A representation of a video, maybe with sound.
- *
- * A representation of a piece of video (maybe with sound), including naming,
- * the source content file, and how it should be presented in a DCP.
+ * @brief A representation of some audio and video content, and details of
+ * how they should be presented in a DCP.
*/
class Film : public boost::enable_shared_from_this<Film>
{
public:
Film (std::string d, bool must_exist = true);
Film (Film const &);
- ~Film ();
std::string info_dir () const;
std::string j2c_path (int f, bool t) const;
std::string info_path (int f) const;
- std::string video_mxf_dir () const;
- std::string video_mxf_filename () const;
+ std::string internal_video_mxf_dir () const;
+ std::string internal_video_mxf_filename () const;
std::string audio_analysis_path () const;
- void examine_content ();
+ void examine_content (boost::shared_ptr<Content>);
+ std::string dcp_video_mxf_filename () const;
+ std::string dcp_audio_mxf_filename () const;
+
void analyse_audio ();
void send_dcp_to_tms ();
-
void make_dcp ();
/** @return Logger.
std::string file (std::string f) const;
std::string dir (std::string d) const;
- std::string content_path () const;
- ContentType content_type () const;
-
int target_audio_sample_rate () const;
void write_metadata () const;
- void read_metadata ();
libdcp::Size cropped_size (libdcp::Size) const;
std::string dci_name (bool if_created_now) const;
return _dirty;
}
+ bool have_dcp () const;
+
+ boost::shared_ptr<Player> player () const;
+
+ /* Proxies for some Playlist methods */
+
+ ContentAudioFrame audio_length () const;
int audio_channels () const;
+ int audio_frame_rate () const;
+ bool has_audio () const;
+
+ float video_frame_rate () const;
+ libdcp::Size video_size () const;
+ ContentVideoFrame video_length () const;
- void set_dci_date_today ();
+ std::vector<FFmpegSubtitleStream> ffmpeg_subtitle_streams () const;
+ boost::optional<FFmpegSubtitleStream> ffmpeg_subtitle_stream () const;
+ std::vector<FFmpegAudioStream> ffmpeg_audio_streams () const;
+ boost::optional<FFmpegAudioStream> ffmpeg_audio_stream () const;
- bool have_dcp () const;
+ void set_ffmpeg_subtitle_stream (FFmpegSubtitleStream);
+ void set_ffmpeg_audio_stream (FFmpegAudioStream);
+ enum TrimType {
+ CPL,
+ ENCODE
+ };
+
/** Identifiers for the parts of our state;
used for signalling changes.
*/
NONE,
NAME,
USE_DCI_NAME,
+ TRUST_CONTENT_HEADERS,
+ /** The content list has changed (i.e. content has been added, moved around or removed) */
CONTENT,
- TRUST_CONTENT_HEADER,
DCP_CONTENT_TYPE,
FORMAT,
CROP,
SCALER,
TRIM_START,
TRIM_END,
- DCP_AB,
- CONTENT_AUDIO_STREAM,
- EXTERNAL_AUDIO,
- USE_CONTENT_AUDIO,
+ AB,
+ TRIM_TYPE,
AUDIO_GAIN,
AUDIO_DELAY,
- STILL_DURATION,
- SUBTITLE_STREAM,
WITH_SUBTITLES,
SUBTITLE_OFFSET,
SUBTITLE_SCALE,
COLOUR_LUT,
J2K_BANDWIDTH,
DCI_METADATA,
- SIZE,
- LENGTH,
- CONTENT_AUDIO_STREAMS,
- SUBTITLE_STREAMS,
- SOURCE_FRAME_RATE,
- DCP_FRAME_RATE
+ DCP_FRAME_RATE,
+ AUDIO_MAPPING
};
return _use_dci_name;
}
- std::string content () const {
+ bool trust_content_headers () const {
boost::mutex::scoped_lock lm (_state_mutex);
- return _content;
+ return _trust_content_headers;
}
- bool trust_content_header () const {
+ ContentList content () const {
boost::mutex::scoped_lock lm (_state_mutex);
- return _trust_content_header;
+ return _content;
}
DCPContentType const * dcp_content_type () const {
return _trim_end;
}
- bool dcp_ab () const {
+ TrimType trim_type () const {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ return _trim_type;
+ }
+
+ bool ab () const {
boost::mutex::scoped_lock lm (_state_mutex);
- return _dcp_ab;
+ return _ab;
}
- boost::shared_ptr<AudioStream> content_audio_stream () const {
- boost::mutex::scoped_lock lm (_state_mutex);
- return _content_audio_stream;
- }
-
- std::vector<std::string> external_audio () const {
- boost::mutex::scoped_lock lm (_state_mutex);
- return _external_audio;
- }
-
- bool use_content_audio () const {
- boost::mutex::scoped_lock lm (_state_mutex);
- return _use_content_audio;
- }
-
float audio_gain () const {
boost::mutex::scoped_lock lm (_state_mutex);
return _audio_gain;
return _audio_delay;
}
- int still_duration () const {
- boost::mutex::scoped_lock lm (_state_mutex);
- return _still_duration;
- }
-
- int still_duration_in_frames () const;
-
- boost::shared_ptr<SubtitleStream> subtitle_stream () const {
- boost::mutex::scoped_lock lm (_state_mutex);
- return _subtitle_stream;
- }
-
bool with_subtitles () const {
boost::mutex::scoped_lock lm (_state_mutex);
return _with_subtitles;
boost::mutex::scoped_lock lm (_state_mutex);
return _dcp_frame_rate;
}
-
- libdcp::Size size () const {
- boost::mutex::scoped_lock lm (_state_mutex);
- return _size;
- }
-
- boost::optional<SourceFrame> length () const {
- boost::mutex::scoped_lock lm (_state_mutex);
- return _length;
- }
-
- std::string content_digest () const {
- boost::mutex::scoped_lock lm (_state_mutex);
- return _content_digest;
- }
-
- std::vector<boost::shared_ptr<AudioStream> > content_audio_streams () const {
- boost::mutex::scoped_lock lm (_state_mutex);
- return _content_audio_streams;
- }
- std::vector<boost::shared_ptr<SubtitleStream> > subtitle_streams () const {
- boost::mutex::scoped_lock lm (_state_mutex);
- return _subtitle_streams;
- }
-
- float source_frame_rate () const {
+ AudioMapping audio_mapping () const {
boost::mutex::scoped_lock lm (_state_mutex);
- if (content_type() == STILL) {
- return 24;
- }
-
- return _source_frame_rate;
+ return _audio_mapping;
}
- boost::shared_ptr<AudioStream> audio_stream () const;
- bool has_audio () const;
-
/* SET */
void set_directory (std::string);
void set_name (std::string);
void set_use_dci_name (bool);
- void set_content (std::string);
- void set_trust_content_header (bool);
+ void set_trust_content_headers (bool);
+ void add_content (boost::shared_ptr<Content>);
+ void remove_content (boost::shared_ptr<Content>);
+ void move_content_earlier (boost::shared_ptr<Content>);
+ void move_content_later (boost::shared_ptr<Content>);
void set_dcp_content_type (DCPContentType const *);
void set_format (Format const *);
void set_crop (Crop);
void set_scaler (Scaler const *);
void set_trim_start (int);
void set_trim_end (int);
- void set_dcp_ab (bool);
- void set_content_audio_stream (boost::shared_ptr<AudioStream>);
- void set_external_audio (std::vector<std::string>);
- void set_use_content_audio (bool);
+ void set_ab (bool);
+ void set_trim_type (TrimType);
void set_audio_gain (float);
void set_audio_delay (int);
- void set_still_duration (int);
- void set_subtitle_stream (boost::shared_ptr<SubtitleStream>);
void set_with_subtitles (bool);
void set_subtitle_offset (int);
void set_subtitle_scale (float);
void set_j2k_bandwidth (int);
void set_dci_metadata (DCIMetadata);
void set_dcp_frame_rate (int);
- void set_size (libdcp::Size);
- void set_length (SourceFrame);
- void unset_length ();
- void set_content_digest (std::string);
- void set_content_audio_streams (std::vector<boost::shared_ptr<AudioStream> >);
- void set_subtitle_streams (std::vector<boost::shared_ptr<SubtitleStream> >);
- void set_source_frame_rate (float);
-
- /** Emitted when some property has changed */
+ void set_dci_date_today ();
+ void set_audio_mapping (AudioMapping);
+
+ /** Emitted when some property has of the Film has changed */
mutable boost::signals2::signal<void (Property)> Changed;
+ /** Emitted when some property of our content has changed */
+ mutable boost::signals2::signal<void (boost::weak_ptr<Content>, int)> ContentChanged;
+
boost::signals2::signal<void ()> AudioAnalysisSucceeded;
/** Current version number of the state file */
private:
- /** Log to write to */
- boost::shared_ptr<Log> _log;
-
- /** Any running ExamineContentJob, or 0 */
- boost::shared_ptr<ExamineContentJob> _examine_content_job;
- /** Any running AnalyseAudioJob, or 0 */
- boost::shared_ptr<AnalyseAudioJob> _analyse_audio_job;
-
void signal_changed (Property);
- void examine_content_finished ();
void analyse_audio_finished ();
std::string video_state_identifier () const;
+ void read_metadata ();
+ void content_changed (boost::weak_ptr<Content>, int);
+ boost::shared_ptr<FFmpegContent> ffmpeg () const;
+ void setup_default_audio_mapping ();
+ std::string filename_safe_name () const;
+ /** Log to write to */
+ boost::shared_ptr<Log> _log;
+ /** Any running AnalyseAudioJob, or 0 */
+ boost::shared_ptr<AnalyseAudioJob> _analyse_audio_job;
+ boost::shared_ptr<Playlist> _playlist;
+
/** Complete path to directory containing the film metadata;
* must not be relative.
*/
/** Mutex for _directory */
mutable boost::mutex _directory_mutex;
- /** Name for DVD-o-matic */
+ /** Name for DCP-o-matic */
std::string _name;
/** True if a auto-generated DCI-compliant name should be used for our DCP */
bool _use_dci_name;
- /** File or directory containing content; may be relative to our directory
- * or an absolute path.
- */
- std::string _content;
- /** If this is true, we will believe the length specified by the content
- * file's header; if false, we will run through the whole content file
- * the first time we see it in order to obtain the length.
- */
- bool _trust_content_header;
+ bool _trust_content_headers;
+ ContentList _content;
/** The type of content that this Film represents (feature, trailer etc.) */
DCPContentType const * _dcp_content_type;
/** The format to present this Film in (flat, scope, etc.) */
int _trim_start;
/** Frames to trim off the end of the DCP */
int _trim_end;
+ TrimType _trim_type;
/** true to create an A/B comparison DCP, where the left half of the image
is the video without any filters or post-processing, and the right half
has the specified filters and post-processing.
*/
- bool _dcp_ab;
- /** The audio stream to use from our content */
- boost::shared_ptr<AudioStream> _content_audio_stream;
- /** List of filenames of external audio files, in channel order
- (L, R, C, Lfe, Ls, Rs)
- */
- std::vector<std::string> _external_audio;
- /** true to use audio from our content file; false to use external audio */
- bool _use_content_audio;
+ bool _ab;
/** Gain to apply to audio in dB */
float _audio_gain;
/** Delay to apply to audio (positive moves audio later) in milliseconds */
int _audio_delay;
- /** Duration to make still-sourced films (in seconds) */
- int _still_duration;
- boost::shared_ptr<SubtitleStream> _subtitle_stream;
/** True if subtitles should be shown for this film */
bool _with_subtitles;
/** y offset for placing subtitles, in source pixels; +ve is further down
int _colour_lut;
/** bandwidth for J2K files in bits per second */
int _j2k_bandwidth;
-
/** DCI naming stuff */
DCIMetadata _dci_metadata;
- /** The date that we should use in a DCI name */
- boost::gregorian::date _dci_date;
/** Frames per second to run our DCP at */
int _dcp_frame_rate;
-
- /* Data which are cached to speed things up */
-
- /** Size, in pixels, of the source (ignoring cropping) */
- libdcp::Size _size;
- /** The length of the source, in video frames (as far as we know) */
- boost::optional<SourceFrame> _length;
- /** MD5 digest of our content file */
- std::string _content_digest;
- /** The audio streams in our content */
- std::vector<boost::shared_ptr<AudioStream> > _content_audio_streams;
- /** A stream to represent possible external audio (will always exist) */
- boost::shared_ptr<AudioStream> _sndfile_stream;
- /** the subtitle streams that we can use */
- std::vector<boost::shared_ptr<SubtitleStream> > _subtitle_streams;
- /** Frames per second of the source */
- float _source_frame_rate;
+ /** The date that we should use in a DCI name */
+ boost::gregorian::date _dci_date;
+ AudioMapping _audio_mapping;
/** true if our state has changed since we last saved it */
mutable bool _dirty;
#
msgid ""
msgstr ""
-"Project-Id-Version: DVD-o-matic\n"
+"Project-Id-Version: DCP-o-matic\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-04-09 11:14+0100\n"
- "PO-Revision-Date: 2013-04-09 10:13+0100\n"
+ "PO-Revision-Date: 2013-04-10 15:35+0100\n"
"Last-Translator: Adam Klotblixt <adam.klotblixt@gmail.com>\n"
"Language-Team: \n"
- "Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
msgstr "16:9 innanför Flat"
#: src/lib/format.cc:115
- #, fuzzy
msgid "16:9 within Scope"
- msgstr "16:9 innanför Flat"
+ msgstr "16:9 innanför Scope"
#: src/lib/filter.cc:88
msgid "3D denoiser"
#: src/lib/job.cc:72
msgid "An error occurred whilst handling the file %1."
- msgstr "Ett fel inträffade vid hantering av filen (%1)"
+ msgstr "Ett fel inträffade vid hantering av filen %1"
#: src/lib/analyse_audio_job.cc:49
msgid "Analyse audio of %1"
#: src/lib/job.cc:92 src/lib/job.cc:101
msgid ""
"It is not known what caused this error. The best idea is to report the "
-"problem to the DVD-o-matic mailing list (dvdomatic@carlh.net)"
+"problem to the DCP-o-matic mailing list (dcpomatic@carlh.net)"
msgstr ""
"Det är inte känt vad som orsakade detta fel. Bästa sättet att rapportera "
-"problemet är till DVD-o-matics mejl-lista (dvdomatic@carlh.net)"
+"problemet är till DCP-o-matics mejl-lista (dcpomatic@carlh.net)"
#: src/lib/filter.cc:82
msgid "Kernel deinterlacer"
#include <libdcp/sound_asset.h>
#include <libdcp/picture_frame.h>
#include <libdcp/reel.h>
+#include <libdcp/dcp.h>
#include "writer.h"
#include "compose.hpp"
#include "film.h"
#include "format.h"
#include "log.h"
#include "dcp_video_frame.h"
+#include "dcp_content_type.h"
+#include "player.h"
+#include "audio_mapping.h"
#include "i18n.h"
_picture_asset.reset (
new libdcp::MonoPictureAsset (
- _film->video_mxf_dir (),
- _film->video_mxf_filename (),
+ _film->internal_video_mxf_dir (),
+ _film->internal_video_mxf_filename (),
_film->dcp_frame_rate (),
_film->format()->dcp_size ()
)
_picture_asset_writer = _picture_asset->start_write (_first_nonexistant_frame > 0);
- AudioMapping m (_film->audio_channels ());
-
- if (m.dcp_channels() > 0) {
+ if (_film->audio_channels() > 0) {
_sound_asset.reset (
new libdcp::SoundAsset (
_film->dir (_film->dcp_name()),
- N_("audio.mxf"),
+ _film->dcp_audio_mxf_filename (),
_film->dcp_frame_rate (),
- m.dcp_channels (),
- dcp_audio_sample_rate (_film->audio_stream()->sample_rate())
+ _film->audio_mapping().dcp_channels (),
+ dcp_audio_sample_rate (_film->audio_frame_rate())
)
);
}
int const frames = _last_written_frame + 1;
- int const duration = frames - _film->trim_start() - _film->trim_end();
+ int duration = 0;
+ if (_film->trim_type() == Film::CPL) {
+ duration = frames - _film->trim_start() - _film->trim_end();
+ _picture_asset->set_entry_point (_film->trim_start ());
+ } else {
+ duration = frames;
+ }
- _picture_asset->set_entry_point (_film->trim_start ());
_picture_asset->set_duration (duration);
/* Hard-link the video MXF into the DCP */
boost::filesystem::path from;
- from /= _film->video_mxf_dir();
- from /= _film->video_mxf_filename();
+ from /= _film->internal_video_mxf_dir();
+ from /= _film->internal_video_mxf_filename();
boost::filesystem::path to;
to /= _film->dir (_film->dcp_name());
- to /= N_("video.mxf");
+ to /= _film->dcp_video_mxf_filename ();
boost::system::error_code ec;
boost::filesystem::create_hard_link (from, to, ec);
/* And update the asset */
_picture_asset->set_directory (_film->dir (_film->dcp_name ()));
- _picture_asset->set_file_name (N_("video.mxf"));
+ _picture_asset->set_file_name (_film->dcp_video_mxf_filename ());
if (_sound_asset) {
- _sound_asset->set_entry_point (_film->trim_start ());
+ if (_film->trim_type() == Film::CPL) {
+ _sound_asset->set_entry_point (_film->trim_start ());
+ }
_sound_asset->set_duration (duration);
}
{
/* Try to open the existing MXF */
boost::filesystem::path p;
- p /= _film->video_mxf_dir ();
- p /= _film->video_mxf_filename ();
+ p /= _film->internal_video_mxf_dir ();
+ p /= _film->internal_video_mxf_filename ();
FILE* mxf = fopen (p.string().c_str(), N_("rb"));
if (!mxf) {
return;
ab_transcoder.cc
analyse_audio_job.cc
audio_analysis.cc
+ audio_content.cc
audio_decoder.cc
+ audio_mapping.cc
audio_source.cc
config.cc
combiner.cc
+ content.cc
cross.cc
dci_metadata.cc
dcp_content_type.cc
dcp_video_frame.cc
decoder.cc
- decoder_factory.cc
delay_line.cc
dolby_cp750.cc
encoder.cc
exceptions.cc
filter_graph.cc
ffmpeg_compatibility.cc
+ ffmpeg_content.cc
ffmpeg_decoder.cc
film.cc
filter.cc
format.cc
gain.cc
image.cc
+ imagemagick_content.cc
imagemagick_decoder.cc
job.cc
job_manager.cc
log.cc
lut.cc
matcher.cc
+ player.cc
+ playlist.cc
scp_dcp_job.cc
scaler.cc
server.cc
+ sndfile_content.cc
sndfile_decoder.cc
sound_processor.cc
- stream.cc
subtitle.cc
timer.cc
transcode_job.cc
transcoder.cc
+ types.cc
+ trimmer.cc
ui_signaller.cc
util.cc
+ video_content.cc
video_decoder.cc
video_source.cc
writer.cc
else:
obj = bld(features = 'cxx cxxshlib')
- obj.name = 'libdvdomatic'
+ obj.name = 'libdcpomatic'
obj.export_includes = ['.']
obj.uselib = """
AVCODEC AVUTIL AVFORMAT AVFILTER SWSCALE SWRESAMPLE
BOOST_FILESYSTEM BOOST_THREAD BOOST_DATETIME BOOST_SIGNALS2
- SNDFILE OPENJPEG POSTPROC TIFF MAGICK SSH DCP GLIB LZMA
+ SNDFILE OPENJPEG POSTPROC TIFF MAGICK SSH DCP CXML GLIB LZMA
"""
if bld.env.TARGET_WINDOWS:
obj.uselib += ' WINSOCK2'
+ if bld.env.STATIC:
+ obj.uselib += ' XML++'
obj.source = sources + " version.cc"
- obj.target = 'dvdomatic'
+ obj.target = 'dcpomatic'
- i18n.po_to_mo(os.path.join('src', 'lib'), 'libdvdomatic', bld)
+ i18n.po_to_mo(os.path.join('src', 'lib'), 'libdcpomatic', bld)
def pot(bld):
- i18n.pot(os.path.join('src', 'lib'), sources, 'libdvdomatic')
+ i18n.pot(os.path.join('src', 'lib'), sources, 'libdcpomatic')
def pot_merge(bld):
- i18n.pot_merge(os.path.join('src', 'lib'), 'libdvdomatic')
+ i18n.pot_merge(os.path.join('src', 'lib'), 'libdcpomatic')
--- /dev/null
- if (Config::instance()->language()) {
- wxLanguageInfo const * li = wxLocale::FindLanguageInfo (std_to_wx (Config::instance()->language().get()));
+/*
+ Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <iostream>
++#include <fstream>
+#include <boost/filesystem.hpp>
+#ifdef __WXMSW__
+#include <shellapi.h>
+#endif
+#include <wx/aboutdlg.h>
+#include <wx/stdpaths.h>
+#include <wx/cmdline.h>
+#include "wx/film_viewer.h"
+#include "wx/film_editor.h"
+#include "wx/job_manager_view.h"
+#include "wx/config_dialog.h"
+#include "wx/job_wrapper.h"
+#include "wx/wx_util.h"
+#include "wx/new_film_dialog.h"
+#include "wx/properties_dialog.h"
+#include "wx/wx_ui_signaller.h"
+#include "lib/film.h"
+#include "lib/format.h"
+#include "lib/config.h"
+#include "lib/filter.h"
+#include "lib/util.h"
+#include "lib/scaler.h"
+#include "lib/exceptions.h"
+#include "lib/version.h"
+#include "lib/ui_signaller.h"
+#include "lib/log.h"
+
+using std::cout;
+using std::string;
+using std::wstring;
+using std::stringstream;
+using std::map;
+using std::make_pair;
+using std::exception;
++using std::ofstream;
+using boost::shared_ptr;
+
+static FilmEditor* film_editor = 0;
+static FilmViewer* film_viewer = 0;
+static shared_ptr<Film> film;
+static std::string log_level;
+static std::string film_to_load;
+static std::string film_to_create;
+static wxMenu* jobs_menu = 0;
+static wxLocale* locale = 0;
+
+static void set_menu_sensitivity ();
+
+class FilmChangedDialog
+{
+public:
+ FilmChangedDialog ()
+ {
+ _dialog = new wxMessageDialog (
+ 0,
+ wxString::Format (_("Save changes to film \"%s\" before closing?"), std_to_wx (film->name ()).data()),
+ _("Film changed"),
+ wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION
+ );
+ }
+
+ ~FilmChangedDialog ()
+ {
+ _dialog->Destroy ();
+ }
+
+ int run ()
+ {
+ return _dialog->ShowModal ();
+ }
+
+private:
+ wxMessageDialog* _dialog;
+};
+
+
+void
+maybe_save_then_delete_film ()
+{
+ if (!film) {
+ return;
+ }
+
+ if (film->dirty ()) {
+ FilmChangedDialog d;
+ switch (d.run ()) {
+ case wxID_NO:
+ break;
+ case wxID_YES:
+ film->write_metadata ();
+ break;
+ }
+ }
+
+ film.reset ();
+}
+
+enum Sensitivity {
+ ALWAYS,
+ NEEDS_FILM
+};
+
+map<wxMenuItem*, Sensitivity> menu_items;
+
+void
+add_item (wxMenu* menu, wxString text, int id, Sensitivity sens)
+{
+ wxMenuItem* item = menu->Append (id, text);
+ menu_items.insert (make_pair (item, sens));
+}
+
+void
+set_menu_sensitivity ()
+{
+ for (map<wxMenuItem*, Sensitivity>::iterator i = menu_items.begin(); i != menu_items.end(); ++i) {
+ if (i->second == NEEDS_FILM) {
+ i->first->Enable (film != 0);
+ } else {
+ i->first->Enable (true);
+ }
+ }
+}
+
+enum {
+ ID_file_new = 1,
+ ID_file_open,
+ ID_file_save,
+ ID_file_properties,
+ ID_file_quit,
+ ID_edit_preferences,
+ ID_jobs_make_dcp,
+ ID_jobs_send_dcp_to_tms,
+ ID_jobs_show_dcp,
+ ID_jobs_analyse_audio,
+ ID_help_about
+};
+
+void
+setup_menu (wxMenuBar* m)
+{
+ wxMenu* file = new wxMenu;
+ add_item (file, _("New..."), ID_file_new, ALWAYS);
+ add_item (file, _("&Open..."), ID_file_open, ALWAYS);
+ file->AppendSeparator ();
+ add_item (file, _("&Save"), ID_file_save, NEEDS_FILM);
+ file->AppendSeparator ();
+ add_item (file, _("&Properties..."), ID_file_properties, NEEDS_FILM);
+ file->AppendSeparator ();
+ add_item (file, _("&Quit"), ID_file_quit, ALWAYS);
+
+ wxMenu* edit = new wxMenu;
+ add_item (edit, _("&Preferences..."), ID_edit_preferences, ALWAYS);
+
+ jobs_menu = new wxMenu;
+ add_item (jobs_menu, _("&Make DCP"), ID_jobs_make_dcp, NEEDS_FILM);
+ add_item (jobs_menu, _("&Send DCP to TMS"), ID_jobs_send_dcp_to_tms, NEEDS_FILM);
+ add_item (jobs_menu, _("S&how DCP"), ID_jobs_show_dcp, NEEDS_FILM);
+ jobs_menu->AppendSeparator ();
+ add_item (jobs_menu, _("&Analyse audio"), ID_jobs_analyse_audio, NEEDS_FILM);
+
+ wxMenu* help = new wxMenu;
+ add_item (help, _("About"), ID_help_about, ALWAYS);
+
+ m->Append (file, _("&File"));
+ m->Append (edit, _("&Edit"));
+ m->Append (jobs_menu, _("&Jobs"));
+ m->Append (help, _("&Help"));
+}
+
+bool
+window_closed (wxCommandEvent &)
+{
+ maybe_save_then_delete_film ();
+ return false;
+}
+
+class Frame : public wxFrame
+{
+public:
+ Frame (wxString const & title)
+ : wxFrame (NULL, -1, title)
+ {
+ wxMenuBar* bar = new wxMenuBar;
+ setup_menu (bar);
+ SetMenuBar (bar);
+
+ Connect (ID_file_new, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::file_new));
+ Connect (ID_file_open, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::file_open));
+ Connect (ID_file_save, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::file_save));
+ Connect (ID_file_properties, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::file_properties));
+ Connect (ID_file_quit, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::file_quit));
+ Connect (ID_edit_preferences, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::edit_preferences));
+ Connect (ID_jobs_make_dcp, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_make_dcp));
+ Connect (ID_jobs_send_dcp_to_tms, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_send_dcp_to_tms));
+ Connect (ID_jobs_show_dcp, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_show_dcp));
+ Connect (ID_jobs_analyse_audio, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_analyse_audio));
+ Connect (ID_help_about, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::help_about));
+
+ Connect (wxID_ANY, wxEVT_MENU_OPEN, wxMenuEventHandler (Frame::menu_opened));
+
+ wxPanel* panel = new wxPanel (this);
+ wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
+ s->Add (panel, 1, wxEXPAND);
+ SetSizer (s);
+
+ film_editor = new FilmEditor (film, panel);
+ film_viewer = new FilmViewer (film, panel);
+ JobManagerView* job_manager_view = new JobManagerView (panel);
+
+ _top_sizer = new wxBoxSizer (wxHORIZONTAL);
+ _top_sizer->Add (film_editor, 0, wxALL, 6);
+ _top_sizer->Add (film_viewer, 1, wxEXPAND | wxALL, 6);
+
+ wxBoxSizer* main_sizer = new wxBoxSizer (wxVERTICAL);
+ main_sizer->Add (_top_sizer, 2, wxEXPAND | wxALL, 6);
+ main_sizer->Add (job_manager_view, 1, wxEXPAND | wxALL, 6);
+ panel->SetSizer (main_sizer);
+
+ set_menu_sensitivity ();
+
+ film_editor->FileChanged.connect (bind (&Frame::file_changed, this, _1));
+ if (film) {
+ file_changed (film->directory ());
+ } else {
+ file_changed ("");
+ }
+
+ set_film ();
+
+ film_editor->Connect (wxID_ANY, wxEVT_SIZE, wxSizeEventHandler (Frame::film_editor_sized), 0, this);
+ }
+
+private:
+
+ void film_editor_sized (wxSizeEvent &)
+ {
+ static bool in_layout = false;
+ if (!in_layout) {
+ in_layout = true;
+ _top_sizer->Layout ();
+ in_layout = false;
+ }
+ }
+
+ void menu_opened (wxMenuEvent& ev)
+ {
+ if (ev.GetMenu() != jobs_menu) {
+ return;
+ }
+
+ bool const have_dcp = film && film->have_dcp();
+ jobs_menu->Enable (ID_jobs_send_dcp_to_tms, have_dcp);
+ jobs_menu->Enable (ID_jobs_show_dcp, have_dcp);
+ }
+
+ void set_film ()
+ {
+ film_viewer->set_film (film);
+ film_editor->set_film (film);
+ set_menu_sensitivity ();
+ }
+
+ void file_changed (string f)
+ {
+ stringstream s;
+ s << wx_to_std (_("DCP-o-matic"));
+ if (!f.empty ()) {
+ s << " - " << f;
+ }
+
+ SetTitle (std_to_wx (s.str()));
+ }
+
+ void file_new (wxCommandEvent &)
+ {
+ NewFilmDialog* d = new NewFilmDialog (this);
+ int const r = d->ShowModal ();
+
+ if (r == wxID_OK) {
+
+ if (boost::filesystem::exists (d->get_path())) {
+ error_dialog (this, std_to_wx (String::compose (wx_to_std (_("The directory %1 already exists.")), d->get_path().c_str())));
+ return;
+ }
+
+ maybe_save_then_delete_film ();
+ film.reset (new Film (d->get_path (), false));
+ film->log()->set_level (log_level);
+ film->set_name (boost::filesystem::path (d->get_path()).filename().generic_string());
+ set_film ();
+ }
+
+ d->Destroy ();
+ }
+
+ void file_open (wxCommandEvent &)
+ {
+ wxDirDialog* c = new wxDirDialog (this, _("Select film to open"), wxStandardPaths::Get().GetDocumentsDir(), wxDEFAULT_DIALOG_STYLE | wxDD_DIR_MUST_EXIST);
+ int r;
+ while (1) {
+ r = c->ShowModal ();
+ if (r == wxID_OK && c->GetPath() == wxStandardPaths::Get().GetDocumentsDir()) {
+ error_dialog (this, _("You did not select a folder. Make sure that you select a folder before clicking Open."));
+ } else {
+ break;
+ }
+ }
+
+ if (r == wxID_OK) {
+ maybe_save_then_delete_film ();
+ try {
+ film.reset (new Film (wx_to_std (c->GetPath ())));
+ film->log()->set_level (log_level);
+ set_film ();
+ } catch (std::exception& e) {
+ wxString p = c->GetPath ();
+ wxCharBuffer b = p.ToUTF8 ();
+ error_dialog (this, wxString::Format (_("Could not open film at %s (%s)"), p.data(), std_to_wx (e.what()).data()));
+ }
+ }
+
+ c->Destroy ();
+ }
+
+ void file_save (wxCommandEvent &)
+ {
+ film->write_metadata ();
+ }
+
+ void file_properties (wxCommandEvent &)
+ {
+ PropertiesDialog* d = new PropertiesDialog (this, film);
+ d->ShowModal ();
+ d->Destroy ();
+ }
+
+ void file_quit (wxCommandEvent &)
+ {
+ maybe_save_then_delete_film ();
+ Close (true);
+ }
+
+ void edit_preferences (wxCommandEvent &)
+ {
+ ConfigDialog* d = new ConfigDialog (this);
+ d->ShowModal ();
+ d->Destroy ();
+ Config::instance()->write ();
+ }
+
+ void jobs_make_dcp (wxCommandEvent &)
+ {
+ JobWrapper::make_dcp (this, film);
+ }
+
+ void jobs_send_dcp_to_tms (wxCommandEvent &)
+ {
+ film->send_dcp_to_tms ();
+ }
+
+ void jobs_show_dcp (wxCommandEvent &)
+ {
+#ifdef __WXMSW__
+ string d = film->directory();
+ wstring w;
+ w.assign (d.begin(), d.end());
+ ShellExecute (0, L"open", w.c_str(), 0, 0, SW_SHOWDEFAULT);
+#else
+ int r = system ("which nautilus");
+ if (WEXITSTATUS (r) == 0) {
+ system (string ("nautilus " + film->directory()).c_str ());
+ } else {
+ int r = system ("which konqueror");
+ if (WEXITSTATUS (r) == 0) {
+ system (string ("konqueror " + film->directory()).c_str ());
+ }
+ }
+#endif
+ }
+
+ void jobs_analyse_audio (wxCommandEvent &)
+ {
+ film->analyse_audio ();
+ }
+
+ void help_about (wxCommandEvent &)
+ {
+ wxAboutDialogInfo info;
+ info.SetName (_("DCP-o-matic"));
+ if (strcmp (dcpomatic_git_commit, "release") == 0) {
+ info.SetVersion (std_to_wx (String::compose ("version %1", dcpomatic_version)));
+ } else {
+ info.SetVersion (std_to_wx (String::compose ("version %1 git %2", dcpomatic_version, dcpomatic_git_commit)));
+ }
+ info.SetDescription (_("Free, open-source DCP generation from almost anything."));
+ info.SetCopyright (_("(C) 2012-2013 Carl Hetherington, Terrence Meiczinger, Paul Davis, Ole Laursen"));
+
+ wxArrayString authors;
+ authors.Add (wxT ("Carl Hetherington"));
+ authors.Add (wxT ("Terrence Meiczinger"));
+ authors.Add (wxT ("Paul Davis"));
+ authors.Add (wxT ("Ole Laursen"));
+ info.SetDevelopers (authors);
+
+ wxArrayString translators;
+ translators.Add (wxT ("Olivier Perriere"));
+ translators.Add (wxT ("Lilian Lefranc"));
+ translators.Add (wxT ("Thierry Journet"));
+ translators.Add (wxT ("Massimiliano Broggi"));
+ translators.Add (wxT ("Manuel AC"));
+ translators.Add (wxT ("Adam Klotblixt"));
+ info.SetTranslators (translators);
+
+ info.SetWebSite (wxT ("http://carlh.net/software/dcpomatic"));
+ wxAboutBox (info);
+ }
+
+ wxSizer* _top_sizer;
+};
+
+#if wxMINOR_VERSION == 9
+static const wxCmdLineEntryDesc command_line_description[] = {
+ { wxCMD_LINE_OPTION, "l", "log", "set log level (silent, verbose or timing)", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
+ { wxCMD_LINE_SWITCH, "n", "new", "create new film", wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
+ { wxCMD_LINE_PARAM, 0, 0, "film to load or create", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL },
+ { wxCMD_LINE_NONE, "", "", "", wxCmdLineParamType (0), 0 }
+};
+#else
+static const wxCmdLineEntryDesc command_line_description[] = {
+ { wxCMD_LINE_OPTION, wxT("l"), wxT("log"), wxT("set log level (silent, verbose or timing)"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
+ { wxCMD_LINE_SWITCH, wxT("n"), wxT("new"), wxT("create new film"), wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
+ { wxCMD_LINE_PARAM, 0, 0, wxT("film to load or create"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL },
+ { wxCMD_LINE_NONE, wxT(""), wxT(""), wxT(""), wxCmdLineParamType (0), 0 }
+};
+#endif
+
+void
+setup_i18n ()
+{
+ int language = wxLANGUAGE_DEFAULT;
+
++ ofstream f ("c:/users/carl hetherington/foo", std::ios::app);
++ f << "Hello.\n";
++
++ boost::optional<string> config_lang = Config::instance()->language ();
++ if (config_lang && !config_lang->empty ()) {
++ f << "Configured language " << config_lang.get() << "\n";
++ wxLanguageInfo const * li = wxLocale::FindLanguageInfo (std_to_wx (config_lang.get ()));
++ f << "LanguageInfo " << li << "\n";
+ if (li) {
+ language = li->Language;
++ f << "language=" << language << " cf " << wxLANGUAGE_DEFAULT << " " << wxLANGUAGE_ENGLISH << "\n";
+ }
+ }
+
+ if (wxLocale::IsAvailable (language)) {
++ f << "Language is available.\n";
+ locale = new wxLocale (language, wxLOCALE_LOAD_DEFAULT);
+
+#ifdef DCPOMATIC_WINDOWS
+ locale->AddCatalogLookupPathPrefix (std_to_wx (mo_path().string()));
+#endif
+
+ locale->AddCatalog (wxT ("libdcpomatic-wx"));
+ locale->AddCatalog (wxT ("dcpomatic"));
+
+ if (!locale->IsOk()) {
++ f << "Locale is not ok.\n";
+ delete locale;
+ locale = new wxLocale (wxLANGUAGE_ENGLISH);
+ language = wxLANGUAGE_ENGLISH;
+ }
+ }
+
+ if (locale) {
+ dcpomatic_setup_i18n (wx_to_std (locale->GetCanonicalName ()));
+ }
+}
+
+class App : public wxApp
+{
+ bool OnInit ()
+ {
+ if (!wxApp::OnInit()) {
+ return false;
+ }
+
+#ifdef DCPOMATIC_POSIX
+ unsetenv ("UBUNTU_MENUPROXY");
+#endif
+
+ wxInitAllImageHandlers ();
+
+ /* Enable i18n; this will create a Config object
+ to look for a force-configured language. This Config
+ object will be wrong, however, because dcpomatic_setup
+ hasn't yet been called and there aren't any scalers, filters etc.
+ set up yet.
+ */
+ setup_i18n ();
+
+ /* Set things up, including scalers / filters etc.
+ which will now be internationalised correctly.
+ */
+ dcpomatic_setup ();
+
+ /* Force the configuration to be re-loaded correctly next
+ time it is needed.
+ */
+ Config::drop ();
+
+ if (!film_to_load.empty() && boost::filesystem::is_directory (film_to_load)) {
+ try {
+ film.reset (new Film (film_to_load));
+ film->log()->set_level (log_level);
+ } catch (exception& e) {
+ error_dialog (0, std_to_wx (String::compose (wx_to_std (_("Could not load film %1 (%2)")), film_to_load, e.what())));
+ }
+ }
+
+ if (!film_to_create.empty ()) {
+ film.reset (new Film (film_to_create, false));
+ film->log()->set_level (log_level);
+ film->set_name (boost::filesystem::path (film_to_create).filename().generic_string ());
+ }
+
+ Frame* f = new Frame (_("DCP-o-matic"));
+ SetTopWindow (f);
+ f->Maximize ();
+ f->Show ();
+
+ ui_signaller = new wxUISignaller (this);
+ this->Connect (-1, wxEVT_IDLE, wxIdleEventHandler (App::idle));
+
+ return true;
+ }
+
+ void OnInitCmdLine (wxCmdLineParser& parser)
+ {
+ parser.SetDesc (command_line_description);
+ parser.SetSwitchChars (wxT ("-"));
+ }
+
+ bool OnCmdLineParsed (wxCmdLineParser& parser)
+ {
+ if (parser.GetParamCount() > 0) {
+ if (parser.Found (wxT ("new"))) {
+ film_to_create = wx_to_std (parser.GetParam (0));
+ } else {
+ film_to_load = wx_to_std (parser.GetParam(0));
+ }
+ }
+
+ wxString log;
+ if (parser.Found (wxT ("log"), &log)) {
+ log_level = wx_to_std (log);
+ }
+
+ return true;
+ }
+
+ void idle (wxIdleEvent &)
+ {
+ ui_signaller->ui_idle ();
+ }
+};
+
+IMPLEMENT_APP (App)
*/
/** @file src/config_dialog.cc
- * @brief A dialogue to edit DVD-o-matic configuration.
+ * @brief A dialogue to edit DCP-o-matic configuration.
*/
#include <iostream>
using boost::bind;
ConfigDialog::ConfigDialog (wxWindow* parent)
- : wxDialog (parent, wxID_ANY, _("DVD-o-matic Preferences"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
+ : wxDialog (parent, wxID_ANY, _("DCP-o-matic Preferences"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
wxFlexGridSizer* table = new wxFlexGridSizer (3, 6, 6);
table->AddGrowableCol (1, 1);
table->AddSpacer (0);
table->AddSpacer (0);
- wxStaticText* restart = add_label_to_sizer (table, this, _("(restart DVD-o-matic to see language changes)"));
+ wxStaticText* restart = add_label_to_sizer (table, this, _("(restart DCP-o-matic to see language changes)"));
wxFont font = restart->GetFont();
font.SetStyle (wxFONTSTYLE_ITALIC);
font.SetPointSize (font.GetPointSize() - 1);
{
switch (_language->GetSelection ()) {
case 0:
- Config::instance()->set_language ("");
+ Config::instance()->set_language ("en");
break;
case 1:
Config::instance()->set_language ("fr");
#include <iomanip>
#include <wx/wx.h>
#include <wx/notebook.h>
+#include <wx/listctrl.h>
#include <boost/thread.hpp>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
#include "lib/filter.h"
#include "lib/config.h"
#include "lib/ffmpeg_decoder.h"
+#include "lib/imagemagick_content.h"
+#include "lib/sndfile_content.h"
+#include "lib/dcp_content_type.h"
#include "filter_dialog.h"
#include "wx_util.h"
#include "film_editor.h"
#include "dci_metadata_dialog.h"
#include "scaler.h"
#include "audio_dialog.h"
+#include "imagemagick_content_dialog.h"
+#include "audio_mapping_view.h"
using std::string;
using std::cout;
using std::list;
using std::vector;
using boost::shared_ptr;
+using boost::weak_ptr;
using boost::dynamic_pointer_cast;
+using boost::lexical_cast;
/** @param f Film to edit */
FilmEditor::FilmEditor (shared_ptr<Film> f, wxWindow* parent)
: wxPanel (parent)
- , _film (f)
, _generally_sensitive (true)
, _audio_dialog (0)
{
wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
- SetSizer (s);
_notebook = new wxNotebook (this, wxID_ANY);
s->Add (_notebook, 1);
make_film_panel ();
_notebook->AddPage (_film_panel, _("Film"), true);
+ make_content_panel ();
+ _notebook->AddPage (_content_panel, _("Content"), false);
make_video_panel ();
_notebook->AddPage (_video_panel, _("Video"), false);
make_audio_panel ();
make_subtitle_panel ();
_notebook->AddPage (_subtitle_panel, _("Subtitles"), false);
- set_film (_film);
+ set_film (f);
connect_to_widgets ();
JobManager::instance()->ActiveJobsChanged.connect (
bind (&FilmEditor::active_jobs_changed, this, _1)
);
- setup_visibility ();
setup_formats ();
+
+ SetSizerAndFit (s);
}
void
grid->Add (_edit_dci_button, wxGBPosition (r, 1), wxDefaultSpan);
++r;
- add_label_to_grid_bag_sizer (grid, _film_panel, _("Content"), wxGBPosition (r, 0));
- _content = new wxFilePickerCtrl (_film_panel, wxID_ANY, wxT (""), _("Select Content File"), wxT("*.*"));
- grid->Add (_content, wxGBPosition (r, 1), wxDefaultSpan, wxEXPAND);
- ++r;
-
- _trust_content_header = new wxCheckBox (_film_panel, wxID_ANY, _("Trust content's header"));
- video_control (_trust_content_header);
- grid->Add (_trust_content_header, wxGBPosition (r, 0), wxGBSpan(1, 2));
+ _trust_content_headers = new wxCheckBox (_film_panel, wxID_ANY, _("Trust content's header"));
+ grid->Add (_trust_content_headers, wxGBPosition (r, 0), wxGBSpan(1, 2));
++r;
add_label_to_grid_bag_sizer (grid, _film_panel, _("Content Type"), wxGBPosition (r, 0));
grid->Add (_dcp_content_type, wxGBPosition (r, 1));
++r;
- video_control (add_label_to_grid_bag_sizer (grid, _film_panel, _("Original Frame Rate"), wxGBPosition (r, 0)));
- _source_frame_rate = new wxStaticText (_film_panel, wxID_ANY, wxT (""));
- grid->Add (video_control (_source_frame_rate), wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
- ++r;
-
{
add_label_to_grid_bag_sizer (grid, _film_panel, _("DCP Frame Rate"), wxGBPosition (r, 0));
wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
++r;
_frame_rate_description = new wxStaticText (_film_panel, wxID_ANY, wxT ("\n \n "), wxDefaultPosition, wxDefaultSize);
- grid->Add (video_control (_frame_rate_description), wxGBPosition (r, 0), wxGBSpan (1, 2), wxEXPAND | wxALIGN_CENTER_VERTICAL | wxALL, 6);
+ grid->Add (_frame_rate_description, wxGBPosition (r, 0), wxGBSpan (1, 2), wxEXPAND | wxALIGN_CENTER_VERTICAL | wxALL, 6);
wxFont font = _frame_rate_description->GetFont();
font.SetStyle(wxFONTSTYLE_ITALIC);
font.SetPointSize(font.GetPointSize() - 1);
_frame_rate_description->SetFont(font);
++r;
- video_control (add_label_to_grid_bag_sizer (grid, _film_panel, _("Length"), wxGBPosition (r, 0)));
+ add_label_to_grid_bag_sizer (grid, _film_panel, _("Length"), wxGBPosition (r, 0));
_length = new wxStaticText (_film_panel, wxID_ANY, wxT (""));
- grid->Add (video_control (_length), wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
+ grid->Add (_length, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
++r;
{
- video_control (add_label_to_grid_bag_sizer (grid, _film_panel, _("Trim frames"), wxGBPosition (r, 0)));
+ add_label_to_grid_bag_sizer (grid, _film_panel, _("Trim frames"), wxGBPosition (r, 0));
wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
- video_control (add_label_to_sizer (s, _film_panel, _("Start")));
+ add_label_to_sizer (s, _film_panel, _("Start"));
_trim_start = new wxSpinCtrl (_film_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1));
- s->Add (video_control (_trim_start));
- video_control (add_label_to_sizer (s, _film_panel, _("End")));
+ s->Add (_trim_start);
+ add_label_to_sizer (s, _film_panel, _("End"));
_trim_end = new wxSpinCtrl (_film_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1));
- s->Add (video_control (_trim_end));
+ s->Add (_trim_end);
grid->Add (s, wxGBPosition (r, 1));
}
++r;
- video_control (add_label_to_grid_bag_sizer (grid, _film_panel, _("Trim method"), wxGBPosition (r, 0)));
++ add_label_to_grid_bag_sizer (grid, _film_panel, _("Trim method"), wxGBPosition (r, 0));
+ _trim_type = new wxChoice (_film_panel, wxID_ANY);
- grid->Add (video_control (_trim_type), wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
++ grid->Add (_trim_type, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
+ ++r;
+
- _dcp_ab = new wxCheckBox (_film_panel, wxID_ANY, _("A/B"));
- video_control (_dcp_ab);
- grid->Add (_dcp_ab, wxGBPosition (r, 0));
- ++r;
-
- /* STILL-only stuff */
- {
- still_control (add_label_to_grid_bag_sizer (grid, _film_panel, _("Duration"), wxGBPosition (r, 0)));
- wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
- _still_duration = new wxSpinCtrl (_film_panel);
- still_control (_still_duration);
- s->Add (_still_duration, 1, wxEXPAND);
- /// TRANSLATORS: `s' here is an abbreviation for seconds, the unit of time
- still_control (add_label_to_sizer (s, _film_panel, _("s")));
- grid->Add (s, wxGBPosition (r, 1));
- }
+ _ab = new wxCheckBox (_film_panel, wxID_ANY, _("A/B"));
+ grid->Add (_ab, wxGBPosition (r, 0));
++r;
vector<DCPContentType const *> const ct = DCPContentType::all ();
for (list<int>::const_iterator i = dfr.begin(); i != dfr.end(); ++i) {
_dcp_frame_rate->Append (std_to_wx (boost::lexical_cast<string> (*i)));
}
+
+ _trim_type->Append (_("encode all frames and play the subset"));
+ _trim_type->Append (_("encode only the subset"));
}
void
FilmEditor::connect_to_widgets ()
{
- _name->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (FilmEditor::name_changed), 0, this);
- _use_dci_name->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::use_dci_name_toggled), 0, this);
- _edit_dci_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::edit_dci_button_clicked), 0, this);
- _format->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::format_changed), 0, this);
- _trust_content_headers->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::trust_content_headers_changed), 0, this);
- _content->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler (FilmEditor::content_selection_changed), 0, this);
- _content->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler (FilmEditor::content_selection_changed), 0, this);
- _content->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler (FilmEditor::content_activated), 0, this);
- _content_add->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_add_clicked), 0, this);
- _content_remove->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_remove_clicked), 0, this);
- _content_edit->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_edit_clicked), 0, this);
- _content_earlier->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_earlier_clicked), 0, this);
- _content_later->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_later_clicked), 0, this);
- _left_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::left_crop_changed), 0, this);
- _right_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::right_crop_changed), 0, this);
- _top_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::top_crop_changed), 0, this);
- _bottom_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::bottom_crop_changed), 0, this);
- _filters_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::edit_filters_clicked), 0, this);
- _scaler->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::scaler_changed), 0, this);
- _dcp_content_type->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_content_type_changed), 0, this);
- _dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_frame_rate_changed), 0, this);
- _best_dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::best_dcp_frame_rate_clicked), 0, this);
- _ab->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::ab_toggled), 0, this);
- _trim_start->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::trim_start_changed), 0, this);
- _trim_end->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::trim_end_changed), 0, this);
- _with_subtitles->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::with_subtitles_toggled), 0, this);
- _subtitle_offset->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::subtitle_offset_changed), 0, this);
- _subtitle_scale->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::subtitle_scale_changed), 0, this);
- _colour_lut->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::colour_lut_changed), 0, this);
- _j2k_bandwidth->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::j2k_bandwidth_changed), 0, this);
- _ffmpeg_subtitle_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::ffmpeg_subtitle_stream_changed), 0, this);
- _ffmpeg_audio_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::ffmpeg_audio_stream_changed), 0, this);
- _audio_gain->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::audio_gain_changed), 0, this);
- _name->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (FilmEditor::name_changed), 0, this);
- _use_dci_name->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::use_dci_name_toggled), 0, this);
- _edit_dci_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::edit_dci_button_clicked), 0, this);
- _format->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::format_changed), 0, this);
- _content->Connect (wxID_ANY, wxEVT_COMMAND_FILEPICKER_CHANGED, wxCommandEventHandler (FilmEditor::content_changed), 0, this);
- _trust_content_header->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::trust_content_header_changed), 0, this);
- _left_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::left_crop_changed), 0, this);
- _right_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::right_crop_changed), 0, this);
- _top_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::top_crop_changed), 0, this);
- _bottom_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::bottom_crop_changed), 0, this);
- _filters_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::edit_filters_clicked), 0, this);
- _scaler->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::scaler_changed), 0, this);
- _dcp_content_type->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_content_type_changed), 0, this);
- _dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_frame_rate_changed), 0, this);
- _best_dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::best_dcp_frame_rate_clicked), 0, this);
- _dcp_ab->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::dcp_ab_toggled), 0, this);
- _still_duration->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::still_duration_changed), 0, this);
- _trim_start->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::trim_start_changed), 0, this);
- _trim_end->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::trim_end_changed), 0, this);
- _trim_type->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::trim_type_changed), 0, this);
- _with_subtitles->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::with_subtitles_toggled), 0, this);
- _subtitle_offset->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::subtitle_offset_changed), 0, this);
- _subtitle_scale->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::subtitle_scale_changed), 0, this);
- _colour_lut->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::colour_lut_changed), 0, this);
- _j2k_bandwidth->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::j2k_bandwidth_changed), 0, this);
- _subtitle_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::subtitle_stream_changed), 0, this);
- _audio_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::audio_stream_changed), 0, this);
- _audio_gain->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::audio_gain_changed), 0, this);
++ _name->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (FilmEditor::name_changed), 0, this);
++ _use_dci_name->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::use_dci_name_toggled), 0, this);
++ _edit_dci_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::edit_dci_button_clicked), 0, this);
++ _format->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::format_changed), 0, this);
++ _trust_content_headers->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::trust_content_headers_changed), 0, this);
++ _content->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler (FilmEditor::content_selection_changed), 0, this);
++ _content->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler (FilmEditor::content_selection_changed), 0, this);
++ _content->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler (FilmEditor::content_activated), 0, this);
++ _content_add->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_add_clicked), 0, this);
++ _content_remove->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_remove_clicked), 0, this);
++ _content_edit->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_edit_clicked), 0, this);
++ _content_earlier->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_earlier_clicked), 0, this);
++ _content_later->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_later_clicked), 0, this);
++ _left_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::left_crop_changed), 0, this);
++ _right_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::right_crop_changed), 0, this);
++ _top_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::top_crop_changed), 0, this);
++ _bottom_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::bottom_crop_changed), 0, this);
++ _filters_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::edit_filters_clicked), 0, this);
++ _scaler->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::scaler_changed), 0, this);
++ _dcp_content_type->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_content_type_changed), 0, this);
++ _dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_frame_rate_changed), 0, this);
++ _best_dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::best_dcp_frame_rate_clicked), 0, this);
++ _ab->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::ab_toggled), 0, this);
++ _trim_start->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::trim_start_changed), 0, this);
++ _trim_end->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::trim_end_changed), 0, this);
++ _trim_type->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::trim_type_changed), 0, this);
++ _with_subtitles->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::with_subtitles_toggled), 0, this);
++ _subtitle_offset->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::subtitle_offset_changed), 0, this);
++ _subtitle_scale->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::subtitle_scale_changed), 0, this);
++ _colour_lut->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::colour_lut_changed), 0, this);
++ _j2k_bandwidth->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::j2k_bandwidth_changed), 0, this);
++ _ffmpeg_subtitle_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::ffmpeg_subtitle_stream_changed), 0, this);
++ _ffmpeg_audio_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::ffmpeg_audio_stream_changed), 0, this);
++ _audio_gain->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::audio_gain_changed), 0, this);
_audio_gain_calculate_button->Connect (
wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::audio_gain_calculate_button_clicked), 0, this
);
- _show_audio->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::show_audio_clicked), 0, this);
- _audio_delay->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::audio_delay_changed), 0, this);
- _show_audio->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::show_audio_clicked), 0, this);
- _audio_delay->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::audio_delay_changed), 0, this);
- _use_content_audio->Connect (wxID_ANY, wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler (FilmEditor::use_audio_changed), 0, this);
- _use_external_audio->Connect (wxID_ANY, wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler (FilmEditor::use_audio_changed), 0, this);
- for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
- _external_audio[i]->Connect (
- wxID_ANY, wxEVT_COMMAND_FILEPICKER_CHANGED, wxCommandEventHandler (FilmEditor::external_audio_changed), 0, this
- );
- }
++ _show_audio->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::show_audio_clicked), 0, this);
++ _audio_delay->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::audio_delay_changed), 0, this);
}
void
/* VIDEO-only stuff */
{
- video_control (add_label_to_grid_bag_sizer (grid, _video_panel, _("Filters"), wxGBPosition (r, 0)));
+ add_label_to_grid_bag_sizer (grid, _video_panel, _("Filters"), wxGBPosition (r, 0));
wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
_filters = new wxStaticText (_video_panel, wxID_ANY, _("None"));
- video_control (_filters);
s->Add (_filters, 1, wxEXPAND | wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM | wxRIGHT, 6);
_filters_button = new wxButton (_video_panel, wxID_ANY, _("Edit..."));
- video_control (_filters_button);
s->Add (_filters_button, 0);
grid->Add (s, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
}
++r;
- video_control (add_label_to_grid_bag_sizer (grid, _video_panel, _("Scaler"), wxGBPosition (r, 0)));
+ add_label_to_grid_bag_sizer (grid, _video_panel, _("Scaler"), wxGBPosition (r, 0));
_scaler = new wxChoice (_video_panel, wxID_ANY);
- grid->Add (video_control (_scaler), wxGBPosition (r, 1));
+ grid->Add (_scaler, wxGBPosition (r, 1));
++r;
vector<Scaler const *> const sc = Scaler::all ();
_top_crop->SetRange (0, 1024);
_right_crop->SetRange (0, 1024);
_bottom_crop->SetRange (0, 1024);
- _still_duration->SetRange (1, 60 * 60);
_trim_start->SetRange (0, 100);
_trim_end->SetRange (0, 100);
_j2k_bandwidth->SetRange (50, 250);
}
+void
+FilmEditor::make_content_panel ()
+{
+ _content_panel = new wxPanel (_notebook);
+ _content_sizer = new wxBoxSizer (wxVERTICAL);
+ _content_panel->SetSizer (_content_sizer);
+
+ {
+ wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
+
+ _content = new wxListCtrl (_content_panel, wxID_ANY, wxDefaultPosition, wxSize (320, 160), wxLC_REPORT | wxLC_NO_HEADER | wxLC_SINGLE_SEL);
+ s->Add (_content, 1, wxEXPAND | wxTOP | wxBOTTOM, 6);
+
+ _content->InsertColumn (0, wxT(""));
+ _content->SetColumnWidth (0, 512);
+
+ wxBoxSizer* b = new wxBoxSizer (wxVERTICAL);
+ _content_add = new wxButton (_content_panel, wxID_ANY, _("Add..."));
+ b->Add (_content_add);
+ _content_remove = new wxButton (_content_panel, wxID_ANY, _("Remove"));
+ b->Add (_content_remove);
+ _content_edit = new wxButton (_content_panel, wxID_ANY, _("Edit..."));
+ b->Add (_content_edit);
+ _content_earlier = new wxButton (_content_panel, wxID_ANY, _("Earlier"));
+ b->Add (_content_earlier);
+ _content_later = new wxButton (_content_panel, wxID_ANY, _("Later"));
+ b->Add (_content_later);
+
+ s->Add (b, 0, wxALL, 4);
+
+ _content_sizer->Add (s, 1, wxEXPAND | wxALL, 6);
+ }
+
+ _content_information = new wxTextCtrl (_content_panel, wxID_ANY, wxT ("\n\n\n\n"), wxDefaultPosition, wxDefaultSize, wxTE_READONLY | wxTE_MULTILINE);
+ _content_sizer->Add (_content_information, 1, wxEXPAND | wxALL, 6);
+}
+
void
FilmEditor::make_audio_panel ()
{
grid->AddSpacer (0);
{
- video_control (add_label_to_sizer (grid, _audio_panel, _("Audio Gain")));
+ add_label_to_sizer (grid, _audio_panel, _("Audio Gain"));
wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
_audio_gain = new wxSpinCtrl (_audio_panel);
- s->Add (video_control (_audio_gain), 1);
- video_control (add_label_to_sizer (s, _audio_panel, _("dB")));
+ s->Add (_audio_gain, 1);
+ add_label_to_sizer (s, _audio_panel, _("dB"));
_audio_gain_calculate_button = new wxButton (_audio_panel, wxID_ANY, _("Calculate..."));
- video_control (_audio_gain_calculate_button);
s->Add (_audio_gain_calculate_button, 1, wxEXPAND);
grid->Add (s);
}
{
- video_control (add_label_to_sizer (grid, _audio_panel, _("Audio Delay")));
+ add_label_to_sizer (grid, _audio_panel, _("Audio Delay"));
wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
_audio_delay = new wxSpinCtrl (_audio_panel);
- s->Add (video_control (_audio_delay), 1);
+ s->Add (_audio_delay, 1);
/// TRANSLATORS: this is an abbreviation for milliseconds, the unit of time
- video_control (add_label_to_sizer (s, _audio_panel, _("ms")));
+ add_label_to_sizer (s, _audio_panel, _("ms"));
grid->Add (s);
}
- {
- _use_content_audio = new wxRadioButton (_audio_panel, wxID_ANY, _("Use content's audio"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
- grid->Add (video_control (_use_content_audio));
- wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
- _audio_stream = new wxChoice (_audio_panel, wxID_ANY);
- s->Add (video_control (_audio_stream), 1);
- _audio = new wxStaticText (_audio_panel, wxID_ANY, wxT (""));
- s->Add (video_control (_audio), 1, wxALIGN_CENTER_VERTICAL | wxLEFT, 8);
- grid->Add (s, 1, wxEXPAND);
- }
-
- _use_external_audio = new wxRadioButton (_audio_panel, wxID_ANY, _("Use external audio"));
- grid->Add (_use_external_audio);
- grid->AddSpacer (0);
-
- for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
- add_label_to_sizer (grid, _audio_panel, std_to_wx (audio_channel_name (i)));
- _external_audio[i] = new wxFilePickerCtrl (_audio_panel, wxID_ANY, wxT (""), _("Select Audio File"), wxT ("*.wav"));
- grid->Add (_external_audio[i], 1, wxEXPAND);
- }
+ {
+ add_label_to_sizer (grid, _audio_panel, _("Audio Stream"));
+ wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
+ _ffmpeg_audio_stream = new wxChoice (_audio_panel, wxID_ANY);
+ s->Add (_ffmpeg_audio_stream, 1);
+ _audio = new wxStaticText (_audio_panel, wxID_ANY, wxT (""));
+ s->Add (_audio, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, 8);
+ grid->Add (s, 1, wxEXPAND);
+ }
+ _audio_mapping = new AudioMappingView (_audio_panel);
+ _audio_sizer->Add (_audio_mapping, 1, wxEXPAND | wxALL, 6);
+
_audio_gain->SetRange (-60, 60);
_audio_delay->SetRange (-1000, 1000);
}
_subtitle_sizer->Add (grid, 0, wxALL, 8);
_with_subtitles = new wxCheckBox (_subtitle_panel, wxID_ANY, _("With Subtitles"));
- video_control (_with_subtitles);
grid->Add (_with_subtitles, 1);
- _subtitle_stream = new wxChoice (_subtitle_panel, wxID_ANY);
- grid->Add (video_control (_subtitle_stream));
+ _ffmpeg_subtitle_stream = new wxChoice (_subtitle_panel, wxID_ANY);
+ grid->Add (_ffmpeg_subtitle_stream);
{
- video_control (add_label_to_sizer (grid, _subtitle_panel, _("Subtitle Offset")));
+ add_label_to_sizer (grid, _subtitle_panel, _("Subtitle Offset"));
wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
_subtitle_offset = new wxSpinCtrl (_subtitle_panel);
s->Add (_subtitle_offset);
- video_control (add_label_to_sizer (s, _subtitle_panel, _("pixels")));
+ add_label_to_sizer (s, _subtitle_panel, _("pixels"));
grid->Add (s);
}
{
- video_control (add_label_to_sizer (grid, _subtitle_panel, _("Subtitle Scale")));
+ add_label_to_sizer (grid, _subtitle_panel, _("Subtitle Scale"));
wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
_subtitle_scale = new wxSpinCtrl (_subtitle_panel);
- s->Add (video_control (_subtitle_scale));
- video_control (add_label_to_sizer (s, _subtitle_panel, _("%")));
+ s->Add (_subtitle_scale);
+ add_label_to_sizer (s, _subtitle_panel, _("%"));
grid->Add (s);
}
_film->set_bottom_crop (_bottom_crop->GetValue ());
}
-/** Called when the content filename has been changed */
void
-FilmEditor::content_changed (wxCommandEvent &)
+FilmEditor::trust_content_headers_changed (wxCommandEvent &)
{
if (!_film) {
return;
}
- try {
- _film->set_content (wx_to_std (_content->GetPath ()));
- } catch (std::exception& e) {
- _content->SetPath (std_to_wx (_film->directory ()));
- error_dialog (this, wxString::Format (_("Could not set content: %s"), std_to_wx (e.what()).data()));
- }
-}
-
-void
-FilmEditor::trust_content_header_changed (wxCommandEvent &)
-{
- if (!_film) {
- return;
- }
-
- _film->set_trust_content_header (_trust_content_header->GetValue ());
+ _film->set_trust_content_headers (_trust_content_headers->GetValue ());
}
/** Called when the DCP A/B switch has been toggled */
void
-FilmEditor::dcp_ab_toggled (wxCommandEvent &)
+FilmEditor::ab_toggled (wxCommandEvent &)
{
if (!_film) {
return;
}
- _film->set_dcp_ab (_dcp_ab->GetValue ());
+ _film->set_ab (_ab->GetValue ());
}
/** Called when the name widget has been changed */
case Film::NONE:
break;
case Film::CONTENT:
- checked_set (_content, _film->content ());
- setup_visibility ();
+ setup_content ();
setup_formats ();
+ setup_format ();
setup_subtitle_control_sensitivity ();
setup_streams ();
setup_show_audio_sensitivity ();
- setup_frame_rate_description ();
- break;
- case Film::TRUST_CONTENT_HEADER:
- checked_set (_trust_content_header, _film->trust_content_header ());
break;
- case Film::SUBTITLE_STREAMS:
- setup_subtitle_control_sensitivity ();
- setup_streams ();
- break;
- case Film::CONTENT_AUDIO_STREAMS:
- setup_streams ();
- setup_show_audio_sensitivity ();
- setup_frame_rate_description ();
+ case Film::TRUST_CONTENT_HEADERS:
+ checked_set (_trust_content_headers, _film->trust_content_headers ());
break;
case Film::FORMAT:
- {
- int n = 0;
- vector<Format const *>::iterator i = _formats.begin ();
- while (i != _formats.end() && *i != _film->format ()) {
- ++i;
- ++n;
- }
- if (i == _formats.end()) {
- checked_set (_format, -1);
- } else {
- checked_set (_format, n);
- }
- setup_dcp_name ();
- setup_scaling_description ();
+ setup_format ();
break;
- }
case Film::CROP:
checked_set (_left_crop, _film->crop().left);
checked_set (_right_crop, _film->crop().right);
checked_set (_name, _film->name());
setup_dcp_name ();
break;
- case Film::SOURCE_FRAME_RATE:
- s << fixed << setprecision(2) << _film->source_frame_rate();
- _source_frame_rate->SetLabel (std_to_wx (s.str ()));
- setup_frame_rate_description ();
- break;
- case Film::SIZE:
- setup_scaling_description ();
- break;
- case Film::LENGTH:
- if (_film->source_frame_rate() > 0 && _film->length()) {
- s << _film->length().get() << " "
- << wx_to_std (_("frames")) << "; " << seconds_to_hms (_film->length().get() / _film->source_frame_rate());
- } else if (_film->length()) {
- s << _film->length().get() << " "
- << wx_to_std (_("frames"));
- }
- _length->SetLabel (std_to_wx (s.str ()));
- if (_film->length()) {
- _trim_start->SetRange (0, _film->length().get());
- _trim_end->SetRange (0, _film->length().get());
- }
- break;
case Film::DCP_CONTENT_TYPE:
checked_set (_dcp_content_type, DCPContentType::as_index (_film->dcp_content_type ()));
setup_dcp_name ();
break;
- case Film::DCP_AB:
- checked_set (_dcp_ab, _film->dcp_ab ());
+ case Film::AB:
+ checked_set (_ab, _film->ab ());
break;
case Film::SCALER:
checked_set (_scaler, Scaler::as_index (_film->scaler ()));
case Film::TRIM_END:
checked_set (_trim_end, _film->trim_end());
break;
+ case Film::TRIM_TYPE:
+ checked_set (_trim_type, _film->trim_type() == Film::CPL ? 0 : 1);
+ break;
case Film::AUDIO_GAIN:
checked_set (_audio_gain, _film->audio_gain ());
break;
case Film::AUDIO_DELAY:
checked_set (_audio_delay, _film->audio_delay ());
break;
- case Film::STILL_DURATION:
- checked_set (_still_duration, _film->still_duration ());
- break;
case Film::WITH_SUBTITLES:
checked_set (_with_subtitles, _film->with_subtitles ());
setup_subtitle_control_sensitivity ();
case Film::DCI_METADATA:
setup_dcp_name ();
break;
- case Film::CONTENT_AUDIO_STREAM:
- if (_film->content_audio_stream()) {
- checked_set (_audio_stream, _film->content_audio_stream()->to_string());
- }
- setup_dcp_name ();
- setup_audio_details ();
- setup_audio_control_sensitivity ();
- setup_show_audio_sensitivity ();
- setup_frame_rate_description ();
- break;
- case Film::USE_CONTENT_AUDIO:
- checked_set (_use_content_audio, _film->use_content_audio());
- checked_set (_use_external_audio, !_film->use_content_audio());
- setup_dcp_name ();
- setup_audio_details ();
- setup_audio_control_sensitivity ();
- setup_show_audio_sensitivity ();
- setup_frame_rate_description ();
- break;
- case Film::SUBTITLE_STREAM:
- if (_film->subtitle_stream()) {
- checked_set (_subtitle_stream, _film->subtitle_stream()->to_string());
- }
- break;
- case Film::EXTERNAL_AUDIO:
- {
- vector<string> a = _film->external_audio ();
- for (size_t i = 0; i < a.size() && i < MAX_AUDIO_CHANNELS; ++i) {
- checked_set (_external_audio[i], a[i]);
- }
- setup_audio_details ();
- setup_show_audio_sensitivity ();
- setup_frame_rate_description ();
- break;
- }
case Film::DCP_FRAME_RATE:
for (unsigned int i = 0; i < _dcp_frame_rate->GetCount(); ++i) {
if (wx_to_std (_dcp_frame_rate->GetString(i)) == boost::lexical_cast<string> (_film->dcp_frame_rate())) {
}
}
- if (_film->source_frame_rate()) {
- _best_dcp_frame_rate->Enable (best_dcp_frame_rate (_film->source_frame_rate ()) != _film->dcp_frame_rate ());
+ if (_film->video_frame_rate()) {
+ _best_dcp_frame_rate->Enable (best_dcp_frame_rate (_film->video_frame_rate ()) != _film->dcp_frame_rate ());
} else {
_best_dcp_frame_rate->Disable ();
}
-
setup_frame_rate_description ();
+ break;
+ case Film::AUDIO_MAPPING:
+ _audio_mapping->set_mapping (_film->audio_mapping ());
+ break;
}
}
+void
+FilmEditor::film_content_changed (weak_ptr<Content> content, int property)
+{
+ if (!_film) {
+ /* We call this method ourselves (as well as using it as a signal handler)
+ so _film can be 0.
+ */
+ return;
+ }
+
+ if (property == FFmpegContentProperty::SUBTITLE_STREAMS) {
+ setup_subtitle_control_sensitivity ();
+ setup_streams ();
+ } else if (property == FFmpegContentProperty::AUDIO_STREAMS) {
+ setup_streams ();
+ setup_show_audio_sensitivity ();
+ } else if (property == VideoContentProperty::VIDEO_LENGTH) {
+ setup_length ();
+ boost::shared_ptr<Content> c = content.lock ();
+ if (c && c == selected_content()) {
+ setup_content_information ();
+ }
+ } else if (property == FFmpegContentProperty::AUDIO_STREAM) {
+ if (_film->ffmpeg_audio_stream()) {
+ checked_set (_ffmpeg_audio_stream, boost::lexical_cast<string> (_film->ffmpeg_audio_stream()->id));
+ }
+ setup_dcp_name ();
+ setup_audio_details ();
+ setup_show_audio_sensitivity ();
+ } else if (property == FFmpegContentProperty::SUBTITLE_STREAM) {
+ if (_film->ffmpeg_subtitle_stream()) {
+ checked_set (_ffmpeg_subtitle_stream, boost::lexical_cast<string> (_film->ffmpeg_subtitle_stream()->id));
+ }
+ }
+}
+
+void
+FilmEditor::setup_format ()
+{
+ int n = 0;
+ vector<Format const *>::iterator i = _formats.begin ();
+ while (i != _formats.end() && *i != _film->format ()) {
+ ++i;
+ ++n;
+ }
+
+ if (i == _formats.end()) {
+ checked_set (_format, -1);
+ } else {
+ checked_set (_format, n);
+ }
+
+ setup_dcp_name ();
+ setup_scaling_description ();
+}
+
+void
+FilmEditor::setup_length ()
+{
+ stringstream s;
+ if (_film->video_frame_rate() > 0 && _film->video_length()) {
+ s << _film->video_length() << " "
+ << wx_to_std (_("frames")) << "; " << seconds_to_hms (_film->video_length() / _film->video_frame_rate());
+ } else if (_film->video_length()) {
+ s << _film->video_length() << " "
+ << wx_to_std (_("frames"));
+ }
+ _length->SetLabel (std_to_wx (s.str ()));
+ if (_film->video_length()) {
+ _trim_start->SetRange (0, _film->video_length());
+ _trim_end->SetRange (0, _film->video_length());
+ }
+}
+
void
FilmEditor::setup_frame_rate_description ()
{
wxString d;
int lines = 0;
- if (_film->source_frame_rate()) {
- d << std_to_wx (FrameRateConversion (_film->source_frame_rate(), _film->dcp_frame_rate()).description);
+ if (_film->video_frame_rate()) {
+ d << std_to_wx (FrameRateConversion (_film->video_frame_rate(), _film->dcp_frame_rate()).description);
++lines;
#ifdef HAVE_SWRESAMPLE
- if (_film->audio_stream() && _film->audio_stream()->sample_rate() != _film->target_audio_sample_rate ()) {
+ if (_film->audio_frame_rate() && _film->audio_frame_rate() != _film->target_audio_sample_rate ()) {
d << wxString::Format (
_("Audio will be resampled from %dHz to %dHz\n"),
- _film->audio_stream()->sample_rate(),
+ _film->audio_frame_rate(),
_film->target_audio_sample_rate()
);
++lines;
void
FilmEditor::set_film (shared_ptr<Film> f)
{
- _film = f;
+ set_things_sensitive (f != 0);
- set_things_sensitive (_film != 0);
+ if (_film == f) {
+ return;
+ }
+
+ _film = f;
if (_film) {
_film->Changed.connect (bind (&FilmEditor::film_changed, this, _1));
+ _film->ContentChanged.connect (bind (&FilmEditor::film_content_changed, this, _1, _2));
}
if (_film) {
film_changed (Film::NAME);
film_changed (Film::USE_DCI_NAME);
film_changed (Film::CONTENT);
- film_changed (Film::TRUST_CONTENT_HEADER);
+ film_changed (Film::TRUST_CONTENT_HEADERS);
film_changed (Film::DCP_CONTENT_TYPE);
film_changed (Film::FORMAT);
film_changed (Film::CROP);
film_changed (Film::SCALER);
film_changed (Film::TRIM_START);
film_changed (Film::TRIM_END);
- film_changed (Film::DCP_AB);
- film_changed (Film::CONTENT_AUDIO_STREAM);
- film_changed (Film::EXTERNAL_AUDIO);
- film_changed (Film::USE_CONTENT_AUDIO);
+ film_changed (Film::AB);
+ film_changed (Film::TRIM_TYPE);
film_changed (Film::AUDIO_GAIN);
film_changed (Film::AUDIO_DELAY);
- film_changed (Film::STILL_DURATION);
film_changed (Film::WITH_SUBTITLES);
film_changed (Film::SUBTITLE_OFFSET);
film_changed (Film::SUBTITLE_SCALE);
film_changed (Film::COLOUR_LUT);
film_changed (Film::J2K_BANDWIDTH);
film_changed (Film::DCI_METADATA);
- film_changed (Film::SIZE);
- film_changed (Film::LENGTH);
- film_changed (Film::CONTENT_AUDIO_STREAMS);
- film_changed (Film::SUBTITLE_STREAMS);
- film_changed (Film::SOURCE_FRAME_RATE);
film_changed (Film::DCP_FRAME_RATE);
+ film_changed (Film::AUDIO_MAPPING);
+
+ film_content_changed (boost::shared_ptr<Content> (), FFmpegContentProperty::SUBTITLE_STREAMS);
+ film_content_changed (boost::shared_ptr<Content> (), FFmpegContentProperty::SUBTITLE_STREAM);
+ film_content_changed (boost::shared_ptr<Content> (), FFmpegContentProperty::AUDIO_STREAMS);
+ film_content_changed (boost::shared_ptr<Content> (), FFmpegContentProperty::AUDIO_STREAM);
}
/** Updates the sensitivity of lots of widgets to a given value.
_edit_dci_button->Enable (s);
_format->Enable (s);
_content->Enable (s);
- _trust_content_header->Enable (s);
+ _trust_content_headers->Enable (s);
+ _content->Enable (s);
_left_crop->Enable (s);
_right_crop->Enable (s);
_top_crop->Enable (s);
_bottom_crop->Enable (s);
_filters_button->Enable (s);
_scaler->Enable (s);
- _audio_stream->Enable (s);
+ _ffmpeg_audio_stream->Enable (s);
_dcp_content_type->Enable (s);
_dcp_frame_rate->Enable (s);
_trim_start->Enable (s);
_trim_end->Enable (s);
- _dcp_ab->Enable (s);
+ _ab->Enable (s);
+ _trim_type->Enable (s);
_colour_lut->Enable (s);
_j2k_bandwidth->Enable (s);
_audio_gain->Enable (s);
_audio_gain_calculate_button->Enable (s);
_show_audio->Enable (s);
_audio_delay->Enable (s);
- _still_duration->Enable (s);
setup_subtitle_control_sensitivity ();
- setup_audio_control_sensitivity ();
setup_show_audio_sensitivity ();
+ setup_content_button_sensitivity ();
}
/** Called when the `Edit filters' button has been clicked */
_film->set_audio_delay (_audio_delay->GetValue ());
}
-wxControl *
-FilmEditor::video_control (wxControl* c)
-{
- _video_controls.push_back (c);
- return c;
-}
-
-wxControl *
-FilmEditor::still_control (wxControl* c)
-{
- _still_controls.push_back (c);
- return c;
-}
-
-void
-FilmEditor::setup_visibility ()
-{
- ContentType c = VIDEO;
-
- if (_film) {
- c = _film->content_type ();
- }
-
- for (list<wxControl*>::iterator i = _video_controls.begin(); i != _video_controls.end(); ++i) {
- (*i)->Show (c == VIDEO);
- }
-
- for (list<wxControl*>::iterator i = _still_controls.begin(); i != _still_controls.end(); ++i) {
- (*i)->Show (c == STILL);
- }
-
- setup_notebook_size ();
-}
-
void
FilmEditor::setup_notebook_size ()
{
Fit ();
}
-void
-FilmEditor::still_duration_changed (wxCommandEvent &)
-{
- if (!_film) {
- return;
- }
-
- _film->set_still_duration (_still_duration->GetValue ());
-}
-
void
FilmEditor::trim_start_changed (wxCommandEvent &)
{
void
FilmEditor::setup_formats ()
{
- ContentType c = VIDEO;
-
- if (_film) {
- c = _film->content_type ();
- }
-
- _formats.clear ();
-
- vector<Format const *> fmt = Format::all ();
- for (vector<Format const *>::iterator i = fmt.begin(); i != fmt.end(); ++i) {
- if (c == VIDEO || (c == STILL && dynamic_cast<VariableFormat const *> (*i))) {
- _formats.push_back (*i);
- }
- }
+ _formats = Format::all ();
_format->Clear ();
for (vector<Format const *>::iterator i = _formats.begin(); i != _formats.end(); ++i) {
{
bool h = false;
if (_generally_sensitive && _film) {
- h = !_film->subtitle_streams().empty();
+ h = !_film->ffmpeg_subtitle_streams().empty();
}
_with_subtitles->Enable (h);
j = _film->with_subtitles ();
}
- _subtitle_stream->Enable (j);
+ _ffmpeg_subtitle_stream->Enable (j);
_subtitle_offset->Enable (j);
_subtitle_scale->Enable (j);
}
-void
-FilmEditor::setup_audio_control_sensitivity ()
-{
- _use_content_audio->Enable (_generally_sensitive && _film && !_film->content_audio_streams().empty());
- _use_external_audio->Enable (_generally_sensitive);
-
- bool const source = _generally_sensitive && _use_content_audio->GetValue();
- bool const external = _generally_sensitive && _use_external_audio->GetValue();
-
- _audio_stream->Enable (source);
- for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
- _external_audio[i]->Enable (external);
- }
-}
-
void
FilmEditor::use_dci_name_toggled (wxCommandEvent &)
{
void
FilmEditor::setup_streams ()
{
- _audio_stream->Clear ();
- vector<shared_ptr<AudioStream> > a = _film->content_audio_streams ();
- for (vector<shared_ptr<AudioStream> >::iterator i = a.begin(); i != a.end(); ++i) {
- shared_ptr<FFmpegAudioStream> ffa = dynamic_pointer_cast<FFmpegAudioStream> (*i);
- assert (ffa);
- _audio_stream->Append (std_to_wx (ffa->name()), new wxStringClientData (std_to_wx (ffa->to_string ())));
+ if (!_film) {
+ return;
+ }
+
+ _ffmpeg_audio_stream->Clear ();
+ vector<FFmpegAudioStream> a = _film->ffmpeg_audio_streams ();
+ for (vector<FFmpegAudioStream>::iterator i = a.begin(); i != a.end(); ++i) {
+ _ffmpeg_audio_stream->Append (std_to_wx (i->name), new wxStringClientData (std_to_wx (boost::lexical_cast<string> (i->id))));
}
- if (_film->use_content_audio() && _film->audio_stream()) {
- checked_set (_audio_stream, _film->audio_stream()->to_string());
+ if (_film->ffmpeg_audio_stream()) {
+ checked_set (_ffmpeg_audio_stream, boost::lexical_cast<string> (_film->ffmpeg_audio_stream()->id));
}
- _subtitle_stream->Clear ();
- vector<shared_ptr<SubtitleStream> > s = _film->subtitle_streams ();
- for (vector<shared_ptr<SubtitleStream> >::iterator i = s.begin(); i != s.end(); ++i) {
- _subtitle_stream->Append (std_to_wx ((*i)->name()), new wxStringClientData (std_to_wx ((*i)->to_string ())));
+ _ffmpeg_subtitle_stream->Clear ();
+ vector<FFmpegSubtitleStream> s = _film->ffmpeg_subtitle_streams ();
+ for (vector<FFmpegSubtitleStream>::iterator i = s.begin(); i != s.end(); ++i) {
+ _ffmpeg_subtitle_stream->Append (std_to_wx (i->name), new wxStringClientData (std_to_wx (boost::lexical_cast<string> (i->id))));
}
- if (_film->subtitle_stream()) {
- checked_set (_subtitle_stream, _film->subtitle_stream()->to_string());
+
+ if (_film->ffmpeg_subtitle_stream()) {
+ checked_set (_ffmpeg_subtitle_stream, boost::lexical_cast<string> (_film->ffmpeg_subtitle_stream()->id));
} else {
- _subtitle_stream->SetSelection (wxNOT_FOUND);
+ _ffmpeg_subtitle_stream->SetSelection (wxNOT_FOUND);
}
}
void
-FilmEditor::audio_stream_changed (wxCommandEvent &)
+FilmEditor::ffmpeg_audio_stream_changed (wxCommandEvent &)
{
if (!_film) {
return;
}
- _film->set_content_audio_stream (
- audio_stream_factory (
- string_client_data (_audio_stream->GetClientObject (_audio_stream->GetSelection ())),
- Film::state_version
- )
- );
+ vector<FFmpegAudioStream> a = _film->ffmpeg_audio_streams ();
+ vector<FFmpegAudioStream>::iterator i = a.begin ();
+ string const s = string_client_data (_ffmpeg_audio_stream->GetClientObject (_ffmpeg_audio_stream->GetSelection ()));
+ while (i != a.end() && lexical_cast<string> (i->id) != s) {
+ ++i;
+ }
+
+ if (i != a.end ()) {
+ _film->set_ffmpeg_audio_stream (*i);
+ }
}
void
-FilmEditor::subtitle_stream_changed (wxCommandEvent &)
+FilmEditor::ffmpeg_subtitle_stream_changed (wxCommandEvent &)
{
if (!_film) {
return;
}
- _film->set_subtitle_stream (
- subtitle_stream_factory (
- string_client_data (_subtitle_stream->GetClientObject (_subtitle_stream->GetSelection ())),
- Film::state_version
- )
- );
+ vector<FFmpegSubtitleStream> a = _film->ffmpeg_subtitle_streams ();
+ vector<FFmpegSubtitleStream>::iterator i = a.begin ();
+ string const s = string_client_data (_ffmpeg_subtitle_stream->GetClientObject (_ffmpeg_subtitle_stream->GetSelection ()));
+ while (i != a.end() && lexical_cast<string> (i->id) != s) {
+ ++i;
+ }
+
+ if (i != a.end ()) {
+ _film->set_ffmpeg_subtitle_stream (*i);
+ }
}
void
FilmEditor::setup_audio_details ()
{
- if (!_film->content_audio_stream()) {
+ if (!_film->ffmpeg_audio_stream()) {
_audio->SetLabel (wxT (""));
} else {
wxString s;
- if (_film->audio_stream()->channels() == 1) {
+ if (_film->audio_channels() == 1) {
s << _("1 channel");
} else {
- s << _film->audio_stream()->channels () << wxT (" ") << _("channels");
+ s << _film->audio_channels() << wxT (" ") << _("channels");
}
- s << wxT (", ") << _film->audio_stream()->sample_rate() << _("Hz");
+ s << wxT (", ") << _film->audio_frame_rate() << _("Hz");
_audio->SetLabel (s);
}
set_things_sensitive (!a);
}
-void
-FilmEditor::use_audio_changed (wxCommandEvent &)
-{
- _film->set_use_content_audio (_use_content_audio->GetValue());
-}
-
-void
-FilmEditor::external_audio_changed (wxCommandEvent &)
-{
- vector<string> a;
- for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
- a.push_back (wx_to_std (_external_audio[i]->GetPath()));
- }
-
- _film->set_external_audio (a);
-}
-
void
FilmEditor::setup_dcp_name ()
{
return;
}
- _film->set_dcp_frame_rate (best_dcp_frame_rate (_film->source_frame_rate ()));
+ _film->set_dcp_frame_rate (best_dcp_frame_rate (_film->video_frame_rate ()));
}
void
_show_audio->Enable (_film && _film->has_audio ());
}
+void
+FilmEditor::setup_content ()
+{
+ string selected_summary;
+ int const s = _content->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+ if (s != -1) {
+ selected_summary = wx_to_std (_content->GetItemText (s));
+ }
+
+ _content->DeleteAllItems ();
+
+ ContentList content = _film->content ();
+ for (ContentList::iterator i = content.begin(); i != content.end(); ++i) {
+ int const t = _content->GetItemCount ();
+ _content->InsertItem (t, std_to_wx ((*i)->summary ()));
+ if ((*i)->summary() == selected_summary) {
+ _content->SetItemState (t, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
+ }
+ }
+
+ if (selected_summary.empty () && !content.empty ()) {
+ /* Select the first item of content if non was selected before */
+ _content->SetItemState (0, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
+ }
+}
+
+void
+FilmEditor::content_add_clicked (wxCommandEvent &)
+{
+ wxFileDialog* d = new wxFileDialog (this);
+ int const r = d->ShowModal ();
+ d->Destroy ();
+
+ if (r != wxID_OK) {
+ return;
+ }
+
+ boost::filesystem::path p (wx_to_std (d->GetPath()));
+
+ if (ImageMagickContent::valid_file (p)) {
+ _film->add_content (shared_ptr<ImageMagickContent> (new ImageMagickContent (p)));
+ } else if (SndfileContent::valid_file (p)) {
+ _film->add_content (shared_ptr<SndfileContent> (new SndfileContent (p)));
+ } else {
+ _film->add_content (shared_ptr<FFmpegContent> (new FFmpegContent (p)));
+ }
+
+}
+
+void
+FilmEditor::content_remove_clicked (wxCommandEvent &)
+{
+ shared_ptr<Content> c = selected_content ();
+ if (c) {
+ _film->remove_content (c);
+ }
+}
+
+void
+FilmEditor::content_activated (wxListEvent& ev)
+{
+ ContentList c = _film->content ();
+ assert (ev.GetIndex() >= 0 && size_t (ev.GetIndex()) < c.size ());
+
+ edit_content (c[ev.GetIndex()]);
+}
+
+void
+FilmEditor::content_edit_clicked (wxCommandEvent &)
+{
+ shared_ptr<Content> c = selected_content ();
+ if (!c) {
+ return;
+ }
+
+ edit_content (c);
+}
+
+void
+FilmEditor::edit_content (shared_ptr<Content> c)
+{
+ shared_ptr<ImageMagickContent> im = dynamic_pointer_cast<ImageMagickContent> (c);
+ if (im) {
+ ImageMagickContentDialog* d = new ImageMagickContentDialog (this, im);
+ d->ShowModal ();
+ d->Destroy ();
+
+ im->set_video_length (d->video_length() * 24);
+ }
+}
+
+void
+FilmEditor::content_earlier_clicked (wxCommandEvent &)
+{
+ shared_ptr<Content> c = selected_content ();
+ if (c) {
+ _film->move_content_earlier (c);
+ }
+}
+
+void
+FilmEditor::content_later_clicked (wxCommandEvent &)
+{
+ shared_ptr<Content> c = selected_content ();
+ if (c) {
+ _film->move_content_later (c);
+ }
+}
+
+void
+FilmEditor::content_selection_changed (wxListEvent &)
+{
+ setup_content_button_sensitivity ();
+ setup_content_information ();
+}
+
+void
+FilmEditor::setup_content_information ()
+{
+ shared_ptr<Content> c = selected_content ();
+ if (!c) {
+ _content_information->SetValue (wxT (""));
+ return;
+ }
+
+ _content_information->SetValue (std_to_wx (c->information ()));
+}
+
+void
+FilmEditor::setup_content_button_sensitivity ()
+{
+ _content_add->Enable (_generally_sensitive);
+
+ shared_ptr<Content> selection = selected_content ();
+
+ _content_edit->Enable (selection && _generally_sensitive && dynamic_pointer_cast<ImageMagickContent> (selection));
+ _content_remove->Enable (selection && _generally_sensitive);
+ _content_earlier->Enable (selection && _generally_sensitive);
+ _content_later->Enable (selection && _generally_sensitive);
+}
+
+shared_ptr<Content>
+FilmEditor::selected_content ()
+{
+ int const s = _content->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+ if (s == -1) {
+ return shared_ptr<Content> ();
+ }
+
+ ContentList c = _film->content ();
+ if (s < 0 || size_t (s) >= c.size ()) {
+ return shared_ptr<Content> ();
+ }
+
+ return c[s];
+}
+
void
FilmEditor::setup_scaling_description ()
{
int lines = 0;
- if (_film->size().width && _film->size().height) {
+ if (_film->video_size().width && _film->video_size().height) {
d << wxString::Format (
_("Original video is %dx%d (%.2f:1)\n"),
- _film->size().width, _film->size().height,
- float (_film->size().width) / _film->size().height
+ _film->video_size().width, _film->video_size().height,
+ float (_film->video_size().width) / _film->video_size().height
);
++lines;
}
Crop const crop = _film->crop ();
if (crop.left || crop.right || crop.top || crop.bottom) {
- libdcp::Size const cropped = _film->cropped_size (_film->size ());
+ libdcp::Size const cropped = _film->cropped_size (_film->video_size ());
d << wxString::Format (
_("Cropped to %dx%d (%.2f:1)\n"),
cropped.width, cropped.height,
_scaling_description->SetLabel (d);
}
+
+ void
+ FilmEditor::trim_type_changed (wxCommandEvent &)
+ {
+ _film->set_trim_type (_trim_type->GetSelection () == 0 ? Film::CPL : Film::ENCODE);
+ }
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
+
/** @file src/film_editor.h
* @brief A wx widget to edit a film's metadata, and perform various functions.
*/
#include "lib/film.h"
class wxNotebook;
+class wxListCtrl;
+class wxListEvent;
class Film;
class AudioDialog;
+class AudioMappingView;
/** @class FilmEditor
* @brief A wx widget to edit a film's metadata, and perform various functions.
FilmEditor (boost::shared_ptr<Film>, wxWindow *);
void set_film (boost::shared_ptr<Film>);
- void setup_visibility ();
boost::signals2::signal<void (std::string)> FileChanged;
private:
void make_film_panel ();
+ void make_content_panel ();
void make_video_panel ();
void make_audio_panel ();
void make_subtitle_panel ();
void right_crop_changed (wxCommandEvent &);
void top_crop_changed (wxCommandEvent &);
void bottom_crop_changed (wxCommandEvent &);
- void content_changed (wxCommandEvent &);
- void trust_content_header_changed (wxCommandEvent &);
+ void trust_content_headers_changed (wxCommandEvent &);
+ void content_selection_changed (wxListEvent &);
+ void content_activated (wxListEvent &);
+ void content_add_clicked (wxCommandEvent &);
+ void content_remove_clicked (wxCommandEvent &);
+ void content_edit_clicked (wxCommandEvent &);
+ void content_earlier_clicked (wxCommandEvent &);
+ void content_later_clicked (wxCommandEvent &);
+ void imagemagick_video_length_changed (wxCommandEvent &);
void format_changed (wxCommandEvent &);
void trim_start_changed (wxCommandEvent &);
void trim_end_changed (wxCommandEvent &);
+ void trim_type_changed (wxCommandEvent &);
void dcp_content_type_changed (wxCommandEvent &);
- void dcp_ab_toggled (wxCommandEvent &);
+ void ab_toggled (wxCommandEvent &);
void scaler_changed (wxCommandEvent &);
void audio_gain_changed (wxCommandEvent &);
void audio_gain_calculate_button_clicked (wxCommandEvent &);
void subtitle_scale_changed (wxCommandEvent &);
void colour_lut_changed (wxCommandEvent &);
void j2k_bandwidth_changed (wxCommandEvent &);
- void still_duration_changed (wxCommandEvent &);
- void audio_stream_changed (wxCommandEvent &);
- void subtitle_stream_changed (wxCommandEvent &);
- void use_audio_changed (wxCommandEvent &);
- void external_audio_changed (wxCommandEvent &);
+ void ffmpeg_audio_stream_changed (wxCommandEvent &);
+ void ffmpeg_subtitle_stream_changed (wxCommandEvent &);
void dcp_frame_rate_changed (wxCommandEvent &);
void best_dcp_frame_rate_clicked (wxCommandEvent &);
+ void edit_filters_clicked (wxCommandEvent &);
/* Handle changes to the model */
void film_changed (Film::Property);
-
- /* Button clicks */
- void edit_filters_clicked (wxCommandEvent &);
+ void film_content_changed (boost::weak_ptr<Content>, int);
void set_things_sensitive (bool);
void setup_formats ();
void setup_subtitle_control_sensitivity ();
- void setup_audio_control_sensitivity ();
void setup_streams ();
void setup_audio_details ();
void setup_dcp_name ();
void setup_scaling_description ();
void setup_notebook_size ();
void setup_frame_rate_description ();
+ void setup_content ();
+ void setup_format ();
+ void setup_length ();
+ void setup_content_information ();
+ void setup_content_button_sensitivity ();
- wxControl* video_control (wxControl *);
- wxControl* still_control (wxControl *);
-
void active_jobs_changed (bool);
+ boost::shared_ptr<Content> selected_content ();
+ void edit_content (boost::shared_ptr<Content>);
wxNotebook* _notebook;
wxPanel* _film_panel;
wxSizer* _film_sizer;
+ wxPanel* _content_panel;
+ wxSizer* _content_sizer;
wxPanel* _video_panel;
wxSizer* _video_sizer;
wxPanel* _audio_panel;
wxTextCtrl* _name;
wxStaticText* _dcp_name;
wxCheckBox* _use_dci_name;
+ wxListCtrl* _content;
+ wxButton* _content_add;
+ wxButton* _content_remove;
+ wxButton* _content_edit;
+ wxButton* _content_earlier;
+ wxButton* _content_later;
+ wxTextCtrl* _content_information;
wxButton* _edit_dci_button;
- /** The Film's format */
wxChoice* _format;
+ wxStaticText* _format_description;
+ wxCheckBox* _trust_content_headers;
wxStaticText* _scaling_description;
- /** The Film's content file */
- wxFilePickerCtrl* _content;
- wxCheckBox* _trust_content_header;
- /** The Film's left crop */
wxSpinCtrl* _left_crop;
- /** The Film's right crop */
wxSpinCtrl* _right_crop;
- /** The Film's top crop */
wxSpinCtrl* _top_crop;
- /** The Film's bottom crop */
wxSpinCtrl* _bottom_crop;
- /** Currently-applied filters */
wxStaticText* _filters;
- /** Button to open the filters dialogue */
wxButton* _filters_button;
- /** The Film's scaler */
wxChoice* _scaler;
- wxRadioButton* _use_content_audio;
- wxChoice* _audio_stream;
- wxRadioButton* _use_external_audio;
- wxFilePickerCtrl* _external_audio[MAX_AUDIO_CHANNELS];
- /** The Film's audio gain */
wxSpinCtrl* _audio_gain;
- /** A button to open the gain calculation dialogue */
wxButton* _audio_gain_calculate_button;
wxButton* _show_audio;
- /** The Film's audio delay */
wxSpinCtrl* _audio_delay;
+ wxChoice* _ffmpeg_audio_stream;
+ AudioMappingView* _audio_mapping;
wxCheckBox* _with_subtitles;
- wxChoice* _subtitle_stream;
+ wxChoice* _ffmpeg_subtitle_stream;
wxSpinCtrl* _subtitle_offset;
wxSpinCtrl* _subtitle_scale;
wxChoice* _colour_lut;
wxSpinCtrl* _j2k_bandwidth;
- /** The Film's DCP content type */
wxChoice* _dcp_content_type;
- /** The Film's source frame rate */
- wxStaticText* _source_frame_rate;
wxChoice* _dcp_frame_rate;
wxButton* _best_dcp_frame_rate;
wxStaticText* _frame_rate_description;
- /** The Film's length */
wxStaticText* _length;
/** The Film's audio details */
wxStaticText* _audio;
- /** The Film's duration for still sources */
- wxSpinCtrl* _still_duration;
wxSpinCtrl* _trim_start;
wxSpinCtrl* _trim_end;
+ wxChoice* _trim_type;
/** Selector to generate an A/B comparison DCP */
- wxCheckBox* _dcp_ab;
-
- std::list<wxControl*> _video_controls;
- std::list<wxControl*> _still_controls;
+ wxCheckBox* _ab;
std::vector<Format const *> _formats;
#include "scaler.h"
#include "ffmpeg_decoder.h"
#include "sndfile_decoder.h"
+#include "dcp_content_type.h"
+ #include "trimmer.h"
#define BOOST_TEST_DYN_LINK
-#define BOOST_TEST_MODULE dvdomatic_test
+#define BOOST_TEST_MODULE dcpomatic_test
#include <boost/test/unit_test.hpp>
using std::string;
BOOST_AUTO_TEST_CASE (make_black_test)
{
/* This needs to happen in the first test */
- dvdomatic_setup ();
+ dcpomatic_setup ();
libdcp::Size in_size (512, 512);
libdcp::Size out_size (1024, 1024);
}
}
+ shared_ptr<AudioBuffers> trimmer_test_last;
+
+ void
+ trimmer_test_helper (shared_ptr<AudioBuffers> audio)
+ {
+ trimmer_test_last = audio;
+ }
+
+ /** Test the audio handling of the Trimmer */
+ BOOST_AUTO_TEST_CASE (trimmer_test)
+ {
+ Trimmer trimmer (shared_ptr<Log> (), 25, 75, 200, 48000, 25, 25);
+
+ trimmer.Audio.connect (bind (&trimmer_test_helper, _1));
+
+ /* 21 video frames-worth of audio frames; should be completely stripped */
+ trimmer_test_last.reset ();
+ shared_ptr<AudioBuffers> audio (new AudioBuffers (6, 21 * 1920));
+ trimmer.process_audio (audio);
+ BOOST_CHECK (trimmer_test_last == 0);
+
+ /* 42 more video frames-worth, 4 should be stripped from the start */
+ audio.reset (new AudioBuffers (6, 42 * 1920));
+ trimmer.process_audio (audio);
+ BOOST_CHECK (trimmer_test_last);
+ BOOST_CHECK_EQUAL (trimmer_test_last->frames(), 38 * 1920);
+
+ /* 42 more video frames-worth, should be kept as-is */
+ trimmer_test_last.reset ();
+ audio.reset (new AudioBuffers (6, 42 * 1920));
+ trimmer.process_audio (audio);
+ BOOST_CHECK (trimmer_test_last);
+ BOOST_CHECK_EQUAL (trimmer_test_last->frames(), 42 * 1920);
+
+ /* 25 more video frames-worth, 5 should be trimmed from the end */
+ trimmer_test_last.reset ();
+ audio.reset (new AudioBuffers (6, 25 * 1920));
+ trimmer.process_audio (audio);
+ BOOST_CHECK (trimmer_test_last);
+ BOOST_CHECK_EQUAL (trimmer_test_last->frames(), 20 * 1920);
+
+ /* Now some more; all should be trimmed */
+ trimmer_test_last.reset ();
+ audio.reset (new AudioBuffers (6, 100 * 1920));
+ trimmer.process_audio (audio);
+ BOOST_CHECK (trimmer_test_last == 0);
+ }
+
+
BOOST_AUTO_TEST_CASE (film_metadata_test)
{
setup_test_config ();
BOOST_CHECK (f->filters ().empty());
f->set_name ("fred");
- BOOST_CHECK_THROW (f->set_content ("jim"), OpenFileError);
+// BOOST_CHECK_THROW (f->set_content ("jim"), OpenFileError);
f->set_dcp_content_type (DCPContentType::from_pretty_name ("Short"));
f->set_format (Format::from_nickname ("Flat"));
f->set_left_crop (1);
f->set_filters (f_filters);
f->set_trim_start (42);
f->set_trim_end (99);
- f->set_dcp_ab (true);
+ f->set_ab (true);
f->write_metadata ();
stringstream s;
BOOST_CHECK_EQUAL (g_filters.back(), Filter::from_id ("unsharp"));
BOOST_CHECK_EQUAL (g->trim_start(), 42);
BOOST_CHECK_EQUAL (g->trim_end(), 99);
- BOOST_CHECK_EQUAL (g->dcp_ab(), true);
+ BOOST_CHECK_EQUAL (g->ab(), true);
g->write_metadata ();
BOOST_CHECK_EQUAL (::system (s.str().c_str ()), 0);
}
-BOOST_AUTO_TEST_CASE (stream_test)
-{
- FFmpegAudioStream a ("ffmpeg 4 44100 1 hello there world", boost::optional<int> (1));
- BOOST_CHECK_EQUAL (a.id(), 4);
- BOOST_CHECK_EQUAL (a.sample_rate(), 44100);
- BOOST_CHECK_EQUAL (a.channel_layout(), 1);
- BOOST_CHECK_EQUAL (a.name(), "hello there world");
- BOOST_CHECK_EQUAL (a.to_string(), "ffmpeg 4 44100 1 hello there world");
-
- SndfileStream e ("external 44100 1", boost::optional<int> (1));
- BOOST_CHECK_EQUAL (e.sample_rate(), 44100);
- BOOST_CHECK_EQUAL (e.channel_layout(), 1);
- BOOST_CHECK_EQUAL (e.to_string(), "external 44100 1");
-
- SubtitleStream s ("5 a b c", boost::optional<int> (1));
- BOOST_CHECK_EQUAL (s.id(), 5);
- BOOST_CHECK_EQUAL (s.name(), "a b c");
-
- shared_ptr<AudioStream> ff = audio_stream_factory ("ffmpeg 4 44100 1 hello there world", boost::optional<int> (1));
- shared_ptr<FFmpegAudioStream> cff = dynamic_pointer_cast<FFmpegAudioStream> (ff);
- BOOST_CHECK (cff);
- BOOST_CHECK_EQUAL (cff->id(), 4);
- BOOST_CHECK_EQUAL (cff->sample_rate(), 44100);
- BOOST_CHECK_EQUAL (cff->channel_layout(), 1);
- BOOST_CHECK_EQUAL (cff->name(), "hello there world");
- BOOST_CHECK_EQUAL (cff->to_string(), "ffmpeg 4 44100 1 hello there world");
-
- shared_ptr<AudioStream> fe = audio_stream_factory ("external 44100 1", boost::optional<int> (1));
- BOOST_CHECK_EQUAL (fe->sample_rate(), 44100);
- BOOST_CHECK_EQUAL (fe->channel_layout(), 1);
- BOOST_CHECK_EQUAL (fe->to_string(), "external 44100 1");
-}
-
BOOST_AUTO_TEST_CASE (format_test)
{
Format::setup_formats ();
Format const * f = Format::from_nickname ("Flat");
BOOST_CHECK (f);
- BOOST_CHECK_EQUAL (f->ratio_as_integer(shared_ptr<const Film> ()), 185);
+// BOOST_CHECK_EQUAL (f->ratio_as_integer(shared_ptr<const Film> ()), 185);
f = Format::from_nickname ("Scope");
BOOST_CHECK (f);
- BOOST_CHECK_EQUAL (f->ratio_as_integer(shared_ptr<const Film> ()), 239);
-}
-
-/* Test VariableFormat-based scaling of content */
-BOOST_AUTO_TEST_CASE (scaling_test)
-{
- shared_ptr<Film> film (new Film (test_film_dir ("scaling_test").string(), false));
-
- /* 4:3 ratio */
- film->set_size (libdcp::Size (320, 240));
-
- /* This format should preserve aspect ratio of the source */
- Format const * format = Format::from_id ("var-185");
-
- /* We should have enough padding that the result is 4:3,
- which would be 1440 pixels.
- */
- BOOST_CHECK_EQUAL (format->dcp_padding (film), (1998 - 1440) / 2);
-
- /* This crops it to 1.291666667 */
- film->set_left_crop (5);
- film->set_right_crop (5);
-
- /* We should now have enough padding that the result is 1.29166667,
- which would be 1395 pixels.
- */
- BOOST_CHECK_EQUAL (format->dcp_padding (film), rint ((1998 - 1395) / 2.0));
+// BOOST_CHECK_EQUAL (f->ratio_as_integer(shared_ptr<const Film> ()), 239);
}
BOOST_AUTO_TEST_CASE (util_test)
BOOST_CHECK_THROW (md5_digest ("foobar"), OpenFileError);
}
-BOOST_AUTO_TEST_CASE (paths_test)
-{
- shared_ptr<Film> f = new_test_film ("paths_test");
- f->set_directory ("build/test/a/b/c/d/e");
-
- f->_content = "/foo/bar/baz";
- BOOST_CHECK_EQUAL (f->content_path(), "/foo/bar/baz");
- f->_content = "foo/bar/baz";
- BOOST_CHECK_EQUAL (f->content_path(), "build/test/a/b/c/d/e/foo/bar/baz");
-}
-
void
do_remote_encode (shared_ptr<DCPVideoFrame> frame, ServerDescription* description, shared_ptr<EncodedData> locally_encoded)
{
new thread (boost::bind (&Server::run, server, 2));
/* Let the server get itself ready */
- dvdomatic_sleep (1);
+ dcpomatic_sleep (1);
ServerDescription description ("localhost", 2);
{
shared_ptr<Film> film = new_test_film ("make_dcp_test");
film->set_name ("test_film2");
- film->set_content ("../../../test/test.mp4");
+// film->set_content ("../../../test/test.mp4");
film->set_format (Format::from_nickname ("Flat"));
film->set_dcp_content_type (DCPContentType::from_pretty_name ("Test"));
film->make_dcp ();
film->write_metadata ();
while (JobManager::instance()->work_to_do ()) {
- dvdomatic_sleep (1);
+ dcpomatic_sleep (1);
}
BOOST_CHECK_EQUAL (JobManager::instance()->errors(), false);
BOOST_CHECK (f.have_dcp());
p /= f.dcp_name();
- p /= "video.mxf";
+ p /= f.dcp_video_mxf_filename();
boost::filesystem::remove (p);
BOOST_CHECK (!f.have_dcp ());
}
{
shared_ptr<Film> film = new_test_film ("make_dcp_with_range_test");
film->set_name ("test_film3");
- film->set_content ("../../../test/test.mp4");
- film->examine_content ();
+// film->set_content ("../../../test/test.mp4");
+// film->examine_content ();
film->set_format (Format::from_nickname ("Flat"));
film->set_dcp_content_type (DCPContentType::from_pretty_name ("Test"));
film->set_trim_end (42);
film->make_dcp ();
while (JobManager::instance()->work_to_do() && !JobManager::instance()->errors()) {
- dvdomatic_sleep (1);
+ dcpomatic_sleep (1);
}
BOOST_CHECK_EQUAL (JobManager::instance()->errors(), false);
Config::instance()->set_allowed_dcp_frame_rates (afr);
shared_ptr<Film> f = new_test_film ("audio_sampling_rate_test");
- f->set_source_frame_rate (24);
+// f->set_source_frame_rate (24);
f->set_dcp_frame_rate (24);
- f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
+// f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 48000);
- f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 44100, 0)));
+// f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 44100, 0)));
BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 48000);
- f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 80000, 0)));
+// f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 80000, 0)));
BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 96000);
- f->set_source_frame_rate (23.976);
+// f->set_source_frame_rate (23.976);
f->set_dcp_frame_rate (best_dcp_frame_rate (23.976));
- f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
+// f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 47952);
- f->set_source_frame_rate (29.97);
+// f->set_source_frame_rate (29.97);
f->set_dcp_frame_rate (best_dcp_frame_rate (29.97));
BOOST_CHECK_EQUAL (f->dcp_frame_rate (), 30);
- f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
+// f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 47952);
- f->set_source_frame_rate (25);
+// f->set_source_frame_rate (25);
f->set_dcp_frame_rate (24);
- f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
+// f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 50000);
- f->set_source_frame_rate (25);
+// f->set_source_frame_rate (25);
f->set_dcp_frame_rate (24);
- f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 44100, 0)));
+// f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 44100, 0)));
BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 50000);
/* Check some out-there conversions (not the best) */
- f->set_source_frame_rate (14.99);
+// f->set_source_frame_rate (14.99);
f->set_dcp_frame_rate (25);
- f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 16000, 0)));
+// f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 16000, 0)));
/* The FrameRateConversion within target_audio_sample_rate should choose to double-up
the 14.99 fps video to 30 and then run it slow at 25.
*/
shared_ptr<TestJob> a (new TestJob (f));
JobManager::instance()->add (a);
- dvdomatic_sleep (1);
+ dcpomatic_sleep (1);
BOOST_CHECK_EQUAL (a->running (), true);
a->set_finished_ok ();
- dvdomatic_sleep (2);
+ dcpomatic_sleep (2);
BOOST_CHECK_EQUAL (a->finished_ok(), true);
}
delete t;
delete u;
}
+