summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-04-01 02:25:02 +0100
committerCarl Hetherington <cth@carlh.net>2013-04-01 02:25:02 +0100
commitb468ccabdb13fca86ae8a324239d83490ef5832e (patch)
tree816332e6d3437b3924c1fdf6ada7d61965136337 /src
parent640c53f0a5f178a894ff2718bf6d74e9e977eb80 (diff)
XML metadata and some other bits.
Diffstat (limited to 'src')
-rw-r--r--src/lib/ab_transcoder.h1
-rw-r--r--src/lib/audio_content.cc9
-rw-r--r--src/lib/audio_content.h5
-rw-r--r--src/lib/config.cc89
-rw-r--r--src/lib/config.h3
-rw-r--r--src/lib/content.cc16
-rw-r--r--src/lib/content.h7
-rw-r--r--src/lib/dci_metadata.cc33
-rw-r--r--src/lib/dci_metadata.h12
-rw-r--r--src/lib/decoder_factory.cc43
-rw-r--r--src/lib/decoder_factory.h47
-rw-r--r--src/lib/ffmpeg_content.cc86
-rw-r--r--src/lib/ffmpeg_content.h10
-rw-r--r--src/lib/film.cc293
-rw-r--r--src/lib/film.h10
-rw-r--r--src/lib/imagemagick_content.cc9
-rw-r--r--src/lib/imagemagick_content.h5
-rw-r--r--src/lib/server.cc23
-rw-r--r--src/lib/server.h9
-rw-r--r--src/lib/sndfile_content.cc11
-rw-r--r--src/lib/sndfile_content.h5
-rw-r--r--src/lib/transcoder.cc1
-rw-r--r--src/lib/transcoder.h2
-rw-r--r--src/lib/video_content.cc22
-rw-r--r--src/lib/video_content.h3
-rw-r--r--src/lib/wscript3
-rw-r--r--src/tools/makedcp.cc2
-rw-r--r--src/tools/servomatictest.cc13
-rw-r--r--src/wx/audio_plot.cc1
-rw-r--r--src/wx/film_editor.cc18
-rw-r--r--src/wx/film_editor.h4
-rw-r--r--src/wx/film_viewer.h1
32 files changed, 441 insertions, 355 deletions
diff --git a/src/lib/ab_transcoder.h b/src/lib/ab_transcoder.h
index 090c26fb7..5ce4a03da 100644
--- a/src/lib/ab_transcoder.h
+++ b/src/lib/ab_transcoder.h
@@ -25,7 +25,6 @@
#include <boost/shared_ptr.hpp>
#include <stdint.h>
#include "util.h"
-#include "decoder_factory.h"
class Job;
class Encoder;
diff --git a/src/lib/audio_content.cc b/src/lib/audio_content.cc
index e9eacfd79..74b8ea2ce 100644
--- a/src/lib/audio_content.cc
+++ b/src/lib/audio_content.cc
@@ -1,7 +1,16 @@
+#include <libcxml/cxml.h>
#include "audio_content.h"
+using boost::shared_ptr;
+
AudioContent::AudioContent (boost::filesystem::path f)
: Content (f)
{
}
+
+AudioContent::AudioContent (shared_ptr<const cxml::Node> node)
+ : Content (node)
+{
+
+}
diff --git a/src/lib/audio_content.h b/src/lib/audio_content.h
index e18d1082e..f3dd81efb 100644
--- a/src/lib/audio_content.h
+++ b/src/lib/audio_content.h
@@ -4,10 +4,15 @@
#include "content.h"
#include "util.h"
+namespace cxml {
+ class Node;
+}
+
class AudioContent : public virtual Content
{
public:
AudioContent (boost::filesystem::path);
+ AudioContent (boost::shared_ptr<const cxml::Node>);
virtual int audio_channels () const = 0;
virtual ContentAudioFrame audio_length () const = 0;
diff --git a/src/lib/config.cc b/src/lib/config.cc
index 5dce3748d..2defa0539 100644
--- a/src/lib/config.cc
+++ b/src/lib/config.cc
@@ -22,6 +22,7 @@
#include <fstream>
#include <glib.h>
#include <boost/filesystem.hpp>
+#include <libcxml/cxml.h>
#include "config.h"
#include "server.h"
#include "scaler.h"
@@ -34,7 +35,9 @@ using std::vector;
using std::ifstream;
using std::string;
using std::ofstream;
+using std::list;
using boost::shared_ptr;
+using boost::optional;
Config* Config::_instance = 0;
@@ -52,8 +55,51 @@ Config::Config ()
_allowed_dcp_frame_rates.push_back (48);
_allowed_dcp_frame_rates.push_back (50);
_allowed_dcp_frame_rates.push_back (60);
+
+ if (!boost::filesystem::exists (file (false))) {
+ read_old_metadata ();
+ return;
+ }
+
+ cxml::File f (file (false), "Config");
+ optional<string> c;
+
+ _num_local_encoding_threads = f.number_child<int> ("NumLocalEncodingThreads");
+ _default_directory = f.string_child ("DefaultDirectory");
+ _server_port = f.number_child<int> ("ServerPort");
+ c = f.optional_string_child ("ReferenceScaler");
+ if (c) {
+ _reference_scaler = Scaler::from_id (c.get ());
+ }
+
+ list<shared_ptr<cxml::Node> > filters = f.node_children ("ReferenceFilter");
+ for (list<shared_ptr<cxml::Node> >::iterator i = filters.begin(); i != filters.end(); ++i) {
+ _reference_filters.push_back (Filter::from_id ((*i)->content ()));
+ }
- ifstream f (file().c_str ());
+ list<shared_ptr<cxml::Node> > servers = f.node_children ("Server");
+ for (list<shared_ptr<cxml::Node> >::iterator i = servers.begin(); i != servers.end(); ++i) {
+ _servers.push_back (new ServerDescription (*i));
+ }
+
+ _tms_ip = f.string_child ("TMSIP");
+ _tms_path = f.string_child ("TMSPath");
+ _tms_user = f.string_child ("TMSUser");
+ _tms_password = f.string_child ("TMSPassword");
+
+ c = f.optional_string_child ("SoundProcessor");
+ if (c) {
+ _sound_processor = SoundProcessor::from_id (c.get ());
+ }
+
+ _language = f.optional_string_child ("Language");
+ _default_dci_metadata = DCIMetadata (f.node_child ("DCIMetadata"));
+}
+
+void
+Config::read_old_metadata ()
+{
+ ifstream f (file(true).c_str ());
string line;
while (getline (f, line)) {
if (line.empty ()) {
@@ -98,17 +144,21 @@ Config::Config ()
_language = v;
}
- _default_dci_metadata.read (k, v);
+ _default_dci_metadata.read_old_metadata (k, v);
}
}
/** @return Filename to write configuration to */
string
-Config::file () const
+Config::file (bool old) const
{
boost::filesystem::path p;
p /= g_get_user_config_dir ();
- p /= N_(".dvdomatic");
+ if (old) {
+ p /= ".dvdomatic";
+ } else {
+ p /= ".dvdomatic.xml";
+ }
return p.string ();
}
@@ -127,35 +177,38 @@ Config::instance ()
void
Config::write () const
{
- ofstream f (file().c_str ());
- f << N_("num_local_encoding_threads ") << _num_local_encoding_threads << N_("\n")
- << N_("default_directory ") << _default_directory << N_("\n")
- << N_("server_port ") << _server_port << N_("\n");
+ xmlpp::Document doc;
+ xmlpp::Element* root = doc.create_root_node ("Config");
+ root->add_child("NumLocalEncodingThreads")->add_child_text (boost::lexical_cast<string> (_num_local_encoding_threads));
+ root->add_child("DefaultDirectory")->add_child_text (_default_directory);
+ root->add_child("ServerPort")->add_child_text (boost::lexical_cast<string> (_server_port));
if (_reference_scaler) {
- f << "reference_scaler " << _reference_scaler->id () << "\n";
+ root->add_child("ReferenceScaler")->add_child_text (_reference_scaler->id ());
}
for (vector<Filter const *>::const_iterator i = _reference_filters.begin(); i != _reference_filters.end(); ++i) {
- f << N_("reference_filter ") << (*i)->id () << N_("\n");
+ root->add_child("ReferenceFilter")->add_child_text ((*i)->id ());
}
for (vector<ServerDescription*>::const_iterator i = _servers.begin(); i != _servers.end(); ++i) {
- f << N_("server ") << (*i)->as_metadata () << N_("\n");
+ (*i)->as_xml (root->add_child ("Server"));
}
- f << N_("tms_ip ") << _tms_ip << N_("\n");
- f << N_("tms_path ") << _tms_path << N_("\n");
- f << N_("tms_user ") << _tms_user << N_("\n");
- f << N_("tms_password ") << _tms_password << N_("\n");
+ root->add_child("TMSIP")->add_child_text (_tms_ip);
+ root->add_child("TMSPath")->add_child_text (_tms_path);
+ root->add_child("TMSUser")->add_child_text (_tms_user);
+ root->add_child("TMSPassword")->add_child_text (_tms_password);
if (_sound_processor) {
- f << "sound_processor " << _sound_processor->id () << "\n";
+ root->add_child("SoundProcessor")->add_child_text (_sound_processor->id ());
}
if (_language) {
- f << "language " << _language.get() << "\n";
+ root->add_child("Language")->add_child_text (_language.get());
}
- _default_dci_metadata.write (f);
+ _default_dci_metadata.as_xml (root->add_child ("DCIMetadata"));
+
+ doc.write_to_file_formatted (file (false));
}
string
diff --git a/src/lib/config.h b/src/lib/config.h
index 011ca716f..13d36d236 100644
--- a/src/lib/config.h
+++ b/src/lib/config.h
@@ -177,7 +177,8 @@ public:
private:
Config ();
- std::string file () const;
+ std::string file (bool) const;
+ void read_old_metadata ();
/** number of threads to use for J2K encoding on the local machine */
int _num_local_encoding_threads;
diff --git a/src/lib/content.cc b/src/lib/content.cc
index 2fb94e959..977f2e2a7 100644
--- a/src/lib/content.cc
+++ b/src/lib/content.cc
@@ -1,4 +1,6 @@
#include <boost/thread/mutex.hpp>
+#include <libxml++/libxml++.h>
+#include <libcxml/cxml.h>
#include "content.h"
#include "util.h"
@@ -11,6 +13,20 @@ Content::Content (boost::filesystem::path f)
}
+Content::Content (shared_ptr<const cxml::Node> node)
+{
+ _file = node->string_child ("File");
+ _digest = node->string_child ("Digest");
+}
+
+void
+Content::as_xml (xmlpp::Node* node) const
+{
+ boost::mutex::scoped_lock lm (_mutex);
+ node->add_child("File")->add_child_text (_file.string());
+ node->add_child("Digest")->add_child_text (_digest);
+}
+
void
Content::examine (shared_ptr<Film>, shared_ptr<Job>, bool)
{
diff --git a/src/lib/content.h b/src/lib/content.h
index 25c097424..3a94d2297 100644
--- a/src/lib/content.h
+++ b/src/lib/content.h
@@ -4,6 +4,11 @@
#include <boost/filesystem.hpp>
#include <boost/signals2.hpp>
#include <boost/thread/mutex.hpp>
+#include <libxml++/libxml++.h>
+
+namespace cxml {
+ class Node;
+}
class Job;
class Film;
@@ -12,9 +17,11 @@ class Content
{
public:
Content (boost::filesystem::path);
+ Content (boost::shared_ptr<const cxml::Node>);
virtual void examine (boost::shared_ptr<Film>, boost::shared_ptr<Job>, bool);
virtual std::string summary () const = 0;
+ virtual void as_xml (xmlpp::Node *) const;
boost::filesystem::path file () const {
boost::mutex::scoped_lock lm (_mutex);
diff --git a/src/lib/dci_metadata.cc b/src/lib/dci_metadata.cc
index 758886db4..f25b3ddb0 100644
--- a/src/lib/dci_metadata.cc
+++ b/src/lib/dci_metadata.cc
@@ -18,26 +18,39 @@
*/
#include <iostream>
+#include <libcxml/cxml.h>
#include "dci_metadata.h"
#include "i18n.h"
-using namespace std;
+using std::string;
+using boost::shared_ptr;
+
+DCIMetadata::DCIMetadata (shared_ptr<const cxml::Node> node)
+{
+ audio_language = node->string_child ("AudioLanguage");
+ subtitle_language = node->string_child ("SubtitleLanguage");
+ territory = node->string_child ("Territory");
+ rating = node->string_child ("Rating");
+ studio = node->string_child ("Studio");
+ facility = node->string_child ("Facility");
+ package_type = node->string_child ("PackageType");
+}
void
-DCIMetadata::write (ostream& f) const
+DCIMetadata::as_xml (xmlpp::Node* root) const
{
- f << N_("audio_language ") << audio_language << N_("\n");
- f << N_("subtitle_language ") << subtitle_language << N_("\n");
- f << N_("territory ") << territory << N_("\n");
- f << N_("rating ") << rating << N_("\n");
- f << N_("studio ") << studio << N_("\n");
- f << N_("facility ") << facility << N_("\n");
- f << N_("package_type ") << package_type << N_("\n");
+ root->add_child("AudioLanguage")->add_child_text (audio_language);
+ root->add_child("SubtitleLanguage")->add_child_text (subtitle_language);
+ root->add_child("Territory")->add_child_text (territory);
+ root->add_child("Rating")->add_child_text (rating);
+ root->add_child("Studio")->add_child_text (studio);
+ root->add_child("Facility")->add_child_text (facility);
+ root->add_child("PackageType")->add_child_text (package_type);
}
void
-DCIMetadata::read (string k, string v)
+DCIMetadata::read_old_metadata (string k, string v)
{
if (k == N_("audio_language")) {
audio_language = v;
diff --git a/src/lib/dci_metadata.h b/src/lib/dci_metadata.h
index eecdc7655..f61dae5a8 100644
--- a/src/lib/dci_metadata.h
+++ b/src/lib/dci_metadata.h
@@ -21,12 +21,20 @@
#define DVDOMATIC_DCI_METADATA_H
#include <string>
+#include <libxml++/libxml++.h>
+
+namespace cxml {
+ class Node;
+}
class DCIMetadata
{
public:
- void read (std::string, std::string);
- void write (std::ostream &) const;
+ DCIMetadata () {}
+ DCIMetadata (boost::shared_ptr<const cxml::Node>);
+
+ void as_xml (xmlpp::Node *) const;
+ void read_old_metadata (std::string, std::string);
std::string audio_language;
std::string subtitle_language;
diff --git a/src/lib/decoder_factory.cc b/src/lib/decoder_factory.cc
deleted file mode 100644
index 7940edc2e..000000000
--- a/src/lib/decoder_factory.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- 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.
-
-*/
-
-/** @file src/decoder_factory.cc
- * @brief A method to create an appropriate decoder for some content.
- */
-
-#include <boost/filesystem.hpp>
-#include "ffmpeg_decoder.h"
-#include "imagemagick_decoder.h"
-#include "film.h"
-#include "sndfile_decoder.h"
-#include "decoder_factory.h"
-
-using std::string;
-using std::pair;
-using std::make_pair;
-using boost::shared_ptr;
-using boost::dynamic_pointer_cast;
-
-Decoders
-decoder_factory (
- shared_ptr<Film> f
- )
-{
- return Decoders ();
-}
diff --git a/src/lib/decoder_factory.h b/src/lib/decoder_factory.h
deleted file mode 100644
index 3fd91f876..000000000
--- a/src/lib/decoder_factory.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- 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.
-
-*/
-
-#ifndef DVDOMATIC_DECODER_FACTORY_H
-#define DVDOMATIC_DECODER_FACTORY_H
-
-/** @file src/decoder_factory.h
- * @brief A method to create appropriate decoders for some content.
- */
-
-class Film;
-class VideoDecoder;
-class AudioDecoder;
-
-struct Decoders {
- Decoders () {}
-
- Decoders (boost::shared_ptr<VideoDecoder> v, boost::shared_ptr<AudioDecoder> a)
- : video (v)
- , audio (a)
- {}
-
- boost::shared_ptr<VideoDecoder> video;
- boost::shared_ptr<AudioDecoder> audio;
-};
-
-extern Decoders decoder_factory (
- boost::shared_ptr<Film>
- );
-
-#endif
diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc
index 6109b7212..42e04e838 100644
--- a/src/lib/ffmpeg_content.cc
+++ b/src/lib/ffmpeg_content.cc
@@ -1,3 +1,4 @@
+#include <libcxml/cxml.h>
#include "ffmpeg_content.h"
#include "ffmpeg_decoder.h"
#include "compose.hpp"
@@ -8,7 +9,10 @@
#include "i18n.h"
using std::string;
+using std::vector;
+using std::list;
using boost::shared_ptr;
+using boost::lexical_cast;
int const FFmpegContentProperty::SUBTITLE_STREAMS = 100;
int const FFmpegContentProperty::SUBTITLE_STREAM = 101;
@@ -23,6 +27,54 @@ FFmpegContent::FFmpegContent (boost::filesystem::path f)
}
+FFmpegContent::FFmpegContent (shared_ptr<const cxml::Node> node)
+ : Content (node)
+ , VideoContent (node)
+ , AudioContent (node)
+{
+ list<shared_ptr<cxml::Node> > c = node->node_children ("SubtitleStream");
+ for (list<shared_ptr<cxml::Node> >::const_iterator i = c.begin(); i != c.end(); ++i) {
+ _subtitle_streams.push_back (FFmpegSubtitleStream (*i));
+ if ((*i)->optional_number_child<int> ("Selected")) {
+ _subtitle_stream = _subtitle_streams.back ();
+ }
+ }
+
+ c = node->node_children ("AudioStream");
+ for (list<shared_ptr<cxml::Node> >::const_iterator i = c.begin(); i != c.end(); ++i) {
+ _audio_streams.push_back (FFmpegAudioStream (*i));
+ if ((*i)->optional_number_child<int> ("Selected")) {
+ _audio_stream = _audio_streams.back ();
+ }
+ }
+}
+
+void
+FFmpegContent::as_xml (xmlpp::Node* node) const
+{
+ node->add_child("Type")->add_child_text ("FFmpeg");
+ Content::as_xml (node);
+ VideoContent::as_xml (node);
+
+ boost::mutex::scoped_lock lm (_mutex);
+
+ for (vector<FFmpegSubtitleStream>::const_iterator i = _subtitle_streams.begin(); i != _subtitle_streams.end(); ++i) {
+ xmlpp::Node* t = node->add_child("SubtitleStream");
+ if (_subtitle_stream && *i == _subtitle_stream.get()) {
+ t->add_child("Selected")->add_child_text("1");
+ }
+ i->as_xml (t);
+ }
+
+ for (vector<FFmpegAudioStream>::const_iterator i = _audio_streams.begin(); i != _audio_streams.end(); ++i) {
+ xmlpp::Node* t = node->add_child("AudioStream");
+ if (_audio_stream && *i == _audio_stream.get()) {
+ t->add_child("Selected")->add_child_text("1");
+ }
+ i->as_xml (t);
+ }
+}
+
void
FFmpegContent::examine (shared_ptr<Film> film, shared_ptr<Job> job, bool quick)
{
@@ -151,3 +203,37 @@ operator== (FFmpegAudioStream const & a, FFmpegAudioStream const & b)
{
return a.id == b.id;
}
+
+FFmpegAudioStream::FFmpegAudioStream (shared_ptr<const cxml::Node> node)
+{
+ name = node->string_child ("Name");
+ id = node->number_child<int> ("Id");
+ frame_rate = node->number_child<int> ("FrameRate");
+ channel_layout = node->number_child<int64_t> ("ChannelLayout");
+}
+
+void
+FFmpegAudioStream::as_xml (xmlpp::Node* root) const
+{
+ root->add_child("Name")->add_child_text (name);
+ root->add_child("Id")->add_child_text (lexical_cast<string> (id));
+ root->add_child("FrameRate")->add_child_text (lexical_cast<string> (frame_rate));
+ root->add_child("ChannelLayout")->add_child_text (lexical_cast<string> (channel_layout));
+}
+
+/** Construct a SubtitleStream from a value returned from to_string().
+ * @param t String returned from to_string().
+ * @param v State file version.
+ */
+FFmpegSubtitleStream::FFmpegSubtitleStream (shared_ptr<const cxml::Node> node)
+{
+ name = node->string_child ("Name");
+ id = node->number_child<int> ("Id");
+}
+
+void
+FFmpegSubtitleStream::as_xml (xmlpp::Node* root) const
+{
+ root->add_child("Name")->add_child_text (name);
+ root->add_child("Id")->add_child_text (lexical_cast<string> (id));
+}
diff --git a/src/lib/ffmpeg_content.h b/src/lib/ffmpeg_content.h
index 83474ea66..95e24b7b3 100644
--- a/src/lib/ffmpeg_content.h
+++ b/src/lib/ffmpeg_content.h
@@ -15,6 +15,10 @@ public:
, channel_layout (c)
{}
+ FFmpegAudioStream (boost::shared_ptr<const cxml::Node>);
+
+ void as_xml (xmlpp::Node *) const;
+
int channels () const {
return av_get_channel_layout_nb_channels (channel_layout);
}
@@ -35,6 +39,10 @@ public:
, id (i)
{}
+ FFmpegSubtitleStream (boost::shared_ptr<const cxml::Node>);
+
+ void as_xml (xmlpp::Node *) const;
+
std::string name;
int id;
};
@@ -54,9 +62,11 @@ class FFmpegContent : public VideoContent, public AudioContent, public boost::en
{
public:
FFmpegContent (boost::filesystem::path);
+ FFmpegContent (boost::shared_ptr<const cxml::Node>);
void examine (boost::shared_ptr<Film>, boost::shared_ptr<Job>, bool);
std::string summary () const;
+ void as_xml (xmlpp::Node *) const;
/* AudioContent */
int audio_channels () const;
diff --git a/src/lib/film.cc b/src/lib/film.cc
index d22f67e67..a6a53b3fc 100644
--- a/src/lib/film.cc
+++ b/src/lib/film.cc
@@ -29,6 +29,8 @@
#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"
@@ -43,7 +45,6 @@
#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"
@@ -52,6 +53,9 @@
#include "sndfile_decoder.h"
#include "analyse_audio_job.h"
#include "playlist.h"
+#include "ffmpeg_content.h"
+#include "imagemagick_content.h"
+#include "sndfile_content.h"
#include "i18n.h"
@@ -67,6 +71,7 @@ using std::setfill;
using std::min;
using std::make_pair;
using std::endl;
+using std::list;
using boost::shared_ptr;
using boost::lexical_cast;
using boost::to_upper_copy;
@@ -93,7 +98,7 @@ Film::Film (string d, bool must_exist)
, _scaler (Scaler::from_id ("bicubic"))
, _trim_start (0)
, _trim_end (0)
- , _dcp_ab (false)
+ , _ab (false)
, _audio_gain (0)
, _audio_delay (0)
, _with_subtitles (false)
@@ -157,7 +162,7 @@ Film::Film (Film const & o)
, _scaler (o._scaler)
, _trim_start (o._trim_start)
, _trim_end (o._trim_end)
- , _dcp_ab (o._dcp_ab)
+ , _ab (o._ab)
, _audio_gain (o._audio_gain)
, _audio_delay (o._audio_delay)
, _with_subtitles (o._with_subtitles)
@@ -199,7 +204,7 @@ Film::video_state_identifier () const
<< "_" << 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;
}
@@ -297,7 +302,7 @@ Film::make_dcp ()
shared_ptr<Job> r;
- if (dcp_ab()) {
+ 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())));
@@ -375,77 +380,54 @@ Film::encoded_frames () const
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);
- }
-
- f << "version " << state_version << endl;
+ xmlpp::Document doc;
+ xmlpp::Element* root = doc.create_root_node ("Metadata");
- /* User stuff */
- f << "name " << _name << endl;
- f << "use_dci_name " << _use_dci_name << endl;
-// f << "content " << _content << endl;
- f << "trust_content_headers " << (_trust_content_headers ? "1" : "0") << 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");
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;
+ root->add_child("Format")->add_child_text (_format->id ());
}
- 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;
- }
- f << "scaler " << _scaler->id () << endl;
- f << "trim_start " << _trim_start << endl;
- f << "trim_end " << _trim_end << endl;
- f << "dcp_ab " << (_dcp_ab ? "1" : "0") << endl;
-// if (_content_audio_stream) {
-// f << "selected_content_audio_stream " << _content_audio_stream->to_string() << endl;
-// }
-// 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;
-// }
-
-// f << "source_frame_rate " << _source_frame_rate << endl;
+ for (vector<Filter const *>::const_iterator i = _filters.begin(); i != _filters.end(); ++i) {
+ root->add_child("Filter")->add_child_text ((*i)->id ());
+ }
+
+ 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("DCIDate")->add_child_text (boost::gregorian::to_iso_string (_dci_date));
+ root->add_child("DCPFrameRate")->add_child_text (boost::lexical_cast<string> (_dcp_frame_rate));
+
+ 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;
}
@@ -456,137 +438,68 @@ Film::read_metadata ()
{
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 DVD-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!"));
}
+
+ cxml::File f (file ("metadata.xml"), "Metadata");
- multimap<string, string> kv = read_key_value (f);
+ _name = f.string_child ("Name");
+ _use_dci_name = f.bool_child ("UseDCIName");
+ _trust_content_headers = f.bool_child ("TrustContentHeaders");
- /* We need version before anything else */
- multimap<string, string>::iterator v = kv.find ("version");
- if (v != kv.end ()) {
- version = atoi (v->second.c_str());
+ {
+ optional<string> c = f.optional_string_child ("DCPContentType");
+ if (c) {
+ _dcp_content_type = DCPContentType::from_dci_name (c.get ());
+ }
}
-
- for (multimap<string, string>::const_iterator i = kv.begin(); i != kv.end(); ++i) {
- string const k = i->first;
- string const v = i->second;
- if (k == "audio_sample_rate") {
- audio_sample_rate = atoi (v.c_str());
+ {
+ optional<string> c = f.optional_string_child ("Format");
+ if (c) {
+ _format = Format::from_id (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_headers") {
- _trust_content_headers = (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 == "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 ());
+ _crop.left = f.number_child<int> ("CropLeft");
+ _crop.right = f.number_child<int> ("CropRight");
+ _crop.top = f.number_child<int> ("CropTop");
+ _crop.bottom = f.number_child<int> ("CropBottom");
+
+ {
+ 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 ()));
}
+ }
- _dci_metadata.read (k, v);
+ _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"));
+ _dci_date = boost::gregorian::from_undelimited_string (f.string_child ("DCIDate"));
+ _dcp_frame_rate = f.number_child<int> ("DCPFrameRate");
+
+ 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");
- /* 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);
+ if (type == "FFmpeg") {
+ _content.push_back (shared_ptr<Content> (new FFmpegContent (*i)));
+ } else if (type == "ImageMagick") {
+ _content.push_back (shared_ptr<Content> (new ImageMagickContent (*i)));
+ } else if (type == "Sndfile") {
+ _content.push_back (shared_ptr<Content> (new SndfileContent (*i)));
}
}
@@ -936,13 +849,13 @@ Film::set_trim_end (int t)
}
void
-Film::set_dcp_ab (bool a)
+Film::set_ab (bool a)
{
{
boost::mutex::scoped_lock lm (_state_mutex);
- _dcp_ab = a;
+ _ab = a;
}
- signal_changed (DCP_AB);
+ signal_changed (AB);
}
void
diff --git a/src/lib/film.h b/src/lib/film.h
index 928866161..f5f944409 100644
--- a/src/lib/film.h
+++ b/src/lib/film.h
@@ -123,7 +123,7 @@ public:
SCALER,
TRIM_START,
TRIM_END,
- DCP_AB,
+ AB,
AUDIO_GAIN,
AUDIO_DELAY,
STILL_DURATION,
@@ -200,9 +200,9 @@ public:
return _trim_end;
}
- bool dcp_ab () const {
+ bool ab () const {
boost::mutex::scoped_lock lm (_state_mutex);
- return _dcp_ab;
+ return _ab;
}
float audio_gain () const {
@@ -268,7 +268,7 @@ public:
void set_scaler (Scaler const *);
void set_trim_start (int);
void set_trim_end (int);
- void set_dcp_ab (bool);
+ void set_ab (bool);
void set_audio_gain (float);
void set_audio_delay (int);
void set_still_duration (int);
@@ -333,7 +333,7 @@ private:
is the video without any filters or post-processing, and the right half
has the specified filters and post-processing.
*/
- bool _dcp_ab;
+ bool _ab;
/** Gain to apply to audio in dB */
float _audio_gain;
/** Delay to apply to audio (positive moves audio later) in milliseconds */
diff --git a/src/lib/imagemagick_content.cc b/src/lib/imagemagick_content.cc
index d096bff84..cb712b417 100644
--- a/src/lib/imagemagick_content.cc
+++ b/src/lib/imagemagick_content.cc
@@ -1,9 +1,11 @@
+#include <libcxml/cxml.h>
#include "imagemagick_content.h"
#include "compose.hpp"
#include "i18n.h"
using std::string;
+using boost::shared_ptr;
ImageMagickContent::ImageMagickContent (boost::filesystem::path f)
: Content (f)
@@ -13,6 +15,13 @@ ImageMagickContent::ImageMagickContent (boost::filesystem::path f)
_video_length = 10 * 24;
}
+ImageMagickContent::ImageMagickContent (shared_ptr<const cxml::Node> node)
+ : Content (node)
+ , VideoContent (node)
+{
+
+}
+
string
ImageMagickContent::summary () const
{
diff --git a/src/lib/imagemagick_content.h b/src/lib/imagemagick_content.h
index 0dd5baba8..99b614512 100644
--- a/src/lib/imagemagick_content.h
+++ b/src/lib/imagemagick_content.h
@@ -1,9 +1,14 @@
#include "video_content.h"
+namespace cxml {
+ class Node;
+}
+
class ImageMagickContent : public VideoContent
{
public:
ImageMagickContent (boost::filesystem::path);
+ ImageMagickContent (boost::shared_ptr<const cxml::Node>);
std::string summary () const;
diff --git a/src/lib/server.cc b/src/lib/server.cc
index 9c5a77f68..ca0bec580 100644
--- a/src/lib/server.cc
+++ b/src/lib/server.cc
@@ -29,6 +29,7 @@
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/scoped_array.hpp>
+#include <libcxml/cxml.h>
#include "server.h"
#include "util.h"
#include "scaler.h"
@@ -51,6 +52,19 @@ using boost::bind;
using boost::scoped_array;
using libdcp::Size;
+ServerDescription::ServerDescription (shared_ptr<const cxml::Node> node)
+{
+ _host_name = node->string_child ("HostName");
+ _threads = node->number_child<int> ("Threads");
+}
+
+void
+ServerDescription::as_xml (xmlpp::Node* root) const
+{
+ root->add_child("HostName")->add_child_text (_host_name);
+ root->add_child("Threads")->add_child_text (boost::lexical_cast<string> (_threads));
+}
+
/** Create a server description from a string of metadata returned from as_metadata().
* @param v Metadata.
* @return ServerDescription, or 0.
@@ -68,15 +82,6 @@ ServerDescription::create_from_metadata (string v)
return new ServerDescription (b[0], atoi (b[1].c_str ()));
}
-/** @return Description of this server as text */
-string
-ServerDescription::as_metadata () const
-{
- stringstream s;
- s << _host_name << N_(" ") << _threads;
- return s.str ();
-}
-
Server::Server (shared_ptr<Log> log)
: _log (log)
{
diff --git a/src/lib/server.h b/src/lib/server.h
index 89aeca626..398401a55 100644
--- a/src/lib/server.h
+++ b/src/lib/server.h
@@ -26,10 +26,15 @@
#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include <boost/thread/condition.hpp>
+#include <libxml++/libxml++.h>
#include "log.h"
class Socket;
+namespace cxml {
+ class Node;
+}
+
/** @class ServerDescription
* @brief Class to describe a server to which we can send encoding work.
*/
@@ -44,6 +49,8 @@ public:
, _threads (t)
{}
+ ServerDescription (boost::shared_ptr<const cxml::Node>);
+
/** @return server's host name or IP address in string form */
std::string host_name () const {
return _host_name;
@@ -62,7 +69,7 @@ public:
_threads = t;
}
- std::string as_metadata () const;
+ void as_xml (xmlpp::Node *) const;
static ServerDescription * create_from_metadata (std::string v);
diff --git a/src/lib/sndfile_content.cc b/src/lib/sndfile_content.cc
index 53df4deea..4794e4d31 100644
--- a/src/lib/sndfile_content.cc
+++ b/src/lib/sndfile_content.cc
@@ -3,7 +3,8 @@
#include "i18n.h"
-using namespace std;
+using std::string;
+using boost::shared_ptr;
SndfileContent::SndfileContent (boost::filesystem::path f)
: Content (f)
@@ -12,6 +13,14 @@ SndfileContent::SndfileContent (boost::filesystem::path f)
}
+SndfileContent::SndfileContent (shared_ptr<const cxml::Node> node)
+ : Content (node)
+ , AudioContent (node)
+
+{
+
+}
+
string
SndfileContent::summary () const
{
diff --git a/src/lib/sndfile_content.h b/src/lib/sndfile_content.h
index 10cb428a1..b9a500c88 100644
--- a/src/lib/sndfile_content.h
+++ b/src/lib/sndfile_content.h
@@ -1,9 +1,14 @@
#include "audio_content.h"
+namespace cxml {
+ class Node;
+}
+
class SndfileContent : public AudioContent
{
public:
SndfileContent (boost::filesystem::path);
+ SndfileContent (boost::shared_ptr<const cxml::Node>);
std::string summary () const;
diff --git a/src/lib/transcoder.cc b/src/lib/transcoder.cc
index 070258008..21944c5fc 100644
--- a/src/lib/transcoder.cc
+++ b/src/lib/transcoder.cc
@@ -28,7 +28,6 @@
#include <boost/signals2.hpp>
#include "transcoder.h"
#include "encoder.h"
-#include "decoder_factory.h"
#include "film.h"
#include "matcher.h"
#include "delay_line.h"
diff --git a/src/lib/transcoder.h b/src/lib/transcoder.h
index 3c47b0c7e..856b10f3a 100644
--- a/src/lib/transcoder.h
+++ b/src/lib/transcoder.h
@@ -23,8 +23,6 @@
* as a parameter to the constructor.
*/
-#include "decoder_factory.h"
-
class Film;
class Job;
class Encoder;
diff --git a/src/lib/video_content.cc b/src/lib/video_content.cc
index 9fc5cf1a2..8a4414c18 100644
--- a/src/lib/video_content.cc
+++ b/src/lib/video_content.cc
@@ -1,3 +1,4 @@
+#include <libcxml/cxml.h>
#include "video_content.h"
#include "video_decoder.h"
@@ -5,7 +6,9 @@ int const VideoContentProperty::VIDEO_LENGTH = 0;
int const VideoContentProperty::VIDEO_SIZE = 1;
int const VideoContentProperty::VIDEO_FRAME_RATE = 2;
+using std::string;
using boost::shared_ptr;
+using boost::lexical_cast;
VideoContent::VideoContent (boost::filesystem::path f)
: Content (f)
@@ -14,6 +17,25 @@ VideoContent::VideoContent (boost::filesystem::path f)
}
+VideoContent::VideoContent (shared_ptr<const cxml::Node> node)
+ : Content (node)
+{
+ _video_length = node->number_child<ContentVideoFrame> ("VideoLength");
+ _video_size.width = node->number_child<int> ("VideoWidth");
+ _video_size.height = node->number_child<int> ("VideoHeight");
+ _video_frame_rate = node->number_child<float> ("VideoFrameRate");
+}
+
+void
+VideoContent::as_xml (xmlpp::Node* node) const
+{
+ boost::mutex::scoped_lock lm (_mutex);
+ node->add_child("VideoLength")->add_child_text (lexical_cast<string> (_video_length));
+ node->add_child("VideoWidth")->add_child_text (lexical_cast<string> (_video_size.width));
+ node->add_child("VideoHeight")->add_child_text (lexical_cast<string> (_video_size.height));
+ node->add_child("VideoFrameRate")->add_child_text (lexical_cast<string> (_video_frame_rate));
+}
+
void
VideoContent::take_from_video_decoder (shared_ptr<VideoDecoder> d)
{
diff --git a/src/lib/video_content.h b/src/lib/video_content.h
index 219130668..7c9db890a 100644
--- a/src/lib/video_content.h
+++ b/src/lib/video_content.h
@@ -18,6 +18,9 @@ class VideoContent : public virtual Content
{
public:
VideoContent (boost::filesystem::path);
+ VideoContent (boost::shared_ptr<const cxml::Node>);
+
+ void as_xml (xmlpp::Node *) const;
ContentVideoFrame video_length () const {
boost::mutex::scoped_lock lm (_mutex);
diff --git a/src/lib/wscript b/src/lib/wscript
index 5510d48a8..303a9951f 100644
--- a/src/lib/wscript
+++ b/src/lib/wscript
@@ -17,7 +17,6 @@ sources = """
dcp_content_type.cc
dcp_video_frame.cc
decoder.cc
- decoder_factory.cc
delay_line.cc
dolby_cp750.cc
encoder.cc
@@ -70,7 +69,7 @@ def build(bld):
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'
diff --git a/src/tools/makedcp.cc b/src/tools/makedcp.cc
index 226cde113..85134b3c5 100644
--- a/src/tools/makedcp.cc
+++ b/src/tools/makedcp.cc
@@ -146,7 +146,7 @@ main (int argc, char* argv[])
film->log()->set_level ((Log::Level) log_level);
cout << "\nMaking ";
- if (film->dcp_ab()) {
+ if (film->ab()) {
cout << "A/B ";
}
cout << "DCP for " << film->name() << "\n";
diff --git a/src/tools/servomatictest.cc b/src/tools/servomatictest.cc
index d08fefa90..3d847d690 100644
--- a/src/tools/servomatictest.cc
+++ b/src/tools/servomatictest.cc
@@ -32,8 +32,8 @@
#include "exceptions.h"
#include "scaler.h"
#include "log.h"
-#include "decoder_factory.h"
#include "video_decoder.h"
+#include "playlist.h"
using std::cout;
using std::cerr;
@@ -150,17 +150,14 @@ main (int argc, char* argv[])
server = new ServerDescription (server_host, 1);
shared_ptr<Film> film (new Film (film_dir, true));
- /* XXX */
-// opt.decode_audio = false;
-// opt.decode_subtitles = true;
-// opt.video_sync = true;
+ shared_ptr<Playlist> playlist = film->playlist ();
+ playlist->disable_audio ();
- Decoders decoders = decoder_factory (film);
try {
- decoders.video->Video.connect (boost::bind (process_video, _1, _2, _3));
+ playlist->Video.connect (boost::bind (process_video, _1, _2, _3));
bool done = false;
while (!done) {
- done = decoders.video->pass ();
+ done = playlist->pass ();
}
} catch (std::exception& e) {
cerr << "Error: " << e.what() << "\n";
diff --git a/src/wx/audio_plot.cc b/src/wx/audio_plot.cc
index cf44eb69f..2a6210164 100644
--- a/src/wx/audio_plot.cc
+++ b/src/wx/audio_plot.cc
@@ -21,7 +21,6 @@
#include <boost/bind.hpp>
#include <wx/graphics.h>
#include "audio_plot.h"
-#include "lib/decoder_factory.h"
#include "lib/audio_decoder.h"
#include "lib/audio_analysis.h"
#include "wx/wx_util.h"
diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc
index 40f4f0362..560c4ef27 100644
--- a/src/wx/film_editor.cc
+++ b/src/wx/film_editor.cc
@@ -175,8 +175,8 @@ FilmEditor::make_film_panel ()
}
++r;
- _dcp_ab = new wxCheckBox (_film_panel, wxID_ANY, _("A/B"));
- grid->Add (_dcp_ab, wxGBPosition (r, 0));
+ _ab = new wxCheckBox (_film_panel, wxID_ANY, _("A/B"));
+ grid->Add (_ab, wxGBPosition (r, 0));
++r;
vector<DCPContentType const *> const ct = DCPContentType::all ();
@@ -212,7 +212,7 @@ FilmEditor::connect_to_widgets ()
_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);
+ _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);
@@ -489,13 +489,13 @@ FilmEditor::trust_content_headers_changed (wxCommandEvent &)
/** 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 */
@@ -674,8 +674,8 @@ FilmEditor::film_changed (Film::Property p)
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 ()));
@@ -811,7 +811,7 @@ FilmEditor::set_film (shared_ptr<Film> f)
film_changed (Film::SCALER);
film_changed (Film::TRIM_START);
film_changed (Film::TRIM_END);
- film_changed (Film::DCP_AB);
+ film_changed (Film::AB);
film_changed (Film::AUDIO_GAIN);
film_changed (Film::AUDIO_DELAY);
film_changed (Film::WITH_SUBTITLES);
@@ -849,7 +849,7 @@ FilmEditor::set_things_sensitive (bool s)
_dcp_frame_rate->Enable (s);
_trim_start->Enable (s);
_trim_end->Enable (s);
- _dcp_ab->Enable (s);
+ _ab->Enable (s);
_colour_lut->Enable (s);
_j2k_bandwidth->Enable (s);
_audio_gain->Enable (s);
diff --git a/src/wx/film_editor.h b/src/wx/film_editor.h
index 50457bdce..80072d48a 100644
--- a/src/wx/film_editor.h
+++ b/src/wx/film_editor.h
@@ -72,7 +72,7 @@ private:
void trim_start_changed (wxCommandEvent &);
void trim_end_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 &);
@@ -162,7 +162,7 @@ private:
wxSpinCtrl* _trim_start;
wxSpinCtrl* _trim_end;
/** Selector to generate an A/B comparison DCP */
- wxCheckBox* _dcp_ab;
+ wxCheckBox* _ab;
std::vector<Format const *> _formats;
diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h
index b552a3dbc..74ab9798c 100644
--- a/src/wx/film_viewer.h
+++ b/src/wx/film_viewer.h
@@ -23,7 +23,6 @@
#include <wx/wx.h>
#include "lib/film.h"
-#include "lib/decoder_factory.h"
class wxToggleButton;
class FFmpegPlayer;