From 828c320df8c56208a8834971f5d937ce06a4edf2 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 17 Jan 2013 20:16:10 +0000 Subject: Pull entry point out of the constructor. --- src/dcp.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src/dcp.cc') diff --git a/src/dcp.cc b/src/dcp.cc index 6c626939..e148c772 100644 --- a/src/dcp.cc +++ b/src/dcp.cc @@ -363,10 +363,11 @@ CPL::CPL (string directory, string file, shared_ptr asset_map, b _directory, asset_map->asset_from_id (p->id)->chunks.front()->path, _fps, - (*i)->asset_list->main_picture->entry_point, (*i)->asset_list->main_picture->duration ) ); + + picture->set_entry_point ((*i)->asset_list->main_picture->entry_point); } catch (MXFFileError) { if (require_mxfs) { throw; @@ -380,10 +381,12 @@ CPL::CPL (string directory, string file, shared_ptr asset_map, b _directory, asset_map->asset_from_id (p->id)->chunks.front()->path, _fps, - p->entry_point, p->duration ) ); + + picture->set_entry_point (p->entry_point); + } catch (MXFFileError) { if (require_mxfs) { throw; @@ -399,10 +402,11 @@ CPL::CPL (string directory, string file, shared_ptr asset_map, b _directory, asset_map->asset_from_id ((*i)->asset_list->main_sound->id)->chunks.front()->path, _fps, - (*i)->asset_list->main_sound->entry_point, (*i)->asset_list->main_sound->duration ) ); + + sound->set_entry_point ((*i)->asset_list->main_sound->entry_point); } catch (MXFFileError) { if (require_mxfs) { throw; -- cgit v1.2.3 From 6a5bb039b3bfd508cc87b6b15102b9eb60c62f8d Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Fri, 18 Jan 2013 21:46:20 +0000 Subject: Add basics for progressive sound asset writing. --- src/dcp.cc | 8 +--- src/mxf_asset.cc | 11 +++++ src/mxf_asset.h | 2 + src/picture_asset.cc | 14 ++++++- src/picture_asset.h | 12 ++---- src/sound_asset.cc | 112 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/sound_asset.h | 39 +++++++++++++++++- 7 files changed, 176 insertions(+), 22 deletions(-) (limited to 'src/dcp.cc') diff --git a/src/dcp.cc b/src/dcp.cc index e148c772..4f1732da 100644 --- a/src/dcp.cc +++ b/src/dcp.cc @@ -361,9 +361,7 @@ CPL::CPL (string directory, string file, shared_ptr asset_map, b try { picture.reset (new MonoPictureAsset ( _directory, - asset_map->asset_from_id (p->id)->chunks.front()->path, - _fps, - (*i)->asset_list->main_picture->duration + asset_map->asset_from_id (p->id)->chunks.front()->path ) ); @@ -400,9 +398,7 @@ CPL::CPL (string directory, string file, shared_ptr asset_map, b try { sound.reset (new SoundAsset ( _directory, - asset_map->asset_from_id ((*i)->asset_list->main_sound->id)->chunks.front()->path, - _fps, - (*i)->asset_list->main_sound->duration + asset_map->asset_from_id ((*i)->asset_list->main_sound->id)->chunks.front()->path ) ); diff --git a/src/mxf_asset.cc b/src/mxf_asset.cc index af3c74dc..7c75cb27 100644 --- a/src/mxf_asset.cc +++ b/src/mxf_asset.cc @@ -36,6 +36,17 @@ using boost::shared_ptr; using boost::dynamic_pointer_cast; using namespace libdcp; +MXFAsset::MXFAsset (string directory, string file_name) + : Asset (directory, file_name) + , _progress (0) + , _fps (0) + , _entry_point (0) + , _intrinsic_duration (0) + , _duration (0) +{ + +} + MXFAsset::MXFAsset (string directory, string file_name, boost::signals2::signal* progress, int fps, int intrinsic_duration) : Asset (directory, file_name) , _progress (progress) diff --git a/src/mxf_asset.h b/src/mxf_asset.h index fd786cc6..ff43fecb 100644 --- a/src/mxf_asset.h +++ b/src/mxf_asset.h @@ -30,6 +30,8 @@ namespace libdcp class MXFAsset : public Asset { public: + MXFAsset (std::string directory, std::string file_name); + /** Construct an MXFAsset. * @param directory Directory where MXF file is. * @param file_name Name of MXF file. diff --git a/src/picture_asset.cc b/src/picture_asset.cc index f3d52396..a7d5243a 100644 --- a/src/picture_asset.cc +++ b/src/picture_asset.cc @@ -53,6 +53,12 @@ PictureAsset::PictureAsset (string directory, string mxf_name, boost::signals2:: } +PictureAsset::PictureAsset (string directory, string mxf_name) + : MXFAsset (directory, mxf_name) +{ + +} + void PictureAsset::write_to_cpl (ostream& s) const { @@ -161,8 +167,8 @@ MonoPictureAsset::MonoPictureAsset (string directory, string mxf_name, int fps, } -MonoPictureAsset::MonoPictureAsset (string directory, string mxf_name, int fps, int intrinsic_duration) - : PictureAsset (directory, mxf_name, 0, fps, intrinsic_duration, Size (0, 0)) +MonoPictureAsset::MonoPictureAsset (string directory, string mxf_name) + : PictureAsset (directory, mxf_name) { ASDCP::JP2K::MXFReader reader; if (ASDCP_FAILURE (reader.OpenRead (path().string().c_str()))) { @@ -176,6 +182,9 @@ MonoPictureAsset::MonoPictureAsset (string directory, string mxf_name, int fps, _size.width = desc.StoredWidth; _size.height = desc.StoredHeight; + _fps = desc.EditRate.Numerator; + assert (desc.EditRate.Denominator == 1); + _intrinsic_duration = desc.ContainerDuration; } void @@ -434,6 +443,7 @@ MonoPictureAssetWriter::finalize () _finalized = true; _asset->set_intrinsic_duration (_frames_written); + _asset->set_duration (_frames_written); } MonoPictureAssetWriter::~MonoPictureAssetWriter () diff --git a/src/picture_asset.h b/src/picture_asset.h index 059e5926..dd69e352 100644 --- a/src/picture_asset.h +++ b/src/picture_asset.h @@ -36,6 +36,7 @@ class StereoPictureFrame; class PictureAsset : public MXFAsset { public: + PictureAsset (std::string directory, std::string mxf_name); PictureAsset (std::string directory, std::string mxf_name, boost::signals2::signal* progress, int fps, int intrinsic_duration, Size size); /** Write details of this asset to a CPL stream. @@ -129,17 +130,12 @@ public: Size size ); - MonoPictureAsset ( - std::string directory, - std::string mxf_name, - int fps, - Size size - ); + MonoPictureAsset (std::string directory, std::string mxf_name); + + MonoPictureAsset (std::string directory, std::string mxf_name, int fps, Size size); boost::shared_ptr start_write (); - MonoPictureAsset (std::string directory, std::string mxf_name, int fps, int intrinsic_duration); - boost::shared_ptr get_frame (int n) const; bool equals (boost::shared_ptr other, EqualityOptions opt, std::list& notes) const; diff --git a/src/sound_asset.cc b/src/sound_asset.cc index 04ca88da..89132f26 100644 --- a/src/sound_asset.cc +++ b/src/sound_asset.cc @@ -75,8 +75,8 @@ SoundAsset::SoundAsset ( construct (get_path); } -SoundAsset::SoundAsset (string directory, string mxf_name, int fps, int intrinsic_duration) - : MXFAsset (directory, mxf_name, 0, fps, intrinsic_duration) +SoundAsset::SoundAsset (string directory, string mxf_name) + : MXFAsset (directory, mxf_name) , _channels (0) , _start_frame (0) { @@ -85,7 +85,6 @@ SoundAsset::SoundAsset (string directory, string mxf_name, int fps, int intrinsi throw MXFFileError ("could not open MXF file for reading", path().string()); } - ASDCP::PCM::AudioDescriptor desc; if (ASDCP_FAILURE (reader.FillAudioDescriptor (desc))) { throw DCPReadError ("could not read audio MXF information"); @@ -93,6 +92,18 @@ SoundAsset::SoundAsset (string directory, string mxf_name, int fps, int intrinsi _sampling_rate = desc.AudioSamplingRate.Numerator / desc.AudioSamplingRate.Denominator; _channels = desc.ChannelCount; + _fps = desc.EditRate.Numerator; + assert (desc.EditRate.Denominator == 1); + _intrinsic_duration = desc.ContainerDuration; +} + +SoundAsset::SoundAsset (string directory, string mxf_name, int fps, int channels, int sampling_rate) + : MXFAsset (directory, mxf_name, 0, fps, 0) + , _channels (channels) + , _sampling_rate (sampling_rate) + , _start_frame (0) +{ + } string @@ -157,7 +168,7 @@ SoundAsset::construct (boost::function get_path) frame_buffer.Size (ASDCP::PCM::CalcFrameBufferSize (audio_desc)); ASDCP::WriterInfo writer_info; - fill_writer_info (&writer_info, _uuid); + MXFAsset::fill_writer_info (&writer_info, _uuid); ASDCP::PCM::MXFWriter mxf_writer; if (ASDCP_FAILURE (mxf_writer.OpenWrite (path().string().c_str(), writer_info, audio_desc))) { @@ -302,3 +313,96 @@ SoundAsset::get_frame (int n) const { return shared_ptr (new SoundFrame (path().string(), n + _entry_point)); } + +shared_ptr +SoundAsset::start_write () +{ + /* XXX: can't we use a shared_ptr here? */ + return shared_ptr (new SoundAssetWriter (this)); +} + +SoundAssetWriter::SoundAssetWriter (SoundAsset* a) + : _asset (a) + , _finalized (false) + , _frames_written (0) + , _frame_buffer_offset (0) +{ + /* Derived from ASDCP::Wav::SimpleWaveHeader::FillADesc */ + _audio_desc.EditRate = ASDCP::Rational (_asset->frames_per_second(), 1); + _audio_desc.AudioSamplingRate = ASDCP::Rational (_asset->sampling_rate(), 0); + _audio_desc.Locked = 0; + _audio_desc.ChannelCount = _asset->channels (); + _audio_desc.QuantizationBits = 24; + _audio_desc.BlockAlign = 3 * _asset->channels(); + _audio_desc.AvgBps = _asset->sampling_rate() * _audio_desc.BlockAlign; + _audio_desc.LinkedTrackID = 0; + _audio_desc.ChannelFormat = ASDCP::PCM::CF_NONE; + + _frame_buffer.Capacity (ASDCP::PCM::CalcFrameBufferSize (_audio_desc)); + _frame_buffer.Size (ASDCP::PCM::CalcFrameBufferSize (_audio_desc)); + memset (_frame_buffer.Data(), 0, _frame_buffer.Capacity()); + + MXFAsset::fill_writer_info (&_writer_info, _asset->uuid ()); + + if (ASDCP_FAILURE (_mxf_writer.OpenWrite (_asset->path().c_str(), _writer_info, _audio_desc))) { + throw FileError ("could not open audio MXF for writing", _asset->path().string()); + } +} + +void +SoundAssetWriter::write (float const * const * data, int frames) +{ + for (int i = 0; i < frames; ++i) { + + byte_t* out = _frame_buffer.Data() + _frame_buffer_offset; + + /* Write one sample per channel */ + for (int j = 0; j < _asset->channels(); ++j) { + int32_t const s = data[j][i] * (1 << 23); + *out++ = (s & 0xff); + *out++ = (s & 0xff00) >> 8; + *out++ = (s & 0xff0000) >> 16; + } + _frame_buffer_offset += 3 * _asset->channels(); + + assert (_frame_buffer_offset <= int (_frame_buffer.Capacity())); + + /* Finish the MXF frame if required */ + if (_frame_buffer_offset == int (_frame_buffer.Capacity())) { + write_current_frame (); + _frame_buffer_offset = 0; + memset (_frame_buffer.Data(), 0, _frame_buffer.Capacity()); + } + } +} + +void +SoundAssetWriter::write_current_frame () +{ + if (ASDCP_FAILURE (_mxf_writer.WriteFrame (_frame_buffer, 0, 0))) { + throw MiscError ("could not write audio MXF frame"); + } + + ++_frames_written; +} + +void +SoundAssetWriter::finalize () +{ + if (_frame_buffer_offset > 0) { + write_current_frame (); + } + + if (ASDCP_FAILURE (_mxf_writer.Finalize())) { + throw MiscError ("could not finalise audio MXF"); + } + + _finalized = true; + _asset->set_intrinsic_duration (_frames_written); + _asset->set_duration (_frames_written); +} + +SoundAssetWriter::~SoundAssetWriter () +{ + assert (_finalized); +} diff --git a/src/sound_asset.h b/src/sound_asset.h index 569bb305..17767b3a 100644 --- a/src/sound_asset.h +++ b/src/sound_asset.h @@ -24,13 +24,40 @@ * @brief An asset made up of PCM audio data files */ +#include "AS_DCP.h" #include "mxf_asset.h" #include "types.h" namespace libdcp { -class SoundFrame; +class SoundFrame; + +class SoundAsset; + +class SoundAssetWriter +{ +public: + ~SoundAssetWriter (); + + void write (float const * const *, int); + void finalize (); + +private: + friend class SoundAsset; + + SoundAssetWriter (SoundAsset *); + void write_current_frame (); + + SoundAsset* _asset; + bool _finalized; + int _frames_written; + int _frame_buffer_offset; + ASDCP::PCM::MXFWriter _mxf_writer; + ASDCP::PCM::FrameBuffer _frame_buffer; + ASDCP::WriterInfo _writer_info; + ASDCP::PCM::AudioDescriptor _audio_desc; +}; /** @brief An asset made up of WAV files */ class SoundAsset : public MXFAsset @@ -80,12 +107,20 @@ public: int channels ); + SoundAsset ( + std::string directory, + std::string mxf_name + ); + SoundAsset ( std::string directory, std::string mxf_name, int fps, - int intrinsic_duration + int channels, + int sampling_rate ); + + boost::shared_ptr start_write (); /** Write details of this asset to a CPL stream. * @param s Stream. -- cgit v1.2.3 From 4a557a8b6631f132e851b1bb362cde4270ca6057 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sun, 10 Feb 2013 21:32:30 +0000 Subject: Derive exceptions from boost::exception and use boost::throw_exception to enable thread-safe exception handling by callers. --- src/dcp.cc | 16 ++++++++-------- src/dcp_time.cc | 2 +- src/picture_asset.cc | 38 +++++++++++++++++++------------------- src/picture_frame.cc | 8 ++++---- src/sound_asset.cc | 34 +++++++++++++++++----------------- src/sound_frame.cc | 4 ++-- src/subtitle_asset.cc | 2 +- src/types.cc | 12 ++++++------ src/util.cc | 6 +++--- src/xml.cc | 20 ++++++++++---------- 10 files changed, 71 insertions(+), 71 deletions(-) (limited to 'src/dcp.cc') diff --git a/src/dcp.cc b/src/dcp.cc index 4f1732da..d446b205 100644 --- a/src/dcp.cc +++ b/src/dcp.cc @@ -182,17 +182,17 @@ DCP::read (bool require_mxfs) if (boost::filesystem::exists (p)) { asset_map.reset (new AssetMap (p.string ())); } else { - throw DCPReadError ("could not find AssetMap file"); + boost::throw_exception (DCPReadError ("could not find AssetMap file")); } } } catch (FileError& e) { - throw FileError ("could not load AssetMap file", files.asset_map); + boost::throw_exception (FileError ("could not load AssetMap file", files.asset_map)); } for (list >::const_iterator i = asset_map->assets.begin(); i != asset_map->assets.end(); ++i) { if ((*i)->chunks.size() != 1) { - throw XMLError ("unsupported asset chunk count"); + boost::throw_exception (XMLError ("unsupported asset chunk count")); } boost::filesystem::path t = _directory; @@ -219,24 +219,24 @@ DCP::read (bool require_mxfs) if (files.pkl.empty ()) { files.pkl = t.string(); } else { - throw DCPReadError ("duplicate PKLs found"); + boost::throw_exception (DCPReadError ("duplicate PKLs found")); } } } if (files.cpls.empty ()) { - throw FileError ("no CPL files found", ""); + boost::throw_exception (FileError ("no CPL files found", "")); } if (files.pkl.empty ()) { - throw FileError ("no PKL file found", ""); + boost::throw_exception (FileError ("no PKL file found", "")); } shared_ptr pkl; try { pkl.reset (new PKLFile (files.pkl)); } catch (FileError& e) { - throw FileError ("could not load PKL file", files.pkl); + boost::throw_exception (FileError ("could not load PKL file", files.pkl)); } /* Cross-check */ @@ -325,7 +325,7 @@ CPL::CPL (string directory, string file, shared_ptr asset_map, b try { cpl.reset (new CPLFile (file)); } catch (FileError& e) { - throw FileError ("could not load CPL file", file); + boost::throw_exception (FileError ("could not load CPL file", file)); } /* Now cherry-pick the required bits into our own data structure */ diff --git a/src/dcp_time.cc b/src/dcp_time.cc index 15ad05d4..bdf55f93 100644 --- a/src/dcp_time.cc +++ b/src/dcp_time.cc @@ -59,7 +59,7 @@ Time::Time (string time) vector b; split (b, time, is_any_of (":")); if (b.size() != 4) { - throw DCPReadError ("unrecognised time specification"); + boost::throw_exception (DCPReadError ("unrecognised time specification")); } h = lexical_cast (b[0]); diff --git a/src/picture_asset.cc b/src/picture_asset.cc index e0e55979..13253242 100644 --- a/src/picture_asset.cc +++ b/src/picture_asset.cc @@ -87,21 +87,21 @@ PictureAsset::equals (shared_ptr other, EqualityOptions opt, listpath().string().c_str()))) { - throw MXFFileError ("could not open MXF file for reading", path().string()); + boost::throw_exception (MXFFileError ("could not open MXF file for reading", path().string())); } ASDCP::JP2K::PictureDescriptor desc_A; if (ASDCP_FAILURE (reader_A.FillPictureDescriptor (desc_A))) { - throw DCPReadError ("could not read video MXF information"); + boost::throw_exception (DCPReadError ("could not read video MXF information")); } ASDCP::JP2K::PictureDescriptor desc_B; if (ASDCP_FAILURE (reader_B.FillPictureDescriptor (desc_B))) { - throw DCPReadError ("could not read video MXF information"); + boost::throw_exception (DCPReadError ("could not read video MXF information")); } if ( @@ -176,12 +176,12 @@ MonoPictureAsset::MonoPictureAsset (string directory, string mxf_name) { ASDCP::JP2K::MXFReader reader; if (ASDCP_FAILURE (reader.OpenRead (path().string().c_str()))) { - throw MXFFileError ("could not open MXF file for reading", path().string()); + boost::throw_exception (MXFFileError ("could not open MXF file for reading", path().string())); } ASDCP::JP2K::PictureDescriptor desc; if (ASDCP_FAILURE (reader.FillPictureDescriptor (desc))) { - throw DCPReadError ("could not read video MXF information"); + boost::throw_exception (DCPReadError ("could not read video MXF information")); } _size.width = desc.StoredWidth; @@ -197,7 +197,7 @@ MonoPictureAsset::construct (boost::function get_path) ASDCP::JP2K::CodestreamParser j2k_parser; ASDCP::JP2K::FrameBuffer frame_buffer (4 * Kumu::Megabyte); if (ASDCP_FAILURE (j2k_parser.OpenReadFrame (get_path(0).c_str(), frame_buffer))) { - throw FileError ("could not open JPEG2000 file for reading", get_path (0)); + boost::throw_exception (FileError ("could not open JPEG2000 file for reading", get_path (0))); } ASDCP::JP2K::PictureDescriptor picture_desc; @@ -209,7 +209,7 @@ MonoPictureAsset::construct (boost::function get_path) ASDCP::JP2K::MXFWriter mxf_writer; if (ASDCP_FAILURE (mxf_writer.OpenWrite (path().string().c_str(), writer_info, picture_desc, 16384, false))) { - throw MXFFileError ("could not open MXF file for writing", path().string()); + boost::throw_exception (MXFFileError ("could not open MXF file for writing", path().string())); } for (int i = 0; i < _intrinsic_duration; ++i) { @@ -217,11 +217,11 @@ MonoPictureAsset::construct (boost::function get_path) string const path = get_path (i); if (ASDCP_FAILURE (j2k_parser.OpenReadFrame (path.c_str(), frame_buffer))) { - throw FileError ("could not open JPEG2000 file for reading", path); + boost::throw_exception (FileError ("could not open JPEG2000 file for reading", path)); } if (ASDCP_FAILURE (mxf_writer.WriteFrame (frame_buffer, 0, 0))) { - throw MXFFileError ("error in writing video MXF", this->path().string()); + boost::throw_exception (MXFFileError ("error in writing video MXF", this->path().string())); } if (_progress) { @@ -230,7 +230,7 @@ MonoPictureAsset::construct (boost::function get_path) } if (ASDCP_FAILURE (mxf_writer.Finalize())) { - throw MXFFileError ("error in finalising video MXF", path().string()); + boost::throw_exception (MXFFileError ("error in finalising video MXF", path().string())); } } @@ -378,12 +378,12 @@ StereoPictureAsset::StereoPictureAsset (string directory, string mxf_name, int f { ASDCP::JP2K::MXFSReader reader; if (ASDCP_FAILURE (reader.OpenRead (path().string().c_str()))) { - throw MXFFileError ("could not open MXF file for reading", path().string()); + boost::throw_exception (MXFFileError ("could not open MXF file for reading", path().string())); } ASDCP::JP2K::PictureDescriptor desc; if (ASDCP_FAILURE (reader.FillPictureDescriptor (desc))) { - throw DCPReadError ("could not read video MXF information"); + boost::throw_exception (DCPReadError ("could not read video MXF information")); } _size.width = desc.StoredWidth; @@ -447,7 +447,7 @@ void MonoPictureAssetWriter::start (uint8_t* data, int size) { if (ASDCP_FAILURE (_state->j2k_parser.OpenReadFrame (data, size, _state->frame_buffer))) { - throw MiscError ("could not parse J2K frame"); + boost::throw_exception (MiscError ("could not parse J2K frame")); } _state->j2k_parser.FillPictureDescriptor (_state->picture_descriptor); @@ -463,7 +463,7 @@ MonoPictureAssetWriter::start (uint8_t* data, int size) _overwrite) )) { - throw MXFFileError ("could not open MXF file for writing", _asset->path().string()); + boost::throw_exception (MXFFileError ("could not open MXF file for writing", _asset->path().string())); } _started = true; @@ -479,14 +479,14 @@ MonoPictureAssetWriter::write (uint8_t* data, int size) } if (ASDCP_FAILURE (_state->j2k_parser.OpenReadFrame (data, size, _state->frame_buffer))) { - throw MiscError ("could not parse J2K frame"); + boost::throw_exception (MiscError ("could not parse J2K frame")); } uint64_t const before_offset = _state->mxf_writer.Tell (); string hash; if (ASDCP_FAILURE (_state->mxf_writer.WriteFrame (_state->frame_buffer, 0, 0, &hash))) { - throw MXFFileError ("error in writing video MXF", _asset->path().string()); + boost::throw_exception (MXFFileError ("error in writing video MXF", _asset->path().string())); } ++_frames_written; @@ -500,7 +500,7 @@ MonoPictureAssetWriter::fake_write (int size) assert (!_finalized); if (ASDCP_FAILURE (_state->mxf_writer.FakeWriteFrame (size))) { - throw MXFFileError ("error in writing video MXF", _asset->path().string()); + boost::throw_exception (MXFFileError ("error in writing video MXF", _asset->path().string())); } ++_frames_written; @@ -512,7 +512,7 @@ MonoPictureAssetWriter::finalize () assert (!_finalized); if (ASDCP_FAILURE (_state->mxf_writer.Finalize())) { - throw MXFFileError ("error in finalizing video MXF", _asset->path().string()); + boost::throw_exception (MXFFileError ("error in finalizing video MXF", _asset->path().string())); } _finalized = true; diff --git a/src/picture_frame.cc b/src/picture_frame.cc index 907f70ab..5898d0ea 100644 --- a/src/picture_frame.cc +++ b/src/picture_frame.cc @@ -38,14 +38,14 @@ MonoPictureFrame::MonoPictureFrame (string mxf_path, int n) { ASDCP::JP2K::MXFReader reader; if (ASDCP_FAILURE (reader.OpenRead (mxf_path.c_str()))) { - throw FileError ("could not open MXF file for reading", mxf_path); + boost::throw_exception (FileError ("could not open MXF file for reading", mxf_path)); } /* XXX: unfortunate guesswork on this buffer size */ _buffer = new ASDCP::JP2K::FrameBuffer (4 * Kumu::Megabyte); if (ASDCP_FAILURE (reader.ReadFrame (n, *_buffer))) { - throw DCPReadError ("could not read video frame"); + boost::throw_exception (DCPReadError ("could not read video frame")); } } @@ -93,14 +93,14 @@ StereoPictureFrame::StereoPictureFrame (string mxf_path, int n) { ASDCP::JP2K::MXFSReader reader; if (ASDCP_FAILURE (reader.OpenRead (mxf_path.c_str()))) { - throw FileError ("could not open MXF file for reading", mxf_path); + boost::throw_exception (FileError ("could not open MXF file for reading", mxf_path)); } /* XXX: unfortunate guesswork on this buffer size */ _buffer = new ASDCP::JP2K::SFrameBuffer (4 * Kumu::Megabyte); if (ASDCP_FAILURE (reader.ReadFrame (n, *_buffer))) { - throw DCPReadError ("could not read video frame"); + boost::throw_exception (DCPReadError ("could not read video frame")); } } diff --git a/src/sound_asset.cc b/src/sound_asset.cc index 4d76a2fd..014b95a2 100644 --- a/src/sound_asset.cc +++ b/src/sound_asset.cc @@ -79,12 +79,12 @@ SoundAsset::SoundAsset (string directory, string mxf_name) { ASDCP::PCM::MXFReader reader; if (ASDCP_FAILURE (reader.OpenRead (path().string().c_str()))) { - throw MXFFileError ("could not open MXF file for reading", path().string()); + boost::throw_exception (MXFFileError ("could not open MXF file for reading", path().string())); } ASDCP::PCM::AudioDescriptor desc; if (ASDCP_FAILURE (reader.FillAudioDescriptor (desc))) { - throw DCPReadError ("could not read audio MXF information"); + boost::throw_exception (DCPReadError ("could not read audio MXF information")); } _sampling_rate = desc.AudioSamplingRate.Numerator / desc.AudioSamplingRate.Denominator; @@ -117,7 +117,7 @@ SoundAsset::construct (boost::function get_path) ASDCP::PCM::WAVParser pcm_parser_channel[_channels]; if (pcm_parser_channel[0].OpenRead (get_path(LEFT).c_str(), asdcp_edit_rate)) { - throw FileError ("could not open WAV file for reading", get_path(LEFT)); + boost::throw_exception (FileError ("could not open WAV file for reading", get_path(LEFT))); } ASDCP::PCM::AudioDescriptor audio_desc; @@ -149,7 +149,7 @@ SoundAsset::construct (boost::function get_path) string const path = get_path (channels[i]); if (ASDCP_FAILURE (pcm_parser_channel[i].OpenRead (path.c_str(), asdcp_edit_rate))) { - throw FileError ("could not open WAV file for reading", path); + boost::throw_exception (FileError ("could not open WAV file for reading", path)); } pcm_parser_channel[i].FillAudioDescriptor (audio_desc_channel[i]); @@ -168,7 +168,7 @@ SoundAsset::construct (boost::function get_path) ASDCP::PCM::MXFWriter mxf_writer; if (ASDCP_FAILURE (mxf_writer.OpenWrite (path().string().c_str(), writer_info, audio_desc))) { - throw FileError ("could not open audio MXF for writing", path().string()); + boost::throw_exception (FileError ("could not open audio MXF for writing", path().string())); } for (int i = 0; i < _intrinsic_duration; ++i) { @@ -176,7 +176,7 @@ SoundAsset::construct (boost::function get_path) for (int j = 0; j < _channels; ++j) { memset (frame_buffer_channel[j].Data(), 0, frame_buffer_channel[j].Capacity()); if (ASDCP_FAILURE (pcm_parser_channel[j].ReadFrame (frame_buffer_channel[j]))) { - throw MiscError ("could not read audio frame"); + boost::throw_exception (MiscError ("could not read audio frame")); } } @@ -195,7 +195,7 @@ SoundAsset::construct (boost::function get_path) } if (ASDCP_FAILURE (mxf_writer.WriteFrame (frame_buffer, 0, 0))) { - throw MiscError ("could not write audio MXF frame"); + boost::throw_exception (MiscError ("could not write audio MXF frame")); } if (_progress) { @@ -204,7 +204,7 @@ SoundAsset::construct (boost::function get_path) } if (ASDCP_FAILURE (mxf_writer.Finalize())) { - throw MiscError ("could not finalise audio MXF"); + boost::throw_exception (MiscError ("could not finalise audio MXF")); } } @@ -230,21 +230,21 @@ SoundAsset::equals (shared_ptr other, EqualityOptions opt, listpath().string().c_str()))) { - throw MXFFileError ("could not open MXF file for reading", path().string()); + boost::throw_exception (MXFFileError ("could not open MXF file for reading", path().string())); } ASDCP::PCM::AudioDescriptor desc_A; if (ASDCP_FAILURE (reader_A.FillAudioDescriptor (desc_A))) { - throw DCPReadError ("could not read audio MXF information"); + boost::throw_exception (DCPReadError ("could not read audio MXF information")); } ASDCP::PCM::AudioDescriptor desc_B; if (ASDCP_FAILURE (reader_B.FillAudioDescriptor (desc_B))) { - throw DCPReadError ("could not read audio MXF information"); + boost::throw_exception (DCPReadError ("could not read audio MXF information")); } if ( @@ -269,11 +269,11 @@ SoundAsset::equals (shared_ptr other, EqualityOptions opt, listwriter_info, _asset->uuid ()); if (ASDCP_FAILURE (_state->mxf_writer.OpenWrite (_asset->path().string().c_str(), _state->writer_info, _state->audio_desc))) { - throw FileError ("could not open audio MXF for writing", _asset->path().string()); + boost::throw_exception (FileError ("could not open audio MXF for writing", _asset->path().string())); } } @@ -376,7 +376,7 @@ void SoundAssetWriter::write_current_frame () { if (ASDCP_FAILURE (_state->mxf_writer.WriteFrame (_state->frame_buffer, 0, 0))) { - throw MiscError ("could not write audio MXF frame"); + boost::throw_exception (MiscError ("could not write audio MXF frame")); } ++_frames_written; @@ -390,7 +390,7 @@ SoundAssetWriter::finalize () } if (ASDCP_FAILURE (_state->mxf_writer.Finalize())) { - throw MiscError ("could not finalise audio MXF"); + boost::throw_exception (MiscError ("could not finalise audio MXF")); } _finalized = true; diff --git a/src/sound_frame.cc b/src/sound_frame.cc index ed626f5e..c2a10564 100644 --- a/src/sound_frame.cc +++ b/src/sound_frame.cc @@ -29,14 +29,14 @@ SoundFrame::SoundFrame (string mxf_path, int n) { ASDCP::PCM::MXFReader reader; if (ASDCP_FAILURE (reader.OpenRead (mxf_path.c_str()))) { - throw FileError ("could not open MXF file for reading", mxf_path); + boost::throw_exception (FileError ("could not open MXF file for reading", mxf_path)); } /* XXX: unfortunate guesswork on this buffer size */ _buffer = new ASDCP::PCM::FrameBuffer (1 * Kumu::Megabyte); if (ASDCP_FAILURE (reader.ReadFrame (n, *_buffer))) { - throw DCPReadError ("could not read audio frame"); + boost::throw_exception (DCPReadError ("could not read audio frame")); } } diff --git a/src/subtitle_asset.cc b/src/subtitle_asset.cc index c7051eae..ba91cf90 100644 --- a/src/subtitle_asset.cc +++ b/src/subtitle_asset.cc @@ -413,7 +413,7 @@ SubtitleAsset::write_xml (ostream& s) const << " " << _language << "\n"; if (_load_font_nodes.size() > 1) { - throw MiscError ("multiple LoadFont nodes not supported"); + boost::throw_exception (MiscError ("multiple LoadFont nodes not supported")); } if (!_load_font_nodes.empty ()) { diff --git a/src/types.cc b/src/types.cc index ac01ae45..693b9ab2 100644 --- a/src/types.cc +++ b/src/types.cc @@ -15,7 +15,7 @@ Fraction::Fraction (string s) vector b; split (b, s, is_any_of (" ")); if (b.size() != 2) { - throw XMLError ("malformed fraction " + s + " in XML node"); + boost::throw_exception (XMLError ("malformed fraction " + s + " in XML node")); } numerator = lexical_cast (b[0]); denominator = lexical_cast (b[1]); @@ -57,7 +57,7 @@ Color::Color (string argb_hex) { int alpha; if (sscanf (argb_hex.c_str(), "%2x%2x%2x%2x", &alpha, &r, &g, &b) < 4) { - throw XMLError ("could not parse colour string"); + boost::throw_exception (XMLError ("could not parse colour string")); } } @@ -118,7 +118,7 @@ libdcp::effect_to_string (Effect e) return "shadow"; } - throw MiscError ("unknown effect type"); + boost::throw_exception (MiscError ("unknown effect type")); } Effect @@ -132,7 +132,7 @@ libdcp::string_to_effect (string s) return SHADOW; } - throw DCPReadError ("unknown subtitle effect type"); + boost::throw_exception (DCPReadError ("unknown subtitle effect type")); } string @@ -147,7 +147,7 @@ libdcp::valign_to_string (VAlign v) return "bottom"; } - throw MiscError ("unknown valign type"); + boost::throw_exception (MiscError ("unknown valign type")); } VAlign @@ -161,7 +161,7 @@ libdcp::string_to_valign (string s) return BOTTOM; } - throw DCPReadError ("unknown subtitle valign type"); + boost::throw_exception (DCPReadError ("unknown subtitle valign type")); } diff --git a/src/util.cc b/src/util.cc index 1cbec719..b1556e33 100644 --- a/src/util.cc +++ b/src/util.cc @@ -66,7 +66,7 @@ libdcp::make_digest (string filename) { Kumu::FileReader reader; if (ASDCP_FAILURE (reader.OpenRead (filename.c_str ()))) { - throw FileError ("could not open file to compute digest", filename); + boost::throw_exception (FileError ("could not open file to compute digest", filename)); } SHA_CTX sha; @@ -81,7 +81,7 @@ libdcp::make_digest (string filename) if (r == Kumu::RESULT_ENDOFFILE) { break; } else if (ASDCP_FAILURE (r)) { - throw FileError ("could not read file to compute digest", filename); + boost::throw_exception (FileError ("could not read file to compute digest", filename)); } SHA1_Update (&sha, read_buffer.Data(), read); @@ -187,7 +187,7 @@ libdcp::decompress_j2k (uint8_t* data, int64_t size, int reduce) if (!image) { opj_destroy_decompress (decoder); opj_cio_close (cio); - throw DCPReadError ("could not decode JPEG2000 codestream"); + boost::throw_exception (DCPReadError ("could not decode JPEG2000 codestream")); } opj_cio_close (cio); diff --git a/src/xml.cc b/src/xml.cc index 22e91ac0..508790ab 100644 --- a/src/xml.cc +++ b/src/xml.cc @@ -29,9 +29,9 @@ XMLNode::node_child (string name) { list n = node_children (name); if (n.size() > 1) { - throw XMLError ("duplicate XML tag " + name); + boost::throw_exception (XMLError ("duplicate XML tag " + name)); } else if (n.empty ()) { - throw XMLError ("missing XML tag " + name + " in " + _node->get_name()); + boost::throw_exception (XMLError ("missing XML tag " + name + " in " + _node->get_name())); } return n.front (); @@ -68,7 +68,7 @@ XMLNode::optional_string_child (string name) { list nodes = node_children (name); if (nodes.size() > 2) { - throw XMLError ("duplicate XML tag " + name); + boost::throw_exception (XMLError ("duplicate XML tag " + name)); } if (nodes.empty ()) { @@ -103,7 +103,7 @@ XMLNode::optional_int64_child (string name) { list nodes = node_children (name); if (nodes.size() > 2) { - throw XMLError ("duplicate XML tag " + name); + boost::throw_exception (XMLError ("duplicate XML tag " + name)); } if (nodes.empty ()) { @@ -136,12 +136,12 @@ XMLNode::string_attribute (string name) { xmlpp::Element const * e = dynamic_cast (_node); if (!e) { - throw XMLError ("missing attribute"); + boost::throw_exception (XMLError ("missing attribute")); } xmlpp::Attribute* a = e->get_attribute (name); if (!a) { - throw XMLError ("missing attribute"); + boost::throw_exception (XMLError ("missing attribute")); } return a->get_value (); @@ -218,7 +218,7 @@ XMLNode::done () xmlpp::Node::NodeList c = _node->get_children (); for (xmlpp::Node::NodeList::iterator i = c.begin(); i != c.end(); ++i) { if (dynamic_cast (*i) && find (_taken.begin(), _taken.end(), (*i)->get_name()) == _taken.end ()) { - throw XMLError ("unexpected XML node " + (*i)->get_name()); + boost::throw_exception (XMLError ("unexpected XML node " + (*i)->get_name())); } } } @@ -242,18 +242,18 @@ XMLNode::content () XMLFile::XMLFile (string file, string root_name) { if (!filesystem::exists (file)) { - throw FileError ("XML file does not exist", file); + boost::throw_exception (FileError ("XML file does not exist", file)); } _parser = new xmlpp::DomParser; _parser->parse_file (file); if (!_parser) { - throw XMLError ("could not parse XML"); + boost::throw_exception (XMLError ("could not parse XML")); } _node = _parser->get_document()->get_root_node (); if (_node->get_name() != root_name) { - throw XMLError ("unrecognised root node"); + boost::throw_exception (XMLError ("unrecognised root node")); } } -- cgit v1.2.3 From 6322c72a13d7be2e991a8e0421414c0af8187b88 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 15 Apr 2013 13:38:14 +0100 Subject: Use boost::function for making notes during equals operations. --- src/asset.cc | 1 + src/asset.h | 3 ++- src/dcp.cc | 20 ++++++++++---------- src/dcp.h | 7 +++---- src/mxf_asset.cc | 12 ++++++------ src/mxf_asset.h | 2 +- src/picture_asset.cc | 29 +++++++++++++++-------------- src/picture_asset.h | 8 ++++---- src/reel.cc | 14 +++++++------- src/reel.h | 3 ++- src/sound_asset.cc | 10 +++++----- src/sound_asset.h | 2 +- src/subtitle_asset.h | 4 ++-- tools/dcpdiff.cc | 13 +++++++------ 14 files changed, 66 insertions(+), 62 deletions(-) (limited to 'src/dcp.cc') diff --git a/src/asset.cc b/src/asset.cc index 3d2a0e03..305fc9a7 100644 --- a/src/asset.cc +++ b/src/asset.cc @@ -24,6 +24,7 @@ #include #include #include +#include #include "AS_DCP.h" #include "KM_util.h" #include "asset.h" diff --git a/src/asset.h b/src/asset.h index 436e8b41..527dea7a 100644 --- a/src/asset.h +++ b/src/asset.h @@ -27,6 +27,7 @@ #include #include #include +#include #include "types.h" namespace ASDCP { @@ -80,7 +81,7 @@ public: _file_name = f; } - virtual bool equals (boost::shared_ptr other, EqualityOptions opt, std::list& notes) const = 0; + virtual bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function) const = 0; protected: diff --git a/src/dcp.cc b/src/dcp.cc index d446b205..49d41c70 100644 --- a/src/dcp.cc +++ b/src/dcp.cc @@ -248,10 +248,10 @@ DCP::read (bool require_mxfs) } bool -DCP::equals (DCP const & other, EqualityOptions opt, list& notes) const +DCP::equals (DCP const & other, EqualityOptions opt, boost::function note) const { if (_cpls.size() != other._cpls.size()) { - notes.push_back ("CPL counts differ"); + note ("CPL counts differ"); return false; } @@ -259,7 +259,7 @@ DCP::equals (DCP const & other, EqualityOptions opt, list& notes) const list >::const_iterator b = other._cpls.begin (); while (a != _cpls.end ()) { - if (!(*a)->equals (*b->get(), opt, notes)) { + if (!(*a)->equals (*b->get(), opt, note)) { return false; } ++a; @@ -516,30 +516,30 @@ CPL::write_to_assetmap (ostream& s) const bool -CPL::equals (CPL const & other, EqualityOptions opt, list& notes) const +CPL::equals (CPL const & other, EqualityOptions opt, boost::function note) const { if (_name != other._name) { - notes.push_back ("names differ"); + note ("names differ"); return false; } if (_content_kind != other._content_kind) { - notes.push_back ("content kinds differ"); + note ("content kinds differ"); return false; } if (_fps != other._fps) { - notes.push_back ("frames per second differ"); + note ("frames per second differ"); return false; } if (_length != other._length) { - notes.push_back ("lengths differ"); + note ("lengths differ"); return false; } if (_reels.size() != other._reels.size()) { - notes.push_back ("reel counts differ"); + note ("reel counts differ"); return false; } @@ -547,7 +547,7 @@ CPL::equals (CPL const & other, EqualityOptions opt, list& notes) const list >::const_iterator b = other._reels.begin (); while (a != _reels.end ()) { - if (!(*a)->equals (*b, opt, notes)) { + if (!(*a)->equals (*b, opt, note)) { return false; } ++a; diff --git a/src/dcp.h b/src/dcp.h index c5734542..7e9b4edc 100644 --- a/src/dcp.h +++ b/src/dcp.h @@ -84,7 +84,7 @@ public: std::list > assets () const; - bool equals (CPL const & other, EqualityOptions options, std::list& notes) const; + bool equals (CPL const & other, EqualityOptions options, boost::function note) const; void write_xml () const; void write_to_assetmap (std::ostream& s) const; @@ -141,11 +141,10 @@ public: /** Compare this DCP with another, according to various options. * @param other DCP to compare this one to. - * @param options Options to define just what "equality" means. - * @param notes Filled in with notes about differences. + * @param options Options to define what "equality" means. * @return true if the DCPs are equal according to EqualityOptions, otherwise false. */ - bool equals (DCP const & other, EqualityOptions options, std::list& notes) const; + bool equals (DCP const & other, EqualityOptions options, boost::function note) const; /** Add a CPL to this DCP. * @param cpl CPL to add. diff --git a/src/mxf_asset.cc b/src/mxf_asset.cc index 9b4cbf74..cf265712 100644 --- a/src/mxf_asset.cc +++ b/src/mxf_asset.cc @@ -71,31 +71,31 @@ MXFAsset::fill_writer_info (ASDCP::WriterInfo* writer_info, string uuid) } bool -MXFAsset::equals (shared_ptr other, EqualityOptions, list& notes) const +MXFAsset::equals (shared_ptr other, EqualityOptions, boost::function note) const { shared_ptr other_mxf = dynamic_pointer_cast (other); if (!other_mxf) { - notes.push_back ("comparing an MXF asset with a non-MXF asset"); + note ("comparing an MXF asset with a non-MXF asset"); return false; } if (_file_name != other_mxf->_file_name) { - notes.push_back ("MXF names differ"); + note ("MXF names differ"); return false; } if (_edit_rate != other_mxf->_edit_rate) { - notes.push_back ("MXF edit rates differ"); + note ("MXF edit rates differ"); return false; } if (_intrinsic_duration != other_mxf->_intrinsic_duration) { - notes.push_back ("MXF intrinsic durations differ"); + note ("MXF intrinsic durations differ"); return false; } if (_duration != other_mxf->_duration) { - notes.push_back ("MXF durations differ"); + note ("MXF durations differ"); return false; } diff --git a/src/mxf_asset.h b/src/mxf_asset.h index 430e9157..0c98f3c6 100644 --- a/src/mxf_asset.h +++ b/src/mxf_asset.h @@ -61,7 +61,7 @@ public: _intrinsic_duration = d; } - virtual bool equals (boost::shared_ptr other, EqualityOptions opt, std::list& notes) const; + virtual bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function note) const; int intrinsic_duration () const { return _intrinsic_duration; diff --git a/src/picture_asset.cc b/src/picture_asset.cc index 13253242..807564c5 100644 --- a/src/picture_asset.cc +++ b/src/picture_asset.cc @@ -79,9 +79,9 @@ PictureAsset::write_to_cpl (ostream& s) const } bool -PictureAsset::equals (shared_ptr other, EqualityOptions opt, list& notes) const +PictureAsset::equals (shared_ptr other, EqualityOptions opt, boost::function note) const { - if (!MXFAsset::equals (other, opt, notes)) { + if (!MXFAsset::equals (other, opt, note)) { return false; } @@ -125,7 +125,7 @@ PictureAsset::equals (shared_ptr other, EqualityOptions opt, list other, EqualityOptions opt, list& notes) const +MonoPictureAsset::equals (shared_ptr other, EqualityOptions opt, boost::function note) const { - if (!PictureAsset::equals (other, opt, notes)) { + if (!PictureAsset::equals (other, opt, note)) { return false; } @@ -262,7 +262,7 @@ MonoPictureAsset::equals (shared_ptr other, EqualityOptions opt, li shared_ptr frame_B = other_picture->get_frame (i); if (!frame_buffer_equals ( - i, opt, notes, + i, opt, note, frame_A->j2k_data(), frame_A->j2k_size(), frame_B->j2k_data(), frame_B->j2k_size() )) { @@ -274,9 +274,9 @@ MonoPictureAsset::equals (shared_ptr other, EqualityOptions opt, li } bool -StereoPictureAsset::equals (shared_ptr other, EqualityOptions opt, list& notes) const +StereoPictureAsset::equals (shared_ptr other, EqualityOptions opt, boost::function note) const { - if (!PictureAsset::equals (other, opt, notes)) { + if (!PictureAsset::equals (other, opt, note)) { return false; } @@ -288,7 +288,7 @@ StereoPictureAsset::equals (shared_ptr other, EqualityOptions opt, shared_ptr frame_B = other_picture->get_frame (i); if (!frame_buffer_equals ( - i, opt, notes, + i, opt, note, frame_A->left_j2k_data(), frame_A->left_j2k_size(), frame_B->left_j2k_data(), frame_B->left_j2k_size() )) { @@ -296,7 +296,7 @@ StereoPictureAsset::equals (shared_ptr other, EqualityOptions opt, } if (!frame_buffer_equals ( - i, opt, notes, + i, opt, note, frame_A->right_j2k_data(), frame_A->right_j2k_size(), frame_B->right_j2k_data(), frame_B->right_j2k_size() )) { @@ -309,7 +309,8 @@ StereoPictureAsset::equals (shared_ptr other, EqualityOptions opt, bool PictureAsset::frame_buffer_equals ( - int frame, EqualityOptions opt, list& notes, uint8_t const * data_A, unsigned int size_A, uint8_t const * data_B, unsigned int size_B + int frame, EqualityOptions opt, boost::function note, + uint8_t const * data_A, unsigned int size_A, uint8_t const * data_B, unsigned int size_B ) const { if (size_A == size_B && memcmp (data_A, data_B, size_A) == 0) { @@ -324,7 +325,7 @@ PictureAsset::frame_buffer_equals ( /* Compare them */ if (image_A->numcomps != image_B->numcomps) { - notes.push_back ("image component counts for frame " + lexical_cast(frame) + " differ"); + note ("image component counts for frame " + lexical_cast(frame) + " differ"); return false; } @@ -335,7 +336,7 @@ PictureAsset::frame_buffer_equals ( for (int c = 0; c < image_A->numcomps; ++c) { if (image_A->comps[c].w != image_B->comps[c].w || image_A->comps[c].h != image_B->comps[c].h) { - notes.push_back ("image sizes for frame " + lexical_cast(frame) + " differ"); + note ("image sizes for frame " + lexical_cast(frame) + " differ"); return false; } @@ -362,7 +363,7 @@ PictureAsset::frame_buffer_equals ( double const std_dev = sqrt (double (total_squared_deviation) / abs_diffs.size()); if (mean > opt.max_mean_pixel_error || std_dev > opt.max_std_dev_pixel_error) { - notes.push_back ("mean or standard deviation out of range for " + lexical_cast(frame)); + note ("mean or standard deviation out of range for " + lexical_cast(frame)); return false; } diff --git a/src/picture_asset.h b/src/picture_asset.h index d3fabbbd..f4d4d7a4 100644 --- a/src/picture_asset.h +++ b/src/picture_asset.h @@ -63,7 +63,7 @@ public: */ void write_to_cpl (std::ostream& s) const; - bool equals (boost::shared_ptr other, EqualityOptions opt, std::list& notes) const; + bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function note) const; Size size () const { return _size; @@ -72,7 +72,7 @@ public: protected: bool frame_buffer_equals ( - int frame, EqualityOptions opt, std::list& notes, + int frame, EqualityOptions opt, boost::function note, uint8_t const * data_A, unsigned int size_A, uint8_t const * data_B, unsigned int size_B ) const; @@ -210,7 +210,7 @@ public: boost::shared_ptr start_write (bool); boost::shared_ptr get_frame (int n) const; - bool equals (boost::shared_ptr other, EqualityOptions opt, std::list& notes) const; + bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function note) const; private: std::string path_from_list (int f, std::vector const & files) const; @@ -224,7 +224,7 @@ public: StereoPictureAsset (std::string directory, std::string mxf_name, int fps, int intrinsic_duration); boost::shared_ptr get_frame (int n) const; - bool equals (boost::shared_ptr other, EqualityOptions opt, std::list& notes) const; + bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function note) const; }; diff --git a/src/reel.cc b/src/reel.cc index 8995f874..096acf19 100644 --- a/src/reel.cc +++ b/src/reel.cc @@ -50,32 +50,32 @@ Reel::write_to_cpl (ostream& s) const } bool -Reel::equals (boost::shared_ptr other, EqualityOptions opt, list& notes) const +Reel::equals (boost::shared_ptr other, EqualityOptions opt, boost::function note) const { if ((_main_picture && !other->_main_picture) || (!_main_picture && other->_main_picture)) { - notes.push_back ("reel has different assets"); + note ("reel has different assets"); return false; } - if (_main_picture && !_main_picture->equals (other->_main_picture, opt, notes)) { + if (_main_picture && !_main_picture->equals (other->_main_picture, opt, note)) { return false; } if ((_main_sound && !other->_main_sound) || (!_main_sound && other->_main_sound)) { - notes.push_back ("reel has different assets"); + note ("reel has different assets"); return false; } - if (_main_sound && !_main_sound->equals (other->_main_sound, opt, notes)) { + if (_main_sound && !_main_sound->equals (other->_main_sound, opt, note)) { return false; } if ((_main_subtitle && !other->_main_subtitle) || (!_main_subtitle && other->_main_subtitle)) { - notes.push_back ("reel has different assets"); + note ("reel has different assets"); return false; } - if (_main_subtitle && !_main_subtitle->equals (other->_main_subtitle, opt, notes)) { + if (_main_subtitle && !_main_subtitle->equals (other->_main_subtitle, opt, note)) { return false; } diff --git a/src/reel.h b/src/reel.h index c7d3b164..b0dfc84d 100644 --- a/src/reel.h +++ b/src/reel.h @@ -19,6 +19,7 @@ #include #include +#include #include "types.h" namespace libdcp { @@ -55,7 +56,7 @@ public: void write_to_cpl (std::ostream & s) const; - bool equals (boost::shared_ptr other, EqualityOptions opt, std::list& notes) const; + bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function notes) const; private: boost::shared_ptr _main_picture; diff --git a/src/sound_asset.cc b/src/sound_asset.cc index e18441c6..da6e72bc 100644 --- a/src/sound_asset.cc +++ b/src/sound_asset.cc @@ -222,9 +222,9 @@ SoundAsset::write_to_cpl (ostream& s) const } bool -SoundAsset::equals (shared_ptr other, EqualityOptions opt, list& notes) const +SoundAsset::equals (shared_ptr other, EqualityOptions opt, boost::function note) const { - if (!MXFAsset::equals (other, opt, notes)) { + if (!MXFAsset::equals (other, opt, note)) { return false; } @@ -260,7 +260,7 @@ SoundAsset::equals (shared_ptr other, EqualityOptions opt, list other, EqualityOptions opt, list(i) + " differ"); + note ("sizes of audio data for frame " + lexical_cast(i) + " differ"); return false; } @@ -285,7 +285,7 @@ SoundAsset::equals (shared_ptr other, EqualityOptions opt, list opt.max_audio_sample_error) { - notes.push_back ("PCM data difference of " + lexical_cast (d)); + note ("PCM data difference of " + lexical_cast (d)); return false; } } diff --git a/src/sound_asset.h b/src/sound_asset.h index ad350ce5..dedebac3 100644 --- a/src/sound_asset.h +++ b/src/sound_asset.h @@ -129,7 +129,7 @@ public: */ void write_to_cpl (std::ostream& s) const; - bool equals (boost::shared_ptr other, EqualityOptions opt, std::list& notes) const; + bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function note) const; boost::shared_ptr get_frame (int n) const; diff --git a/src/subtitle_asset.h b/src/subtitle_asset.h index 71ae42fc..b3936dc2 100644 --- a/src/subtitle_asset.h +++ b/src/subtitle_asset.h @@ -184,9 +184,9 @@ public: SubtitleAsset (std::string directory, std::string movie_title, std::string language); void write_to_cpl (std::ostream&) const; - virtual bool equals (boost::shared_ptr, EqualityOptions, std::list& notes) const { + virtual bool equals (boost::shared_ptr, EqualityOptions, boost::function note) const { /* XXX */ - notes.push_back ("subtitle assets not compared yet"); + note ("subtitle assets not compared yet"); return true; } diff --git a/tools/dcpdiff.cc b/tools/dcpdiff.cc index 025308e6..6d55586d 100644 --- a/tools/dcpdiff.cc +++ b/tools/dcpdiff.cc @@ -20,6 +20,12 @@ help (string n) << "and differing UUIDs.\n"; } +void +note (string n) +{ + cout << " " << n << "\n"; +} + int main (int argc, char* argv[]) { @@ -87,12 +93,7 @@ main (int argc, char* argv[]) /* I think this is just below the LSB at 16-bits (ie the 8th most significant bit at 24-bit) */ options.max_audio_sample_error = 255; - list notes; - bool equals = a->equals (*b, options, notes); - - for (list::iterator i = notes.begin(); i != notes.end(); ++i) { - cout << " " << *i << "\n"; - } + bool const equals = a->equals (*b, options, boost::bind (note, _1)); if (equals) { exit (EXIT_SUCCESS); -- cgit v1.2.3 From 034abb6bb0f1d0382620bdcc43501ce0ba30b03a Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 15 Apr 2013 13:48:22 +0100 Subject: Try to give basic progress indication on dcpdiff. --- src/asset.h | 2 +- src/dcp.cc | 16 ++++++++-------- src/dcp.h | 4 ++-- src/mxf_asset.cc | 12 ++++++------ src/mxf_asset.h | 2 +- src/picture_asset.cc | 17 +++++++++-------- src/picture_asset.h | 8 ++++---- src/reel.cc | 8 ++++---- src/reel.h | 2 +- src/sound_asset.cc | 8 ++++---- src/sound_asset.h | 2 +- src/subtitle_asset.h | 4 ++-- src/types.h | 5 +++++ tools/dcpdiff.cc | 23 ++++++++++++++++------- 14 files changed, 64 insertions(+), 49 deletions(-) (limited to 'src/dcp.cc') diff --git a/src/asset.h b/src/asset.h index 527dea7a..1b1bf4c6 100644 --- a/src/asset.h +++ b/src/asset.h @@ -81,7 +81,7 @@ public: _file_name = f; } - virtual bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function) const = 0; + virtual bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function) const = 0; protected: diff --git a/src/dcp.cc b/src/dcp.cc index 49d41c70..bac266ab 100644 --- a/src/dcp.cc +++ b/src/dcp.cc @@ -248,10 +248,10 @@ DCP::read (bool require_mxfs) } bool -DCP::equals (DCP const & other, EqualityOptions opt, boost::function note) const +DCP::equals (DCP const & other, EqualityOptions opt, boost::function note) const { if (_cpls.size() != other._cpls.size()) { - note ("CPL counts differ"); + note (ERROR, "CPL counts differ"); return false; } @@ -516,30 +516,30 @@ CPL::write_to_assetmap (ostream& s) const bool -CPL::equals (CPL const & other, EqualityOptions opt, boost::function note) const +CPL::equals (CPL const & other, EqualityOptions opt, boost::function note) const { if (_name != other._name) { - note ("names differ"); + note (ERROR, "names differ"); return false; } if (_content_kind != other._content_kind) { - note ("content kinds differ"); + note (ERROR, "content kinds differ"); return false; } if (_fps != other._fps) { - note ("frames per second differ"); + note (ERROR, "frames per second differ"); return false; } if (_length != other._length) { - note ("lengths differ"); + note (ERROR, "lengths differ"); return false; } if (_reels.size() != other._reels.size()) { - note ("reel counts differ"); + note (ERROR, "reel counts differ"); return false; } diff --git a/src/dcp.h b/src/dcp.h index 7e9b4edc..9e2e8a02 100644 --- a/src/dcp.h +++ b/src/dcp.h @@ -84,7 +84,7 @@ public: std::list > assets () const; - bool equals (CPL const & other, EqualityOptions options, boost::function note) const; + bool equals (CPL const & other, EqualityOptions options, boost::function note) const; void write_xml () const; void write_to_assetmap (std::ostream& s) const; @@ -144,7 +144,7 @@ public: * @param options Options to define what "equality" means. * @return true if the DCPs are equal according to EqualityOptions, otherwise false. */ - bool equals (DCP const & other, EqualityOptions options, boost::function note) const; + bool equals (DCP const & other, EqualityOptions options, boost::function note) const; /** Add a CPL to this DCP. * @param cpl CPL to add. diff --git a/src/mxf_asset.cc b/src/mxf_asset.cc index cf265712..9b491dd7 100644 --- a/src/mxf_asset.cc +++ b/src/mxf_asset.cc @@ -71,31 +71,31 @@ MXFAsset::fill_writer_info (ASDCP::WriterInfo* writer_info, string uuid) } bool -MXFAsset::equals (shared_ptr other, EqualityOptions, boost::function note) const +MXFAsset::equals (shared_ptr other, EqualityOptions, boost::function note) const { shared_ptr other_mxf = dynamic_pointer_cast (other); if (!other_mxf) { - note ("comparing an MXF asset with a non-MXF asset"); + note (ERROR, "comparing an MXF asset with a non-MXF asset"); return false; } if (_file_name != other_mxf->_file_name) { - note ("MXF names differ"); + note (ERROR, "MXF names differ"); return false; } if (_edit_rate != other_mxf->_edit_rate) { - note ("MXF edit rates differ"); + note (ERROR, "MXF edit rates differ"); return false; } if (_intrinsic_duration != other_mxf->_intrinsic_duration) { - note ("MXF intrinsic durations differ"); + note (ERROR, "MXF intrinsic durations differ"); return false; } if (_duration != other_mxf->_duration) { - note ("MXF durations differ"); + note (ERROR, "MXF durations differ"); return false; } diff --git a/src/mxf_asset.h b/src/mxf_asset.h index 0c98f3c6..29b3c1b0 100644 --- a/src/mxf_asset.h +++ b/src/mxf_asset.h @@ -61,7 +61,7 @@ public: _intrinsic_duration = d; } - virtual bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function note) const; + virtual bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function note) const; int intrinsic_duration () const { return _intrinsic_duration; diff --git a/src/picture_asset.cc b/src/picture_asset.cc index 807564c5..4b775980 100644 --- a/src/picture_asset.cc +++ b/src/picture_asset.cc @@ -79,7 +79,7 @@ PictureAsset::write_to_cpl (ostream& s) const } bool -PictureAsset::equals (shared_ptr other, EqualityOptions opt, boost::function note) const +PictureAsset::equals (shared_ptr other, EqualityOptions opt, boost::function note) const { if (!MXFAsset::equals (other, opt, note)) { return false; @@ -125,7 +125,7 @@ PictureAsset::equals (shared_ptr other, EqualityOptions opt, boost: // desc_A.QuantizationDefault != desc_B.QuantizationDefault ) { - note ("video MXF picture descriptors differ"); + note (ERROR, "video MXF picture descriptors differ"); return false; } @@ -248,7 +248,7 @@ MonoPictureAsset::get_frame (int n) const bool -MonoPictureAsset::equals (shared_ptr other, EqualityOptions opt, boost::function note) const +MonoPictureAsset::equals (shared_ptr other, EqualityOptions opt, boost::function note) const { if (!PictureAsset::equals (other, opt, note)) { return false; @@ -258,6 +258,7 @@ MonoPictureAsset::equals (shared_ptr other, EqualityOptions opt, bo assert (other_picture); for (int i = 0; i < _intrinsic_duration; ++i) { + note (PROGRESS, "Comparing video frame " + lexical_cast (i) + " of " + lexical_cast (_intrinsic_duration)); shared_ptr frame_A = get_frame (i); shared_ptr frame_B = other_picture->get_frame (i); @@ -274,7 +275,7 @@ MonoPictureAsset::equals (shared_ptr other, EqualityOptions opt, bo } bool -StereoPictureAsset::equals (shared_ptr other, EqualityOptions opt, boost::function note) const +StereoPictureAsset::equals (shared_ptr other, EqualityOptions opt, boost::function note) const { if (!PictureAsset::equals (other, opt, note)) { return false; @@ -309,7 +310,7 @@ StereoPictureAsset::equals (shared_ptr other, EqualityOptions opt, bool PictureAsset::frame_buffer_equals ( - int frame, EqualityOptions opt, boost::function note, + int frame, EqualityOptions opt, boost::function note, uint8_t const * data_A, unsigned int size_A, uint8_t const * data_B, unsigned int size_B ) const { @@ -325,7 +326,7 @@ PictureAsset::frame_buffer_equals ( /* Compare them */ if (image_A->numcomps != image_B->numcomps) { - note ("image component counts for frame " + lexical_cast(frame) + " differ"); + note (ERROR, "image component counts for frame " + lexical_cast(frame) + " differ"); return false; } @@ -336,7 +337,7 @@ PictureAsset::frame_buffer_equals ( for (int c = 0; c < image_A->numcomps; ++c) { if (image_A->comps[c].w != image_B->comps[c].w || image_A->comps[c].h != image_B->comps[c].h) { - note ("image sizes for frame " + lexical_cast(frame) + " differ"); + note (ERROR, "image sizes for frame " + lexical_cast(frame) + " differ"); return false; } @@ -363,7 +364,7 @@ PictureAsset::frame_buffer_equals ( double const std_dev = sqrt (double (total_squared_deviation) / abs_diffs.size()); if (mean > opt.max_mean_pixel_error || std_dev > opt.max_std_dev_pixel_error) { - note ("mean or standard deviation out of range for " + lexical_cast(frame)); + note (ERROR, "mean or standard deviation out of range for " + lexical_cast(frame)); return false; } diff --git a/src/picture_asset.h b/src/picture_asset.h index f4d4d7a4..c9226b1f 100644 --- a/src/picture_asset.h +++ b/src/picture_asset.h @@ -63,7 +63,7 @@ public: */ void write_to_cpl (std::ostream& s) const; - bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function note) const; + bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function note) const; Size size () const { return _size; @@ -72,7 +72,7 @@ public: protected: bool frame_buffer_equals ( - int frame, EqualityOptions opt, boost::function note, + int frame, EqualityOptions opt, boost::function note, uint8_t const * data_A, unsigned int size_A, uint8_t const * data_B, unsigned int size_B ) const; @@ -210,7 +210,7 @@ public: boost::shared_ptr start_write (bool); boost::shared_ptr get_frame (int n) const; - bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function note) const; + bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function note) const; private: std::string path_from_list (int f, std::vector const & files) const; @@ -224,7 +224,7 @@ public: StereoPictureAsset (std::string directory, std::string mxf_name, int fps, int intrinsic_duration); boost::shared_ptr get_frame (int n) const; - bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function note) const; + bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function note) const; }; diff --git a/src/reel.cc b/src/reel.cc index 096acf19..86533ea2 100644 --- a/src/reel.cc +++ b/src/reel.cc @@ -50,10 +50,10 @@ Reel::write_to_cpl (ostream& s) const } bool -Reel::equals (boost::shared_ptr other, EqualityOptions opt, boost::function note) const +Reel::equals (boost::shared_ptr other, EqualityOptions opt, boost::function note) const { if ((_main_picture && !other->_main_picture) || (!_main_picture && other->_main_picture)) { - note ("reel has different assets"); + note (ERROR, "reel has different assets"); return false; } @@ -62,7 +62,7 @@ Reel::equals (boost::shared_ptr other, EqualityOptions opt, boost::f } if ((_main_sound && !other->_main_sound) || (!_main_sound && other->_main_sound)) { - note ("reel has different assets"); + note (ERROR, "reel has different assets"); return false; } @@ -71,7 +71,7 @@ Reel::equals (boost::shared_ptr other, EqualityOptions opt, boost::f } if ((_main_subtitle && !other->_main_subtitle) || (!_main_subtitle && other->_main_subtitle)) { - note ("reel has different assets"); + note (ERROR, "reel has different assets"); return false; } diff --git a/src/reel.h b/src/reel.h index b0dfc84d..93dc0920 100644 --- a/src/reel.h +++ b/src/reel.h @@ -56,7 +56,7 @@ public: void write_to_cpl (std::ostream & s) const; - bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function notes) const; + bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function notes) const; private: boost::shared_ptr _main_picture; diff --git a/src/sound_asset.cc b/src/sound_asset.cc index da6e72bc..6e29aadf 100644 --- a/src/sound_asset.cc +++ b/src/sound_asset.cc @@ -222,7 +222,7 @@ SoundAsset::write_to_cpl (ostream& s) const } bool -SoundAsset::equals (shared_ptr other, EqualityOptions opt, boost::function note) const +SoundAsset::equals (shared_ptr other, EqualityOptions opt, boost::function note) const { if (!MXFAsset::equals (other, opt, note)) { return false; @@ -260,7 +260,7 @@ SoundAsset::equals (shared_ptr other, EqualityOptions opt, boost::f // desc_A.ChannelFormat != desc_B.ChannelFormat || ) { - note ("audio MXF picture descriptors differ"); + note (ERROR, "audio MXF picture descriptors differ"); return false; } @@ -277,7 +277,7 @@ SoundAsset::equals (shared_ptr other, EqualityOptions opt, boost::f } if (buffer_A.Size() != buffer_B.Size()) { - note ("sizes of audio data for frame " + lexical_cast(i) + " differ"); + note (ERROR, "sizes of audio data for frame " + lexical_cast(i) + " differ"); return false; } @@ -285,7 +285,7 @@ SoundAsset::equals (shared_ptr other, EqualityOptions opt, boost::f for (uint32_t i = 0; i < buffer_A.Size(); ++i) { int const d = abs (buffer_A.RoData()[i] - buffer_B.RoData()[i]); if (d > opt.max_audio_sample_error) { - note ("PCM data difference of " + lexical_cast (d)); + note (ERROR, "PCM data difference of " + lexical_cast (d)); return false; } } diff --git a/src/sound_asset.h b/src/sound_asset.h index dedebac3..9e6e75cf 100644 --- a/src/sound_asset.h +++ b/src/sound_asset.h @@ -129,7 +129,7 @@ public: */ void write_to_cpl (std::ostream& s) const; - bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function note) const; + bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function note) const; boost::shared_ptr get_frame (int n) const; diff --git a/src/subtitle_asset.h b/src/subtitle_asset.h index b3936dc2..1e31df2b 100644 --- a/src/subtitle_asset.h +++ b/src/subtitle_asset.h @@ -184,9 +184,9 @@ public: SubtitleAsset (std::string directory, std::string movie_title, std::string language); void write_to_cpl (std::ostream&) const; - virtual bool equals (boost::shared_ptr, EqualityOptions, boost::function note) const { + virtual bool equals (boost::shared_ptr, EqualityOptions, boost::function note) const { /* XXX */ - note ("subtitle assets not compared yet"); + note (ERROR, "subtitle assets not compared yet"); return true; } diff --git a/src/types.h b/src/types.h index ebcfb838..4c824080 100644 --- a/src/types.h +++ b/src/types.h @@ -107,6 +107,11 @@ struct EqualityOptions { int max_audio_sample_error; }; +enum NoteType { + PROGRESS, + ERROR +}; + /** @class Color * @brief An RGB color (aka colour). */ diff --git a/tools/dcpdiff.cc b/tools/dcpdiff.cc index 6d55586d..7913c533 100644 --- a/tools/dcpdiff.cc +++ b/tools/dcpdiff.cc @@ -8,12 +8,15 @@ using namespace std; using namespace boost; using namespace libdcp; +static bool verbose = false; + static void help (string n) { cerr << "Syntax: " << n << " [OPTION] \n" - << " -v, --version show libdcp version\n" + << " -V, --version show libdcp version\n" << " -h, --help show this help\n" + << " -v, --verbose be verbose\n" << "\n" << "The s are the DCP directories to compare.\n" << "Comparison is of metadata and content, ignoring timestamps\n" @@ -21,9 +24,11 @@ help (string n) } void -note (string n) +note (NoteType t, string n) { - cout << " " << n << "\n"; + if (t == ERROR || (t == PROGRESS && verbose)) { + cout << " " << n << "\n"; + } } int @@ -34,24 +39,28 @@ main (int argc, char* argv[]) int option_index = 0; while (1) { static struct option long_options[] = { - { "version", no_argument, 0, 'v'}, + { "version", no_argument, 0, 'V'}, { "help", no_argument, 0, 'h'}, + { "verbose", no_argument, 0, 'v'}, { 0, 0, 0, 0 } }; - int c = getopt_long (argc, argv, "vh", long_options, &option_index); + int c = getopt_long (argc, argv, "Vhv", long_options, &option_index); if (c == -1) { break; } switch (c) { - case 'v': + case 'V': cout << "dcpdiff version " << LIBDCP_VERSION << "\n"; exit (EXIT_SUCCESS); case 'h': help (argv[0]); exit (EXIT_SUCCESS); + case 'v': + verbose = true; + break; } } @@ -93,7 +102,7 @@ main (int argc, char* argv[]) /* I think this is just below the LSB at 16-bits (ie the 8th most significant bit at 24-bit) */ options.max_audio_sample_error = 255; - bool const equals = a->equals (*b, options, boost::bind (note, _1)); + bool const equals = a->equals (*b, options, boost::bind (note, _1, _2)); if (equals) { exit (EXIT_SUCCESS); -- cgit v1.2.3 From 09ad2806848f5c3609b7915da504f94db099e3af Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sat, 4 May 2013 09:58:35 +0100 Subject: Split CPL up into its own files. --- examples/make_dcp.cc | 2 + src/cpl.cc | 296 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/cpl.h | 95 +++++++++++++++++ src/dcp.cc | 259 +------------------------------------------- src/dcp.h | 67 +----------- src/wscript | 1 + test/rewrite_subs.cc | 1 + test/tests.cc | 1 + tools/dcpinfo.cc | 1 + 9 files changed, 400 insertions(+), 323 deletions(-) create mode 100644 src/cpl.cc create mode 100644 src/cpl.h (limited to 'src/dcp.cc') diff --git a/examples/make_dcp.cc b/examples/make_dcp.cc index 3891db3f..06dd05ab 100644 --- a/examples/make_dcp.cc +++ b/examples/make_dcp.cc @@ -26,11 +26,13 @@ /* If you are using an installed libdcp, these #includes would need to be changed to #include +#include #include ... etc. ... */ #include "dcp.h" +#include "cpl.h" #include "picture_asset.h" #include "sound_asset.h" #include "reel.h" diff --git a/src/cpl.cc b/src/cpl.cc new file mode 100644 index 00000000..90c48ae9 --- /dev/null +++ b/src/cpl.cc @@ -0,0 +1,296 @@ +/* + Copyright (C) 2012 Carl Hetherington + + 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 +#include "cpl.h" +#include "cpl_file.h" +#include "util.h" +#include "picture_asset.h" +#include "sound_asset.h" +#include "subtitle_asset.h" +#include "asset_map.h" +#include "reel.h" +#include "metadata.h" + +using std::string; +using std::stringstream; +using std::ofstream; +using std::ostream; +using std::list; +using boost::shared_ptr; +using namespace libdcp; + +CPL::CPL (string directory, string name, ContentKind content_kind, int length, int frames_per_second) + : _directory (directory) + , _name (name) + , _content_kind (content_kind) + , _length (length) + , _fps (frames_per_second) +{ + _uuid = make_uuid (); +} + +/** Construct a CPL object from a XML file. + * @param directory The directory containing this CPL's DCP. + * @param file The CPL XML filename. + * @param asset_map The corresponding asset map. + * @param require_mxfs true to throw an exception if a required MXF file does not exist. + */ +CPL::CPL (string directory, string file, shared_ptr asset_map, bool require_mxfs) + : _directory (directory) + , _content_kind (FEATURE) + , _length (0) + , _fps (0) +{ + /* Read the XML */ + shared_ptr cpl; + try { + cpl.reset (new CPLFile (file)); + } catch (FileError& e) { + boost::throw_exception (FileError ("could not load CPL file", file)); + } + + /* Now cherry-pick the required bits into our own data structure */ + + _name = cpl->annotation_text; + _content_kind = cpl->content_kind; + + for (list >::iterator i = cpl->reels.begin(); i != cpl->reels.end(); ++i) { + + shared_ptr p; + + if ((*i)->asset_list->main_picture) { + p = (*i)->asset_list->main_picture; + } else { + p = (*i)->asset_list->main_stereoscopic_picture; + } + + _fps = p->edit_rate.numerator; + _length += p->duration; + + shared_ptr picture; + shared_ptr sound; + shared_ptr subtitle; + + /* Some rather twisted logic to decide if we are 3D or not; + some DCPs give a MainStereoscopicPicture to indicate 3D, others + just have a FrameRate twice the EditRate and apparently + expect you to divine the fact that they are hence 3D. + */ + + if (!(*i)->asset_list->main_stereoscopic_picture && p->edit_rate == p->frame_rate) { + + try { + picture.reset (new MonoPictureAsset ( + _directory, + asset_map->asset_from_id (p->id)->chunks.front()->path + ) + ); + + picture->set_entry_point ((*i)->asset_list->main_picture->entry_point); + } catch (MXFFileError) { + if (require_mxfs) { + throw; + } + } + + } else { + + try { + picture.reset (new StereoPictureAsset ( + _directory, + asset_map->asset_from_id (p->id)->chunks.front()->path, + _fps, + p->duration + ) + ); + + picture->set_entry_point (p->entry_point); + + } catch (MXFFileError) { + if (require_mxfs) { + throw; + } + } + + } + + if ((*i)->asset_list->main_sound) { + + try { + sound.reset (new SoundAsset ( + _directory, + asset_map->asset_from_id ((*i)->asset_list->main_sound->id)->chunks.front()->path + ) + ); + + sound->set_entry_point ((*i)->asset_list->main_sound->entry_point); + } catch (MXFFileError) { + if (require_mxfs) { + throw; + } + } + } + + if ((*i)->asset_list->main_subtitle) { + + subtitle.reset (new SubtitleAsset ( + _directory, + asset_map->asset_from_id ((*i)->asset_list->main_subtitle->id)->chunks.front()->path + ) + ); + } + + _reels.push_back (shared_ptr (new Reel (picture, sound, subtitle))); + } +} + +void +CPL::add_reel (shared_ptr reel) +{ + _reels.push_back (reel); +} + +void +CPL::write_xml () const +{ + boost::filesystem::path p; + p /= _directory; + stringstream s; + s << _uuid << "_cpl.xml"; + p /= s.str(); + ofstream os (p.string().c_str()); + + os << "\n" + << "\n" + << " urn:uuid:" << _uuid << "\n" + << " " << _name << "\n" + << " " << Metadata::instance()->issue_date << "\n" + << " " << Metadata::instance()->creator << "\n" + << " " << _name << "\n" + << " " << content_kind_to_string (_content_kind) << "\n" + << " \n" + << " urn:uri:" << _uuid << "_" << Metadata::instance()->issue_date << "\n" + << " " << _uuid << "_" << Metadata::instance()->issue_date << "\n" + << " \n" + << " \n" + << " \n"; + + for (list >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) { + (*i)->write_to_cpl (os); + } + + os << " \n" + << "\n"; + + os.close (); + + _digest = make_digest (p.string ()); + _length = boost::filesystem::file_size (p.string ()); +} + +void +CPL::write_to_pkl (ostream& s) const +{ + s << " \n" + << " urn:uuid:" << _uuid << "\n" + << " " << _digest << "\n" + << " " << _length << "\n" + << " text/xml\n" + << " \n"; +} + +list > +CPL::assets () const +{ + list > a; + for (list >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) { + if ((*i)->main_picture ()) { + a.push_back ((*i)->main_picture ()); + } + if ((*i)->main_sound ()) { + a.push_back ((*i)->main_sound ()); + } + if ((*i)->main_subtitle ()) { + a.push_back ((*i)->main_subtitle ()); + } + } + + return a; +} + +void +CPL::write_to_assetmap (ostream& s) const +{ + s << " \n" + << " urn:uuid:" << _uuid << "\n" + << " \n" + << " \n" + << " " << _uuid << "_cpl.xml\n" + << " 1\n" + << " 0\n" + << " " << _length << "\n" + << " \n" + << " \n" + << " \n"; +} + + + +bool +CPL::equals (CPL const & other, EqualityOptions opt, boost::function note) const +{ + if (_name != other._name) { + note (ERROR, "names differ"); + return false; + } + + if (_content_kind != other._content_kind) { + note (ERROR, "content kinds differ"); + return false; + } + + if (_fps != other._fps) { + note (ERROR, "frames per second differ"); + return false; + } + + if (_length != other._length) { + note (ERROR, "lengths differ"); + return false; + } + + if (_reels.size() != other._reels.size()) { + note (ERROR, "reel counts differ"); + return false; + } + + list >::const_iterator a = _reels.begin (); + list >::const_iterator b = other._reels.begin (); + + while (a != _reels.end ()) { + if (!(*a)->equals (*b, opt, note)) { + return false; + } + ++a; + ++b; + } + + return true; +} diff --git a/src/cpl.h b/src/cpl.h new file mode 100644 index 00000000..3be10894 --- /dev/null +++ b/src/cpl.h @@ -0,0 +1,95 @@ +/* + Copyright (C) 2012 Carl Hetherington + + 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 +#include +#include +#include "types.h" + +namespace libdcp { + +class AssetMap; +class Asset; +class Reel; + +/** @brief A CPL within a DCP */ +class CPL +{ +public: + CPL (std::string directory, std::string name, ContentKind content_kind, int length, int frames_per_second); + CPL (std::string directory, std::string file, boost::shared_ptr asset_map, bool require_mxfs = true); + + void add_reel (boost::shared_ptr reel); + + /** @return the length in frames */ + int length () const { + return _length; + } + + /** @return the type of the content, used by media servers + * to categorise things (e.g. feature, trailer, etc.) + */ + ContentKind content_kind () const { + return _content_kind; + } + + std::list > reels () const { + return _reels; + } + + /** @return the CPL's name, as will be presented on projector + * media servers and theatre management systems. + */ + std::string name () const { + return _name; + } + + /** @return the number of frames per second */ + int frames_per_second () const { + return _fps; + } + + std::list > assets () const; + + bool equals (CPL const & other, EqualityOptions options, boost::function note) const; + + void write_xml () const; + void write_to_assetmap (std::ostream& s) const; + void write_to_pkl (std::ostream& s) const; + +private: + std::string _directory; + /** the name of the DCP */ + std::string _name; + /** the content kind of the CPL */ + ContentKind _content_kind; + /** length in frames */ + mutable int _length; + /** frames per second */ + int _fps; + /** reels */ + std::list > _reels; + + /** our UUID */ + std::string _uuid; + /** a SHA1 digest of our XML */ + mutable std::string _digest; +}; + +} diff --git a/src/dcp.cc b/src/dcp.cc index bac266ab..e74e0d95 100644 --- a/src/dcp.cc +++ b/src/dcp.cc @@ -41,6 +41,7 @@ #include "pkl_file.h" #include "asset_map.h" #include "reel.h" +#include "cpl.h" using std::string; using std::list; @@ -298,261 +299,3 @@ DCP::assets () const return a; } -CPL::CPL (string directory, string name, ContentKind content_kind, int length, int frames_per_second) - : _directory (directory) - , _name (name) - , _content_kind (content_kind) - , _length (length) - , _fps (frames_per_second) -{ - _uuid = make_uuid (); -} - -/** Construct a CPL object from a XML file. - * @param directory The directory containing this CPL's DCP. - * @param file The CPL XML filename. - * @param asset_map The corresponding asset map. - * @param require_mxfs true to throw an exception if a required MXF file does not exist. - */ -CPL::CPL (string directory, string file, shared_ptr asset_map, bool require_mxfs) - : _directory (directory) - , _content_kind (FEATURE) - , _length (0) - , _fps (0) -{ - /* Read the XML */ - shared_ptr cpl; - try { - cpl.reset (new CPLFile (file)); - } catch (FileError& e) { - boost::throw_exception (FileError ("could not load CPL file", file)); - } - - /* Now cherry-pick the required bits into our own data structure */ - - _name = cpl->annotation_text; - _content_kind = cpl->content_kind; - - for (list >::iterator i = cpl->reels.begin(); i != cpl->reels.end(); ++i) { - - shared_ptr p; - - if ((*i)->asset_list->main_picture) { - p = (*i)->asset_list->main_picture; - } else { - p = (*i)->asset_list->main_stereoscopic_picture; - } - - _fps = p->edit_rate.numerator; - _length += p->duration; - - shared_ptr picture; - shared_ptr sound; - shared_ptr subtitle; - - /* Some rather twisted logic to decide if we are 3D or not; - some DCPs give a MainStereoscopicPicture to indicate 3D, others - just have a FrameRate twice the EditRate and apparently - expect you to divine the fact that they are hence 3D. - */ - - if (!(*i)->asset_list->main_stereoscopic_picture && p->edit_rate == p->frame_rate) { - - try { - picture.reset (new MonoPictureAsset ( - _directory, - asset_map->asset_from_id (p->id)->chunks.front()->path - ) - ); - - picture->set_entry_point ((*i)->asset_list->main_picture->entry_point); - } catch (MXFFileError) { - if (require_mxfs) { - throw; - } - } - - } else { - - try { - picture.reset (new StereoPictureAsset ( - _directory, - asset_map->asset_from_id (p->id)->chunks.front()->path, - _fps, - p->duration - ) - ); - - picture->set_entry_point (p->entry_point); - - } catch (MXFFileError) { - if (require_mxfs) { - throw; - } - } - - } - - if ((*i)->asset_list->main_sound) { - - try { - sound.reset (new SoundAsset ( - _directory, - asset_map->asset_from_id ((*i)->asset_list->main_sound->id)->chunks.front()->path - ) - ); - - sound->set_entry_point ((*i)->asset_list->main_sound->entry_point); - } catch (MXFFileError) { - if (require_mxfs) { - throw; - } - } - } - - if ((*i)->asset_list->main_subtitle) { - - subtitle.reset (new SubtitleAsset ( - _directory, - asset_map->asset_from_id ((*i)->asset_list->main_subtitle->id)->chunks.front()->path - ) - ); - } - - _reels.push_back (shared_ptr (new Reel (picture, sound, subtitle))); - } -} - -void -CPL::add_reel (shared_ptr reel) -{ - _reels.push_back (reel); -} - -void -CPL::write_xml () const -{ - boost::filesystem::path p; - p /= _directory; - stringstream s; - s << _uuid << "_cpl.xml"; - p /= s.str(); - ofstream os (p.string().c_str()); - - os << "\n" - << "\n" - << " urn:uuid:" << _uuid << "\n" - << " " << _name << "\n" - << " " << Metadata::instance()->issue_date << "\n" - << " " << Metadata::instance()->creator << "\n" - << " " << _name << "\n" - << " " << content_kind_to_string (_content_kind) << "\n" - << " \n" - << " urn:uri:" << _uuid << "_" << Metadata::instance()->issue_date << "\n" - << " " << _uuid << "_" << Metadata::instance()->issue_date << "\n" - << " \n" - << " \n" - << " \n"; - - for (list >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) { - (*i)->write_to_cpl (os); - } - - os << " \n" - << "\n"; - - os.close (); - - _digest = make_digest (p.string ()); - _length = boost::filesystem::file_size (p.string ()); -} - -void -CPL::write_to_pkl (ostream& s) const -{ - s << " \n" - << " urn:uuid:" << _uuid << "\n" - << " " << _digest << "\n" - << " " << _length << "\n" - << " text/xml\n" - << " \n"; -} - -list > -CPL::assets () const -{ - list > a; - for (list >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) { - if ((*i)->main_picture ()) { - a.push_back ((*i)->main_picture ()); - } - if ((*i)->main_sound ()) { - a.push_back ((*i)->main_sound ()); - } - if ((*i)->main_subtitle ()) { - a.push_back ((*i)->main_subtitle ()); - } - } - - return a; -} - -void -CPL::write_to_assetmap (ostream& s) const -{ - s << " \n" - << " urn:uuid:" << _uuid << "\n" - << " \n" - << " \n" - << " " << _uuid << "_cpl.xml\n" - << " 1\n" - << " 0\n" - << " " << _length << "\n" - << " \n" - << " \n" - << " \n"; -} - - - -bool -CPL::equals (CPL const & other, EqualityOptions opt, boost::function note) const -{ - if (_name != other._name) { - note (ERROR, "names differ"); - return false; - } - - if (_content_kind != other._content_kind) { - note (ERROR, "content kinds differ"); - return false; - } - - if (_fps != other._fps) { - note (ERROR, "frames per second differ"); - return false; - } - - if (_length != other._length) { - note (ERROR, "lengths differ"); - return false; - } - - if (_reels.size() != other._reels.size()) { - note (ERROR, "reel counts differ"); - return false; - } - - list >::const_iterator a = _reels.begin (); - list >::const_iterator b = other._reels.begin (); - - while (a != _reels.end ()) { - if (!(*a)->equals (*b, opt, note)) { - return false; - } - ++a; - ++b; - } - - return true; -} diff --git a/src/dcp.h b/src/dcp.h index 9e2e8a02..decac4f2 100644 --- a/src/dcp.h +++ b/src/dcp.h @@ -44,72 +44,9 @@ class SoundAsset; class SubtitleAsset; class Reel; class AssetMap; +class CPL; -/** @brief A CPL within a DCP */ -class CPL -{ -public: - CPL (std::string directory, std::string name, ContentKind content_kind, int length, int frames_per_second); - CPL (std::string directory, std::string file, boost::shared_ptr asset_map, bool require_mxfs = true); - - void add_reel (boost::shared_ptr reel); - - /** @return the length in frames */ - int length () const { - return _length; - } - - /** @return the type of the content, used by media servers - * to categorise things (e.g. feature, trailer, etc.) - */ - ContentKind content_kind () const { - return _content_kind; - } - - std::list > reels () const { - return _reels; - } - - /** @return the CPL's name, as will be presented on projector - * media servers and theatre management systems. - */ - std::string name () const { - return _name; - } - - /** @return the number of frames per second */ - int frames_per_second () const { - return _fps; - } - - std::list > assets () const; - - bool equals (CPL const & other, EqualityOptions options, boost::function note) const; - - void write_xml () const; - void write_to_assetmap (std::ostream& s) const; - void write_to_pkl (std::ostream& s) const; - -private: - std::string _directory; - /** the name of the DCP */ - std::string _name; - /** the content kind of the CPL */ - ContentKind _content_kind; - /** length in frames */ - mutable int _length; - /** frames per second */ - int _fps; - /** reels */ - std::list > _reels; - - /** our UUID */ - std::string _uuid; - /** a SHA1 digest of our XML */ - mutable std::string _digest; -}; - -/** @class DCP dcp.h libdcp/dcp.h +/** @class DCP * @brief A class to create or read a DCP. */ diff --git a/src/wscript b/src/wscript index 3960f2b0..95092173 100644 --- a/src/wscript +++ b/src/wscript @@ -14,6 +14,7 @@ def build(bld): asset_map.cc cpl_file.cc dcp.cc + cpl.cc dcp_time.cc gamma_lut.cc metadata.cc diff --git a/test/rewrite_subs.cc b/test/rewrite_subs.cc index 651b207a..adb9f6b4 100644 --- a/test/rewrite_subs.cc +++ b/test/rewrite_subs.cc @@ -1,5 +1,6 @@ #include #include "dcp.h" +#include "cpl.h" #include "reel.h" #include "subtitle_asset.h" diff --git a/test/tests.cc b/test/tests.cc index 30c9f406..d33890b6 100644 --- a/test/tests.cc +++ b/test/tests.cc @@ -30,6 +30,7 @@ #include "sound_asset.h" #include "reel.h" #include "gamma_lut.h" +#include "cpl.h" #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MODULE libdcp_test diff --git a/tools/dcpinfo.cc b/tools/dcpinfo.cc index 40e2be99..04fec82f 100644 --- a/tools/dcpinfo.cc +++ b/tools/dcpinfo.cc @@ -8,6 +8,7 @@ #include "sound_asset.h" #include "picture_asset.h" #include "subtitle_asset.h" +#include "cpl.h" using std::string; using std::cerr; -- cgit v1.2.3 From af87bfc82beee0b0600558c84c3843dfd5a252f6 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sat, 4 May 2013 11:13:04 +0100 Subject: Split metadata into XML and MXF bits; remove singleton. --- examples/make_dcp.cc | 3 ++- src/cpl.cc | 10 +++++----- src/cpl.h | 3 ++- src/dcp.cc | 24 ++++++++++++------------ src/dcp.h | 7 ++++--- src/metadata.cc | 30 ++++++++++++++---------------- src/metadata.h | 29 ++++++++++++++++------------- src/mxf_asset.cc | 8 ++++---- src/mxf_asset.h | 6 ++++-- src/picture_asset.cc | 27 ++++++++++++++++----------- src/picture_asset.h | 14 +++++++++----- src/sound_asset.cc | 23 +++++++++++++---------- src/sound_asset.h | 15 +++++++++------ src/test_mode.cc | 45 --------------------------------------------- src/test_mode.h | 29 ----------------------------- src/wscript | 3 +-- test/tests.cc | 23 +++++++++++++---------- 17 files changed, 124 insertions(+), 175 deletions(-) delete mode 100644 src/test_mode.cc delete mode 100644 src/test_mode.h (limited to 'src/dcp.cc') diff --git a/examples/make_dcp.cc b/examples/make_dcp.cc index 06dd05ab..0d6a8215 100644 --- a/examples/make_dcp.cc +++ b/examples/make_dcp.cc @@ -108,7 +108,8 @@ main () /* Finally, we call this to write the XML description files to the DCP. After this, the DCP is ready to ingest and play. */ - dcp.write_xml (); + libdcp::XMLMetadata metadata; + dcp.write_xml (metadata); return 0; } diff --git a/src/cpl.cc b/src/cpl.cc index 90c48ae9..18526b24 100644 --- a/src/cpl.cc +++ b/src/cpl.cc @@ -168,7 +168,7 @@ CPL::add_reel (shared_ptr reel) } void -CPL::write_xml () const +CPL::write_xml (XMLMetadata const & metadata) const { boost::filesystem::path p; p /= _directory; @@ -181,13 +181,13 @@ CPL::write_xml () const << "\n" << " urn:uuid:" << _uuid << "\n" << " " << _name << "\n" - << " " << Metadata::instance()->issue_date << "\n" - << " " << Metadata::instance()->creator << "\n" + << " " << metadata.issue_date << "\n" + << " " << metadata.creator << "\n" << " " << _name << "\n" << " " << content_kind_to_string (_content_kind) << "\n" << " \n" - << " urn:uri:" << _uuid << "_" << Metadata::instance()->issue_date << "\n" - << " " << _uuid << "_" << Metadata::instance()->issue_date << "\n" + << " urn:uri:" << _uuid << "_" << metadata.issue_date << "\n" + << " " << _uuid << "_" << metadata.issue_date << "\n" << " \n" << " \n" << " \n"; diff --git a/src/cpl.h b/src/cpl.h index 3be10894..0abff749 100644 --- a/src/cpl.h +++ b/src/cpl.h @@ -27,6 +27,7 @@ namespace libdcp { class AssetMap; class Asset; class Reel; +class XMLMetadata; /** @brief A CPL within a DCP */ class CPL @@ -69,7 +70,7 @@ public: bool equals (CPL const & other, EqualityOptions options, boost::function note) const; - void write_xml () const; + void write_xml (XMLMetadata const &) const; void write_to_assetmap (std::ostream& s) const; void write_to_pkl (std::ostream& s) const; diff --git a/src/dcp.cc b/src/dcp.cc index e74e0d95..7af3f353 100644 --- a/src/dcp.cc +++ b/src/dcp.cc @@ -58,21 +58,21 @@ DCP::DCP (string directory) } void -DCP::write_xml () const +DCP::write_xml (XMLMetadata const & metadata) const { for (list >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) { - (*i)->write_xml (); + (*i)->write_xml (metadata); } string pkl_uuid = make_uuid (); - string pkl_path = write_pkl (pkl_uuid); + string pkl_path = write_pkl (pkl_uuid, metadata); write_volindex (); - write_assetmap (pkl_uuid, boost::filesystem::file_size (pkl_path)); + write_assetmap (pkl_uuid, boost::filesystem::file_size (pkl_path), metadata); } std::string -DCP::write_pkl (string pkl_uuid) const +DCP::write_pkl (string pkl_uuid, XMLMetadata const & metadata) const { assert (!_cpls.empty ()); @@ -88,9 +88,9 @@ DCP::write_pkl (string pkl_uuid) const << " urn:uuid:" << pkl_uuid << "\n" /* XXX: this is a bit of a hack */ << " " << _cpls.front()->name() << "\n" - << " " << Metadata::instance()->issue_date << "\n" - << " " << Metadata::instance()->issuer << "\n" - << " " << Metadata::instance()->creator << "\n" + << " " << metadata.issue_date << "\n" + << " " << metadata.issuer << "\n" + << " " << metadata.creator << "\n" << " \n"; list > a = assets (); @@ -123,7 +123,7 @@ DCP::write_volindex () const } void -DCP::write_assetmap (string pkl_uuid, int pkl_length) const +DCP::write_assetmap (string pkl_uuid, int pkl_length, XMLMetadata const & metadata) const { boost::filesystem::path p; p /= _directory; @@ -133,10 +133,10 @@ DCP::write_assetmap (string pkl_uuid, int pkl_length) const am << "\n" << "\n" << " urn:uuid:" << make_uuid() << "\n" - << " " << Metadata::instance()->creator << "\n" + << " " << metadata.creator << "\n" << " 1\n" - << " " << Metadata::instance()->issue_date << "\n" - << " " << Metadata::instance()->issuer << "\n" + << " " << metadata.issue_date << "\n" + << " " << metadata.issuer << "\n" << " \n"; am << " \n" diff --git a/src/dcp.h b/src/dcp.h index decac4f2..42c0c6d9 100644 --- a/src/dcp.h +++ b/src/dcp.h @@ -45,6 +45,7 @@ class SubtitleAsset; class Reel; class AssetMap; class CPL; +class XMLMetadata; /** @class DCP * @brief A class to create or read a DCP. @@ -74,7 +75,7 @@ public: /** Write the required XML files to the directory that was * passed into the constructor. */ - void write_xml () const; + void write_xml (XMLMetadata const &) const; /** Compare this DCP with another, according to various options. * @param other DCP to compare this one to. @@ -103,7 +104,7 @@ private: /** Write the PKL file. * @param pkl_uuid UUID to use. */ - std::string write_pkl (std::string pkl_uuid) const; + std::string write_pkl (std::string pkl_uuid, XMLMetadata const &) const; /** Write the VOLINDEX file */ void write_volindex () const; @@ -112,7 +113,7 @@ private: * @param pkl_uuid UUID of our PKL. * @param pkl_length Length of our PKL in bytes. */ - void write_assetmap (std::string pkl_uuid, int pkl_length) const; + void write_assetmap (std::string pkl_uuid, int pkl_length, XMLMetadata const &) const; /** @return Assets in all this CPLs in this DCP */ std::list > assets () const; diff --git a/src/metadata.cc b/src/metadata.cc index 7e900e50..2967ac1d 100644 --- a/src/metadata.cc +++ b/src/metadata.cc @@ -27,15 +27,24 @@ using namespace std; using namespace libdcp; -Metadata* Metadata::_instance = 0; - -/** Construct a Metadata object with some default values */ -Metadata::Metadata () +MXFMetadata::MXFMetadata () : company_name ("libdcp") , product_name ("libdcp") , product_version (LIBDCP_VERSION) - , issuer ("libdcp" LIBDCP_VERSION) +{ + +} + + +XMLMetadata::XMLMetadata () + : issuer ("libdcp" LIBDCP_VERSION) , creator ("libdcp" LIBDCP_VERSION) +{ + set_issue_date_now (); +} + +void +XMLMetadata::set_issue_date_now () { char buffer[64]; time_t now; @@ -44,15 +53,4 @@ Metadata::Metadata () strftime (buffer, 64, "%Y-%m-%dT%I:%M:%S+00:00", tm); issue_date = string (buffer); } - -/** @return Singleton Metadata instance */ -Metadata * -Metadata::instance () -{ - if (_instance == 0) { - _instance = new Metadata; - } - - return _instance; -} diff --git a/src/metadata.h b/src/metadata.h index 1610491e..7336766d 100644 --- a/src/metadata.h +++ b/src/metadata.h @@ -17,6 +17,9 @@ */ +#ifndef LIBDCP_METADATA_H +#define LIBDCP_METADATA_H + /** @file src/metadata.h * @brief Metadata for writing to the DCP. */ @@ -26,28 +29,28 @@ namespace libdcp { -/** @brief A class to hold various metadata that will be written - * to the DCP. - * - * The values are initialised, and can be modified if desired. - */ -class Metadata +class MXFMetadata { public: - static Metadata* instance (); + MXFMetadata (); std::string company_name; std::string product_name; std::string product_version; +}; + +class XMLMetadata +{ +public: + XMLMetadata (); + + void set_issue_date_now (); + std::string issuer; std::string creator; std::string issue_date; - -private: - Metadata (); - - /** Singleton instance of Metadata */ - static Metadata* _instance; }; } + +#endif diff --git a/src/mxf_asset.cc b/src/mxf_asset.cc index 144532f8..eb323f59 100644 --- a/src/mxf_asset.cc +++ b/src/mxf_asset.cc @@ -58,11 +58,11 @@ MXFAsset::MXFAsset (string directory, string file_name, boost::signals2::signal< } void -MXFAsset::fill_writer_info (ASDCP::WriterInfo* writer_info, string uuid) +MXFAsset::fill_writer_info (ASDCP::WriterInfo* writer_info, string uuid, MXFMetadata const & metadata) { - writer_info->ProductVersion = Metadata::instance()->product_version; - writer_info->CompanyName = Metadata::instance()->company_name; - writer_info->ProductName = Metadata::instance()->product_name.c_str(); + writer_info->ProductVersion = metadata.product_version; + writer_info->CompanyName = metadata.company_name; + writer_info->ProductName = metadata.product_name.c_str(); writer_info->LabelSetType = ASDCP::LS_MXF_SMPTE; unsigned int c; diff --git a/src/mxf_asset.h b/src/mxf_asset.h index 29b3c1b0..f5cee5de 100644 --- a/src/mxf_asset.h +++ b/src/mxf_asset.h @@ -26,6 +26,8 @@ namespace libdcp { +class MXFMetadata; + /** @brief Parent class for assets which have MXF files */ class MXFAsset : public Asset { @@ -75,10 +77,10 @@ public: * @param w struct to fill in. * @param uuid uuid to use. */ - static void fill_writer_info (ASDCP::WriterInfo* w, std::string uuid); + static void fill_writer_info (ASDCP::WriterInfo* w, std::string uuid, MXFMetadata const & metadata); protected: - + /** Signal to emit to report progress, or 0 */ boost::signals2::signal* _progress; /** The edit rate; this is normally equal to the number of video frames per second */ diff --git a/src/picture_asset.cc b/src/picture_asset.cc index f2982b47..d98ef066 100644 --- a/src/picture_asset.cc +++ b/src/picture_asset.cc @@ -146,10 +146,12 @@ MonoPictureAsset::MonoPictureAsset ( boost::signals2::signal* progress, int fps, int intrinsic_duration, - Size size) + Size size, + MXFMetadata const & metadata + ) : PictureAsset (directory, mxf_name, progress, fps, intrinsic_duration, size) { - construct (get_path); + construct (get_path, metadata); } MonoPictureAsset::MonoPictureAsset ( @@ -159,10 +161,12 @@ MonoPictureAsset::MonoPictureAsset ( boost::signals2::signal* progress, int fps, int intrinsic_duration, - Size size) + Size size, + MXFMetadata const & metadata + ) : PictureAsset (directory, mxf_name, progress, fps, intrinsic_duration, size) { - construct (boost::bind (&MonoPictureAsset::path_from_list, this, _1, files)); + construct (boost::bind (&MonoPictureAsset::path_from_list, this, _1, files), metadata); } MonoPictureAsset::MonoPictureAsset (string directory, string mxf_name, int fps, Size size) @@ -192,7 +196,7 @@ MonoPictureAsset::MonoPictureAsset (string directory, string mxf_name) } void -MonoPictureAsset::construct (boost::function get_path) +MonoPictureAsset::construct (boost::function get_path, MXFMetadata const & metadata) { ASDCP::JP2K::CodestreamParser j2k_parser; ASDCP::JP2K::FrameBuffer frame_buffer (4 * Kumu::Megabyte); @@ -205,7 +209,7 @@ MonoPictureAsset::construct (boost::function get_path) picture_desc.EditRate = ASDCP::Rational (_edit_rate, 1); ASDCP::WriterInfo writer_info; - fill_writer_info (&writer_info, _uuid); + fill_writer_info (&writer_info, _uuid, metadata); ASDCP::JP2K::MXFWriter mxf_writer; if (ASDCP_FAILURE (mxf_writer.OpenWrite (path().string().c_str(), writer_info, picture_desc, 16384, false))) { @@ -402,10 +406,10 @@ StereoPictureAsset::get_frame (int n) const } shared_ptr -MonoPictureAsset::start_write (bool overwrite) +MonoPictureAsset::start_write (bool overwrite, MXFMetadata const & metadata) { - /* XXX: can't we use a shared_ptr here? */ - return shared_ptr (new MonoPictureAssetWriter (this, overwrite)); + /* XXX: can't we use shared_ptr here? */ + return shared_ptr (new MonoPictureAssetWriter (this, overwrite, metadata)); } FrameInfo::FrameInfo (istream& s) @@ -436,13 +440,14 @@ struct MonoPictureAssetWriter::ASDCPState /** @param a Asset to write to. `a' must not be deleted while * this writer class still exists, or bad things will happen. */ -MonoPictureAssetWriter::MonoPictureAssetWriter (MonoPictureAsset* a, bool overwrite) +MonoPictureAssetWriter::MonoPictureAssetWriter (MonoPictureAsset* a, bool overwrite, MXFMetadata const & m) : _state (new MonoPictureAssetWriter::ASDCPState) , _asset (a) , _frames_written (0) , _started (false) , _finalized (false) , _overwrite (overwrite) + , _metadata (m) { } @@ -458,7 +463,7 @@ MonoPictureAssetWriter::start (uint8_t* data, int size) _state->j2k_parser.FillPictureDescriptor (_state->picture_descriptor); _state->picture_descriptor.EditRate = ASDCP::Rational (_asset->edit_rate(), 1); - MXFAsset::fill_writer_info (&_state->writer_info, _asset->uuid()); + MXFAsset::fill_writer_info (&_state->writer_info, _asset->uuid(), _metadata); if (ASDCP_FAILURE (_state->mxf_writer.OpenWrite ( _asset->path().string().c_str(), diff --git a/src/picture_asset.h b/src/picture_asset.h index c9226b1f..59c4dc00 100644 --- a/src/picture_asset.h +++ b/src/picture_asset.h @@ -27,6 +27,7 @@ #include #include "mxf_asset.h" #include "util.h" +#include "metadata.h" namespace libdcp { @@ -121,7 +122,7 @@ public: private: friend class MonoPictureAsset; - MonoPictureAssetWriter (MonoPictureAsset *, bool); + MonoPictureAssetWriter (MonoPictureAsset *, bool, MXFMetadata const &); void start (uint8_t *, int); /* no copy construction */ @@ -142,6 +143,7 @@ private: /** true if finalize() has been called */ bool _finalized; bool _overwrite; + MXFMetadata _metadata; }; /** A 2D (monoscopic) picture asset */ @@ -166,7 +168,8 @@ public: boost::signals2::signal* progress, int fps, int intrinsic_duration, - Size size + Size size, + MXFMetadata const & metadata = MXFMetadata () ); /** Construct a MonoPictureAsset, generating the MXF from the JPEG2000 files. @@ -187,7 +190,8 @@ public: boost::signals2::signal* progress, int fps, int intrinsic_duration, - Size size + Size size, + MXFMetadata const & metadata = MXFMetadata () ); /** Construct a MonoPictureAsset, reading the MXF from disk. @@ -207,14 +211,14 @@ public: MonoPictureAsset (std::string directory, std::string mxf_name, int fps, Size size); /** Start a progressive write to a MonoPictureAsset */ - boost::shared_ptr start_write (bool); + boost::shared_ptr start_write (bool, MXFMetadata const & metadata = MXFMetadata ()); boost::shared_ptr get_frame (int n) const; bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function note) const; private: std::string path_from_list (int f, std::vector const & files) const; - void construct (boost::function); + void construct (boost::function, MXFMetadata const &); }; /** A 3D (stereoscopic) picture asset */ diff --git a/src/sound_asset.cc b/src/sound_asset.cc index 6e29aadf..9b6b48aa 100644 --- a/src/sound_asset.cc +++ b/src/sound_asset.cc @@ -46,7 +46,8 @@ SoundAsset::SoundAsset ( string directory, string mxf_name, boost::signals2::signal* progress, - int fps, int intrinsic_duration + int fps, int intrinsic_duration, + MXFMetadata const & metadata ) : MXFAsset (directory, mxf_name, progress, fps, intrinsic_duration) , _channels (files.size ()) @@ -54,7 +55,7 @@ SoundAsset::SoundAsset ( { assert (_channels); - construct (boost::bind (&SoundAsset::path_from_channel, this, _1, files)); + construct (boost::bind (&SoundAsset::path_from_channel, this, _1, files), metadata); } SoundAsset::SoundAsset ( @@ -62,7 +63,8 @@ SoundAsset::SoundAsset ( string directory, string mxf_name, boost::signals2::signal* progress, - int fps, int intrinsic_duration, int channels + int fps, int intrinsic_duration, int channels, + MXFMetadata const & metadata ) : MXFAsset (directory, mxf_name, progress, fps, intrinsic_duration) , _channels (channels) @@ -70,7 +72,7 @@ SoundAsset::SoundAsset ( { assert (_channels); - construct (get_path); + construct (get_path, metadata); } SoundAsset::SoundAsset (string directory, string mxf_name) @@ -111,7 +113,7 @@ SoundAsset::path_from_channel (Channel channel, vector const & files) } void -SoundAsset::construct (boost::function get_path) +SoundAsset::construct (boost::function get_path, MXFMetadata const & metadata) { ASDCP::Rational asdcp_edit_rate (_edit_rate, 1); @@ -164,7 +166,7 @@ SoundAsset::construct (boost::function get_path) frame_buffer.Size (ASDCP::PCM::CalcFrameBufferSize (audio_desc)); ASDCP::WriterInfo writer_info; - MXFAsset::fill_writer_info (&writer_info, _uuid); + MXFAsset::fill_writer_info (&writer_info, _uuid, metadata); ASDCP::PCM::MXFWriter mxf_writer; if (ASDCP_FAILURE (mxf_writer.OpenWrite (path().string().c_str(), writer_info, audio_desc))) { @@ -303,10 +305,10 @@ SoundAsset::get_frame (int n) const } shared_ptr -SoundAsset::start_write () +SoundAsset::start_write (MXFMetadata const & metadata) { /* XXX: can't we use a shared_ptr here? */ - return shared_ptr (new SoundAssetWriter (this)); + return shared_ptr (new SoundAssetWriter (this, metadata)); } struct SoundAssetWriter::ASDCPState @@ -317,12 +319,13 @@ struct SoundAssetWriter::ASDCPState ASDCP::PCM::AudioDescriptor audio_desc; }; -SoundAssetWriter::SoundAssetWriter (SoundAsset* a) +SoundAssetWriter::SoundAssetWriter (SoundAsset* a, MXFMetadata const & m) : _state (new SoundAssetWriter::ASDCPState) , _asset (a) , _finalized (false) , _frames_written (0) , _frame_buffer_offset (0) + , _metadata (m) { /* Derived from ASDCP::Wav::SimpleWaveHeader::FillADesc */ _state->audio_desc.EditRate = ASDCP::Rational (_asset->edit_rate(), 1); @@ -339,7 +342,7 @@ SoundAssetWriter::SoundAssetWriter (SoundAsset* a) _state->frame_buffer.Size (ASDCP::PCM::CalcFrameBufferSize (_state->audio_desc)); memset (_state->frame_buffer.Data(), 0, _state->frame_buffer.Capacity()); - MXFAsset::fill_writer_info (&_state->writer_info, _asset->uuid ()); + MXFAsset::fill_writer_info (&_state->writer_info, _asset->uuid (), _metadata); if (ASDCP_FAILURE (_state->mxf_writer.OpenWrite (_asset->path().string().c_str(), _state->writer_info, _state->audio_desc))) { boost::throw_exception (FileError ("could not open audio MXF for writing", _asset->path().string())); diff --git a/src/sound_asset.h b/src/sound_asset.h index 9e6e75cf..5c230e06 100644 --- a/src/sound_asset.h +++ b/src/sound_asset.h @@ -26,12 +26,12 @@ #include "mxf_asset.h" #include "types.h" +#include "metadata.h" namespace libdcp { class SoundFrame; - class SoundAsset; class SoundAssetWriter @@ -45,7 +45,7 @@ public: private: friend class SoundAsset; - SoundAssetWriter (SoundAsset *); + SoundAssetWriter (SoundAsset *, MXFMetadata const &); /* no copy construction */ SoundAssetWriter (SoundAssetWriter const &); @@ -64,6 +64,7 @@ private: bool _finalized; int _frames_written; int _frame_buffer_offset; + MXFMetadata _metadata; }; /** @brief An asset made up of WAV files */ @@ -86,7 +87,8 @@ public: std::string mxf_name, boost::signals2::signal* progress, int fps, - int intrinsic_duration + int intrinsic_duration, + MXFMetadata const & metadata = MXFMetadata () ); /** Construct a SoundAsset, generating the MXF from some WAV files. @@ -106,7 +108,8 @@ public: boost::signals2::signal* progress, int fps, int intrinsic_duration, - int channels + int channels, + MXFMetadata const & metadata = MXFMetadata () ); SoundAsset ( @@ -122,7 +125,7 @@ public: int sampling_rate ); - boost::shared_ptr start_write (); + boost::shared_ptr start_write (MXFMetadata const & metadata = MXFMetadata ()); /** Write details of this asset to a CPL stream. * @param s Stream. @@ -142,7 +145,7 @@ public: } private: - void construct (boost::function get_path); + void construct (boost::function get_path, MXFMetadata const &); std::string path_from_channel (Channel channel, std::vector const & files); /** Number of channels in the asset */ diff --git a/src/test_mode.cc b/src/test_mode.cc deleted file mode 100644 index bfe10fee..00000000 --- a/src/test_mode.cc +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright (C) 2012 Carl Hetherington - - 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/test_mode.cc - * @brief A method to enable test mode for libdcp. - */ - -#include "KM_prng.h" -#include "test_mode.h" -#include "metadata.h" - -/** Calling this will seed the random number generator used to - * generate UUIDs with a known value, and set the DCP issue - * date to 1st January 2012 at midnight. This means that - * two runs of libdcp with the same inputs will produce - * the same output. - */ - -void -libdcp::enable_test_mode () -{ - Kumu::libdcp_test = true; - Metadata::instance()->issue_date = "2012-01-01T00:00:00+00:00"; - - /* Remove version strings */ - Metadata::instance()->issuer = "libdcp-test"; - Metadata::instance()->creator = "libdcp-test"; - Metadata::instance()->product_version = "test"; -} diff --git a/src/test_mode.h b/src/test_mode.h deleted file mode 100644 index b2e671d5..00000000 --- a/src/test_mode.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - Copyright (C) 2012 Carl Hetherington - - 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/test_mode.h - * @brief A method to enable test mode for libdcp. - */ - -namespace libdcp -{ - -extern void enable_test_mode (); - -} diff --git a/src/wscript b/src/wscript index 95092173..81c39926 100644 --- a/src/wscript +++ b/src/wscript @@ -27,7 +27,6 @@ def build(bld): sound_asset.cc sound_frame.cc subtitle_asset.cc - test_mode.cc types.cc util.cc version.cc @@ -36,6 +35,7 @@ def build(bld): headers = """ asset.h + cpl.h dcp.h dcp_time.h exceptions.h @@ -48,7 +48,6 @@ def build(bld): sound_asset.h sound_frame.h subtitle_asset.h - test_mode.h types.h util.h version.h diff --git a/test/tests.cc b/test/tests.cc index d33890b6..d8b7e5d4 100644 --- a/test/tests.cc +++ b/test/tests.cc @@ -59,13 +59,14 @@ BOOST_AUTO_TEST_CASE (dcp_test) { Kumu::libdcp_test = true; - libdcp::Metadata* t = libdcp::Metadata::instance (); - t->issuer = "OpenDCP 0.0.25"; - t->creator = "OpenDCP 0.0.25"; - t->company_name = "OpenDCP"; - t->product_name = "OpenDCP"; - t->product_version = "0.0.25"; - t->issue_date = "2012-07-17T04:45:18+00:00"; + libdcp::XMLMetadata xml_meta; + xml_meta.issuer = "OpenDCP 0.0.25"; + xml_meta.creator = "OpenDCP 0.0.25"; + xml_meta.issue_date = "2012-07-17T04:45:18+00:00"; + libdcp::MXFMetadata mxf_meta; + mxf_meta.company_name = "OpenDCP"; + mxf_meta.product_name = "OpenDCP"; + mxf_meta.product_version = "0.0.25"; boost::filesystem::remove_all ("build/test/foo"); boost::filesystem::create_directories ("build/test/foo"); libdcp::DCP d ("build/test/foo"); @@ -78,7 +79,8 @@ BOOST_AUTO_TEST_CASE (dcp_test) &d.Progress, 24, 24, - libdcp::Size (32, 32) + libdcp::Size (32, 32), + mxf_meta )); shared_ptr ms (new libdcp::SoundAsset ( @@ -88,13 +90,14 @@ BOOST_AUTO_TEST_CASE (dcp_test) &(d.Progress), 24, 24, - 2 + 2, + mxf_meta )); cpl->add_reel (shared_ptr (new libdcp::Reel (mp, ms, shared_ptr ()))); d.add_cpl (cpl); - d.write_xml (); + d.write_xml (xml_meta); } BOOST_AUTO_TEST_CASE (error_test) -- cgit v1.2.3 From 7394f50d8b5334a17cac37c8956b1b7e8e5e49c8 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 13 May 2013 14:45:16 +0100 Subject: Try to move XML bits out into parse/ subdir. --- src/asset_map.cc | 78 ------------------------ src/asset_map.h | 77 ----------------------- src/cpl.cc | 14 ++--- src/cpl.h | 7 ++- src/cpl_file.cc | 147 -------------------------------------------- src/cpl_file.h | 157 ----------------------------------------------- src/dcp.cc | 17 +++--- src/dcp.h | 1 - src/parse/asset_map.cc | 78 ++++++++++++++++++++++++ src/parse/asset_map.h | 81 +++++++++++++++++++++++++ src/parse/cpl.cc | 147 ++++++++++++++++++++++++++++++++++++++++++++ src/parse/cpl.h | 161 +++++++++++++++++++++++++++++++++++++++++++++++++ src/parse/pkl.cc | 51 ++++++++++++++++ src/parse/pkl.h | 60 ++++++++++++++++++ src/parse/subtitle.cc | 135 +++++++++++++++++++++++++++++++++++++++++ src/parse/subtitle.h | 93 ++++++++++++++++++++++++++++ src/pkl_file.cc | 51 ---------------- src/pkl_file.h | 56 ----------------- src/subtitle_asset.cc | 125 ++++---------------------------------- src/subtitle_asset.h | 74 +++-------------------- src/wscript | 8 ++- 21 files changed, 849 insertions(+), 769 deletions(-) delete mode 100644 src/asset_map.cc delete mode 100644 src/asset_map.h delete mode 100644 src/cpl_file.cc delete mode 100644 src/cpl_file.h create mode 100644 src/parse/asset_map.cc create mode 100644 src/parse/asset_map.h create mode 100644 src/parse/cpl.cc create mode 100644 src/parse/cpl.h create mode 100644 src/parse/pkl.cc create mode 100644 src/parse/pkl.h create mode 100644 src/parse/subtitle.cc create mode 100644 src/parse/subtitle.h delete mode 100644 src/pkl_file.cc delete mode 100644 src/pkl_file.h (limited to 'src/dcp.cc') diff --git a/src/asset_map.cc b/src/asset_map.cc deleted file mode 100644 index fb42f363..00000000 --- a/src/asset_map.cc +++ /dev/null @@ -1,78 +0,0 @@ -/* - Copyright (C) 2012 Carl Hetherington - - 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/asset_map.cc - * @brief Classes used to parse a AssetMap. - */ - -#include -#include "asset_map.h" -#include "util.h" -#include "xml.h" - -using std::string; -using std::list; -using boost::shared_ptr; -using namespace libdcp; - -AssetMap::AssetMap (string file) -{ - cxml::File f (file, "AssetMap"); - - id = f.string_child ("Id"); - creator = f.string_child ("Creator"); - volume_count = f.number_child ("VolumeCount"); - issue_date = f.string_child ("IssueDate"); - issuer = f.string_child ("Issuer"); - assets = type_grand_children (f, "AssetList", "Asset"); -} - -AssetMapAsset::AssetMapAsset (shared_ptr node) -{ - id = node->string_child ("Id"); - packing_list = node->optional_string_child ("PackingList").get_value_or (""); - chunks = type_grand_children (node, "ChunkList", "Chunk"); -} - -Chunk::Chunk (shared_ptr node) -{ - path = node->string_child ("Path"); - - string const prefix = "file://"; - - if (boost::algorithm::starts_with (path, prefix)) { - path = path.substr (prefix.length()); - } - - volume_index = node->optional_number_child ("VolumeIndex").get_value_or (0); - offset = node->optional_number_child ("Offset").get_value_or (0); - length = node->optional_number_child ("Length").get_value_or (0); -} - -shared_ptr -AssetMap::asset_from_id (string id) const -{ - for (list >::const_iterator i = assets.begin (); i != assets.end(); ++i) { - if ((*i)->id == id) { - return *i; - } - } - - return shared_ptr (); -} diff --git a/src/asset_map.h b/src/asset_map.h deleted file mode 100644 index e7ba6978..00000000 --- a/src/asset_map.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - Copyright (C) 2012 Carl Hetherington - - 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/asset_map.h - * @brief Classes used to parse a AssetMap. - */ - -#include -#include -#include - -namespace libdcp { - -/** @class Chunk - * @brief A simple parser for and representation of a \ node within an asset map. - */ -class Chunk -{ -public: - Chunk (); - Chunk (boost::shared_ptr node); - - std::string path; - int64_t volume_index; - int64_t offset; - int64_t length; -}; - -/** @class AssetMapAsset - * @brief A simple parser for and representation of an \ node within an asset map. - */ -class AssetMapAsset -{ -public: - AssetMapAsset (); - AssetMapAsset (boost::shared_ptr node); - - std::string id; - std::string packing_list; - std::list > chunks; -}; - -/** @class AssetMap - * @brief A simple parser for and representation of an asset map file. - */ -class AssetMap -{ -public: - AssetMap (std::string file); - - boost::shared_ptr asset_from_id (std::string id) const; - - std::string id; - std::string creator; - int64_t volume_count; - std::string issue_date; - std::string issuer; - std::list > assets; -}; - -} diff --git a/src/cpl.cc b/src/cpl.cc index 10a83078..3a2ad0b3 100644 --- a/src/cpl.cc +++ b/src/cpl.cc @@ -19,12 +19,12 @@ #include #include "cpl.h" -#include "cpl_file.h" +#include "parse/cpl.h" #include "util.h" #include "picture_asset.h" #include "sound_asset.h" #include "subtitle_asset.h" -#include "asset_map.h" +#include "parse/asset_map.h" #include "reel.h" #include "metadata.h" @@ -52,16 +52,16 @@ CPL::CPL (string directory, string name, ContentKind content_kind, int length, i * @param asset_map The corresponding asset map. * @param require_mxfs true to throw an exception if a required MXF file does not exist. */ -CPL::CPL (string directory, string file, shared_ptr asset_map, bool require_mxfs) +CPL::CPL (string directory, string file, shared_ptr asset_map, bool require_mxfs) : _directory (directory) , _content_kind (FEATURE) , _length (0) , _fps (0) { /* Read the XML */ - shared_ptr cpl; + shared_ptr cpl; try { - cpl.reset (new CPLFile (file)); + cpl.reset (new parse::CPL (file)); } catch (FileError& e) { boost::throw_exception (FileError ("could not load CPL file", file)); } @@ -71,9 +71,9 @@ CPL::CPL (string directory, string file, shared_ptr asset_map, b _name = cpl->annotation_text; _content_kind = cpl->content_kind; - for (list >::iterator i = cpl->reels.begin(); i != cpl->reels.end(); ++i) { + for (list >::iterator i = cpl->reels.begin(); i != cpl->reels.end(); ++i) { - shared_ptr p; + shared_ptr p; if ((*i)->asset_list->main_picture) { p = (*i)->asset_list->main_picture; diff --git a/src/cpl.h b/src/cpl.h index 0abff749..c04fd6ad 100644 --- a/src/cpl.h +++ b/src/cpl.h @@ -24,7 +24,10 @@ namespace libdcp { -class AssetMap; +namespace parse { + class AssetMap; +} + class Asset; class Reel; class XMLMetadata; @@ -34,7 +37,7 @@ class CPL { public: CPL (std::string directory, std::string name, ContentKind content_kind, int length, int frames_per_second); - CPL (std::string directory, std::string file, boost::shared_ptr asset_map, bool require_mxfs = true); + CPL (std::string directory, std::string file, boost::shared_ptr asset_map, bool require_mxfs = true); void add_reel (boost::shared_ptr reel); diff --git a/src/cpl_file.cc b/src/cpl_file.cc deleted file mode 100644 index 3126b99c..00000000 --- a/src/cpl_file.cc +++ /dev/null @@ -1,147 +0,0 @@ -/* - Copyright (C) 2012 Carl Hetherington - - 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/cpl_file.cc - * @brief Classes used to parse a CPL. - */ - -#include -#include "cpl_file.h" -#include "xml.h" -#include "util.h" - -using std::string; -using std::bad_cast; -using boost::shared_ptr; -using namespace libdcp; - -CPLFile::CPLFile (string file) -{ - cxml::File f (file, "CompositionPlaylist"); - - id = f.string_child ("Id"); - annotation_text = f.optional_string_child ("AnnotationText").get_value_or (""); - issue_date = f.string_child ("IssueDate"); - creator = f.optional_string_child ("Creator").get_value_or (""); - content_title_text = f.string_child ("ContentTitleText"); - content_kind = content_kind_from_string (f.string_child ("ContentKind")); - content_version = optional_type_child (f, "ContentVersion"); - f.ignore_child ("RatingList"); - reels = type_grand_children (f, "ReelList", "Reel"); - - f.ignore_child ("Issuer"); - f.ignore_child ("Signer"); - f.ignore_child ("Signature"); - - f.done (); -} - -ContentVersion::ContentVersion (shared_ptr node) -{ - id = node->optional_string_child ("Id").get_value_or (""); - label_text = node->string_child ("LabelText"); - node->done (); -} - -CPLReel::CPLReel (shared_ptr node) -{ - id = node->string_child ("Id"); - asset_list = type_child (node, "AssetList"); - - node->ignore_child ("AnnotationText"); - node->done (); -} - -CPLAssetList::CPLAssetList (shared_ptr node) -{ - main_picture = optional_type_child (node, "MainPicture"); - main_stereoscopic_picture = optional_type_child (node, "MainStereoscopicPicture"); - main_sound = optional_type_child (node, "MainSound"); - main_subtitle = optional_type_child (node, "MainSubtitle"); - - node->done (); -} - -MainPicture::MainPicture (shared_ptr node) - : Picture (node) -{ - -} - -MainStereoscopicPicture::MainStereoscopicPicture (shared_ptr node) - : Picture (node) -{ - -} - -Picture::Picture (shared_ptr node) -{ - id = node->string_child ("Id"); - annotation_text = node->optional_string_child ("AnnotationText").get_value_or (""); - edit_rate = Fraction (node->string_child ("EditRate")); - intrinsic_duration = node->number_child ("IntrinsicDuration"); - entry_point = node->number_child ("EntryPoint"); - duration = node->number_child ("Duration"); - frame_rate = Fraction (node->string_child ("FrameRate")); - try { - screen_aspect_ratio = Fraction (node->string_child ("ScreenAspectRatio")); - } catch (XMLError& e) { - /* Maybe it's not a fraction */ - } - try { - float f = node->number_child ("ScreenAspectRatio"); - screen_aspect_ratio = Fraction (f * 1000, 1000); - } catch (bad_cast& e) { - - } - - node->ignore_child ("Hash"); - - node->done (); -} - -MainSound::MainSound (shared_ptr node) -{ - id = node->string_child ("Id"); - annotation_text = node->optional_string_child ("AnnotationText").get_value_or (""); - edit_rate = Fraction (node->string_child ("EditRate")); - intrinsic_duration = node->number_child ("IntrinsicDuration"); - entry_point = node->number_child ("EntryPoint"); - duration = node->number_child ("Duration"); - - node->ignore_child ("Hash"); - node->ignore_child ("Language"); - - node->done (); -} - -MainSubtitle::MainSubtitle (shared_ptr node) -{ - id = node->string_child ("Id"); - annotation_text = node->optional_string_child ("AnnotationText").get_value_or (""); - edit_rate = Fraction (node->string_child ("EditRate")); - intrinsic_duration = node->number_child ("IntrinsicDuration"); - entry_point = node->number_child ("EntryPoint"); - duration = node->number_child ("Duration"); - - node->ignore_child ("Hash"); - node->ignore_child ("Language"); - - node->done (); -} diff --git a/src/cpl_file.h b/src/cpl_file.h deleted file mode 100644 index b17f47cd..00000000 --- a/src/cpl_file.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - Copyright (C) 2012 Carl Hetherington - - 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/cpl_file.h - * @brief Classes used to parse a CPL. - */ - -#include -#include -#include -#include "types.h" - -namespace libdcp { - -/** @brief A simple representation of a CPL \ node */ -class Picture -{ -public: - Picture () {} - Picture (boost::shared_ptr node); - - std::string id; - std::string annotation_text; - Fraction edit_rate; - /** Duration of the whole thing */ - int64_t intrinsic_duration; - /** Start point in frames */ - int64_t entry_point; - /** Duration that will actually play */ - int64_t duration; - Fraction frame_rate; - Fraction screen_aspect_ratio; -}; - - -/** @brief A simple parser for and representation of a CPL \ node */ -class MainPicture : public Picture -{ -public: - MainPicture () {} - MainPicture (boost::shared_ptr node); -}; - -/** @brief A simple parser for and representation of a CPL \ node */ -class MainStereoscopicPicture : public Picture -{ -public: - MainStereoscopicPicture () {} - MainStereoscopicPicture (boost::shared_ptr node); -}; - -/** @brief A simple parser for and representation of a CPL \ node */ -class MainSound -{ -public: - MainSound () {} - MainSound (boost::shared_ptr node); - - std::string id; - std::string annotation_text; - Fraction edit_rate; - int64_t intrinsic_duration; - int64_t entry_point; - int64_t duration; -}; - -/** @brief A simple parser for and representation of a CPL \ node */ -class MainSubtitle -{ -public: - MainSubtitle () {} - MainSubtitle (boost::shared_ptr node); - - std::string id; - std::string annotation_text; - Fraction edit_rate; - int64_t intrinsic_duration; - int64_t entry_point; - int64_t duration; -}; - -/** @brief A simple parser for and representation of a CPL \ node */ -class CPLAssetList -{ -public: - CPLAssetList () {} - CPLAssetList (boost::shared_ptr node); - - boost::shared_ptr main_picture; - boost::shared_ptr main_stereoscopic_picture; - boost::shared_ptr main_sound; - boost::shared_ptr main_subtitle; -}; - -/** @brief A simple parser for and representation of a CPL \ node */ -class CPLReel -{ -public: - CPLReel () {} - CPLReel (boost::shared_ptr node); - - std::string id; - boost::shared_ptr asset_list; -}; - - -/** @brief A simple parser for and representation of a CPL \ node */ -class ContentVersion -{ -public: - ContentVersion () {} - ContentVersion (boost::shared_ptr node); - - std::string id; - std::string label_text; -}; - -/** @class CPLFile - * @brief Class to parse a CPL - * - * This class is used to parse XML CPL files. It is rarely necessary - * for the caller to use it outside libdcp. - */ -class CPLFile -{ -public: - /** Parse a CPL XML file into our member variables */ - CPLFile (std::string file); - - std::string id; - std::string annotation_text; - std::string issue_date; - std::string creator; - std::string content_title_text; - ContentKind content_kind; - boost::shared_ptr content_version; - std::list > reels; -}; - -} - diff --git a/src/dcp.cc b/src/dcp.cc index 7af3f353..7a43e9b2 100644 --- a/src/dcp.cc +++ b/src/dcp.cc @@ -37,9 +37,8 @@ #include "util.h" #include "metadata.h" #include "exceptions.h" -#include "cpl_file.h" -#include "pkl_file.h" -#include "asset_map.h" +#include "parse/pkl.h" +#include "parse/asset_map.h" #include "reel.h" #include "cpl.h" @@ -171,17 +170,17 @@ DCP::read (bool require_mxfs) { Files files; - shared_ptr asset_map; + shared_ptr asset_map; try { boost::filesystem::path p = _directory; p /= "ASSETMAP"; if (boost::filesystem::exists (p)) { - asset_map.reset (new AssetMap (p.string ())); + asset_map.reset (new libdcp::parse::AssetMap (p.string ())); } else { p = _directory; p /= "ASSETMAP.xml"; if (boost::filesystem::exists (p)) { - asset_map.reset (new AssetMap (p.string ())); + asset_map.reset (new libdcp::parse::AssetMap (p.string ())); } else { boost::throw_exception (DCPReadError ("could not find AssetMap file")); } @@ -191,7 +190,7 @@ DCP::read (bool require_mxfs) boost::throw_exception (FileError ("could not load AssetMap file", files.asset_map)); } - for (list >::const_iterator i = asset_map->assets.begin(); i != asset_map->assets.end(); ++i) { + for (list >::const_iterator i = asset_map->assets.begin(); i != asset_map->assets.end(); ++i) { if ((*i)->chunks.size() != 1) { boost::throw_exception (XMLError ("unsupported asset chunk count")); } @@ -233,9 +232,9 @@ DCP::read (bool require_mxfs) boost::throw_exception (FileError ("no PKL file found", "")); } - shared_ptr pkl; + shared_ptr pkl; try { - pkl.reset (new PKLFile (files.pkl)); + pkl.reset (new parse::PKL (files.pkl)); } catch (FileError& e) { boost::throw_exception (FileError ("could not load PKL file", files.pkl)); } diff --git a/src/dcp.h b/src/dcp.h index 42c0c6d9..eea043dd 100644 --- a/src/dcp.h +++ b/src/dcp.h @@ -43,7 +43,6 @@ class PictureAsset; class SoundAsset; class SubtitleAsset; class Reel; -class AssetMap; class CPL; class XMLMetadata; diff --git a/src/parse/asset_map.cc b/src/parse/asset_map.cc new file mode 100644 index 00000000..aedc931e --- /dev/null +++ b/src/parse/asset_map.cc @@ -0,0 +1,78 @@ +/* + Copyright (C) 2012 Carl Hetherington + + 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/asset_map.cc + * @brief Classes used to parse a AssetMap. + */ + +#include +#include "asset_map.h" +#include "../util.h" +#include "../xml.h" + +using std::string; +using std::list; +using boost::shared_ptr; +using namespace libdcp::parse; + +AssetMap::AssetMap (string file) +{ + cxml::File f (file, "AssetMap"); + + id = f.string_child ("Id"); + creator = f.string_child ("Creator"); + volume_count = f.number_child ("VolumeCount"); + issue_date = f.string_child ("IssueDate"); + issuer = f.string_child ("Issuer"); + assets = type_grand_children (f, "AssetList", "Asset"); +} + +AssetMapAsset::AssetMapAsset (shared_ptr node) +{ + id = node->string_child ("Id"); + packing_list = node->optional_string_child ("PackingList").get_value_or (""); + chunks = type_grand_children (node, "ChunkList", "Chunk"); +} + +Chunk::Chunk (shared_ptr node) +{ + path = node->string_child ("Path"); + + string const prefix = "file://"; + + if (boost::algorithm::starts_with (path, prefix)) { + path = path.substr (prefix.length()); + } + + volume_index = node->optional_number_child ("VolumeIndex").get_value_or (0); + offset = node->optional_number_child ("Offset").get_value_or (0); + length = node->optional_number_child ("Length").get_value_or (0); +} + +shared_ptr +AssetMap::asset_from_id (string id) const +{ + for (list >::const_iterator i = assets.begin (); i != assets.end(); ++i) { + if ((*i)->id == id) { + return *i; + } + } + + return shared_ptr (); +} diff --git a/src/parse/asset_map.h b/src/parse/asset_map.h new file mode 100644 index 00000000..af3e8918 --- /dev/null +++ b/src/parse/asset_map.h @@ -0,0 +1,81 @@ +/* + Copyright (C) 2012 Carl Hetherington + + 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/asset_map.h + * @brief Classes used to parse a AssetMap. + */ + +#include +#include +#include + +namespace libdcp { + +namespace parse { + +/** @class Chunk + * @brief A simple parser for and representation of a \ node within an asset map. + */ +class Chunk +{ +public: + Chunk (); + Chunk (boost::shared_ptr node); + + std::string path; + int64_t volume_index; + int64_t offset; + int64_t length; +}; + +/** @class AssetMapAsset + * @brief A simple parser for and representation of an \ node within an asset map. + */ +class AssetMapAsset +{ +public: + AssetMapAsset (); + AssetMapAsset (boost::shared_ptr node); + + std::string id; + std::string packing_list; + std::list > chunks; +}; + +/** @class AssetMap + * @brief A simple parser for and representation of an asset map file. + */ +class AssetMap +{ +public: + AssetMap (std::string file); + + boost::shared_ptr asset_from_id (std::string id) const; + + std::string id; + std::string creator; + int64_t volume_count; + std::string issue_date; + std::string issuer; + std::list > assets; +}; + +} + +} diff --git a/src/parse/cpl.cc b/src/parse/cpl.cc new file mode 100644 index 00000000..c4cf4374 --- /dev/null +++ b/src/parse/cpl.cc @@ -0,0 +1,147 @@ +/* + Copyright (C) 2012 Carl Hetherington + + 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/cpl_file.cc + * @brief Classes used to parse a CPL. + */ + +#include +#include "cpl.h" +#include "../xml.h" +#include "../util.h" + +using std::string; +using std::bad_cast; +using boost::shared_ptr; +using namespace libdcp::parse; + +CPL::CPL (string file) +{ + cxml::File f (file, "CompositionPlaylist"); + + id = f.string_child ("Id"); + annotation_text = f.optional_string_child ("AnnotationText").get_value_or (""); + issue_date = f.string_child ("IssueDate"); + creator = f.optional_string_child ("Creator").get_value_or (""); + content_title_text = f.string_child ("ContentTitleText"); + content_kind = content_kind_from_string (f.string_child ("ContentKind")); + content_version = optional_type_child (f, "ContentVersion"); + f.ignore_child ("RatingList"); + reels = type_grand_children (f, "ReelList", "Reel"); + + f.ignore_child ("Issuer"); + f.ignore_child ("Signer"); + f.ignore_child ("Signature"); + + f.done (); +} + +ContentVersion::ContentVersion (shared_ptr node) +{ + id = node->optional_string_child ("Id").get_value_or (""); + label_text = node->string_child ("LabelText"); + node->done (); +} + +Reel::Reel (shared_ptr node) +{ + id = node->string_child ("Id"); + asset_list = type_child (node, "AssetList"); + + node->ignore_child ("AnnotationText"); + node->done (); +} + +CPLAssetList::CPLAssetList (shared_ptr node) +{ + main_picture = optional_type_child (node, "MainPicture"); + main_stereoscopic_picture = optional_type_child (node, "MainStereoscopicPicture"); + main_sound = optional_type_child (node, "MainSound"); + main_subtitle = optional_type_child (node, "MainSubtitle"); + + node->done (); +} + +MainPicture::MainPicture (shared_ptr node) + : Picture (node) +{ + +} + +MainStereoscopicPicture::MainStereoscopicPicture (shared_ptr node) + : Picture (node) +{ + +} + +Picture::Picture (shared_ptr node) +{ + id = node->string_child ("Id"); + annotation_text = node->optional_string_child ("AnnotationText").get_value_or (""); + edit_rate = Fraction (node->string_child ("EditRate")); + intrinsic_duration = node->number_child ("IntrinsicDuration"); + entry_point = node->number_child ("EntryPoint"); + duration = node->number_child ("Duration"); + frame_rate = Fraction (node->string_child ("FrameRate")); + try { + screen_aspect_ratio = Fraction (node->string_child ("ScreenAspectRatio")); + } catch (XMLError& e) { + /* Maybe it's not a fraction */ + } + try { + float f = node->number_child ("ScreenAspectRatio"); + screen_aspect_ratio = Fraction (f * 1000, 1000); + } catch (bad_cast& e) { + + } + + node->ignore_child ("Hash"); + + node->done (); +} + +MainSound::MainSound (shared_ptr node) +{ + id = node->string_child ("Id"); + annotation_text = node->optional_string_child ("AnnotationText").get_value_or (""); + edit_rate = Fraction (node->string_child ("EditRate")); + intrinsic_duration = node->number_child ("IntrinsicDuration"); + entry_point = node->number_child ("EntryPoint"); + duration = node->number_child ("Duration"); + + node->ignore_child ("Hash"); + node->ignore_child ("Language"); + + node->done (); +} + +MainSubtitle::MainSubtitle (shared_ptr node) +{ + id = node->string_child ("Id"); + annotation_text = node->optional_string_child ("AnnotationText").get_value_or (""); + edit_rate = Fraction (node->string_child ("EditRate")); + intrinsic_duration = node->number_child ("IntrinsicDuration"); + entry_point = node->number_child ("EntryPoint"); + duration = node->number_child ("Duration"); + + node->ignore_child ("Hash"); + node->ignore_child ("Language"); + + node->done (); +} diff --git a/src/parse/cpl.h b/src/parse/cpl.h new file mode 100644 index 00000000..434a244b --- /dev/null +++ b/src/parse/cpl.h @@ -0,0 +1,161 @@ +/* + Copyright (C) 2012 Carl Hetherington + + 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/parse/cpl.h + * @brief Classes used to parse a CPL. + */ + +#include +#include +#include +#include "../types.h" + +namespace libdcp { + +namespace parse { + +/** @brief A simple representation of a CPL \ node */ +class Picture +{ +public: + Picture () {} + Picture (boost::shared_ptr node); + + std::string id; + std::string annotation_text; + Fraction edit_rate; + /** Duration of the whole thing */ + int64_t intrinsic_duration; + /** Start point in frames */ + int64_t entry_point; + /** Duration that will actually play */ + int64_t duration; + Fraction frame_rate; + Fraction screen_aspect_ratio; +}; + + +/** @brief A simple parser for and representation of a CPL \ node */ +class MainPicture : public Picture +{ +public: + MainPicture () {} + MainPicture (boost::shared_ptr node); +}; + +/** @brief A simple parser for and representation of a CPL \ node */ +class MainStereoscopicPicture : public Picture +{ +public: + MainStereoscopicPicture () {} + MainStereoscopicPicture (boost::shared_ptr node); +}; + +/** @brief A simple parser for and representation of a CPL \ node */ +class MainSound +{ +public: + MainSound () {} + MainSound (boost::shared_ptr node); + + std::string id; + std::string annotation_text; + Fraction edit_rate; + int64_t intrinsic_duration; + int64_t entry_point; + int64_t duration; +}; + +/** @brief A simple parser for and representation of a CPL \ node */ +class MainSubtitle +{ +public: + MainSubtitle () {} + MainSubtitle (boost::shared_ptr node); + + std::string id; + std::string annotation_text; + Fraction edit_rate; + int64_t intrinsic_duration; + int64_t entry_point; + int64_t duration; +}; + +/** @brief A simple parser for and representation of a CPL \ node */ +class CPLAssetList +{ +public: + CPLAssetList () {} + CPLAssetList (boost::shared_ptr node); + + boost::shared_ptr main_picture; + boost::shared_ptr main_stereoscopic_picture; + boost::shared_ptr main_sound; + boost::shared_ptr main_subtitle; +}; + +/** @brief A simple parser for and representation of a CPL \ node */ +class Reel +{ +public: + Reel () {} + Reel (boost::shared_ptr node); + + std::string id; + boost::shared_ptr asset_list; +}; + + +/** @brief A simple parser for and representation of a CPL \ node */ +class ContentVersion +{ +public: + ContentVersion () {} + ContentVersion (boost::shared_ptr node); + + std::string id; + std::string label_text; +}; + +/** @class CPL + * @brief Class to parse a CPL + * + * This class is used to parse XML CPL files. It is rarely necessary + * for the caller to use it outside libdcp. + */ +class CPL +{ +public: + /** Parse a CPL XML file into our member variables */ + CPL (std::string file); + + std::string id; + std::string annotation_text; + std::string issue_date; + std::string creator; + std::string content_title_text; + ContentKind content_kind; + boost::shared_ptr content_version; + std::list > reels; +}; + +} + +} + diff --git a/src/parse/pkl.cc b/src/parse/pkl.cc new file mode 100644 index 00000000..d790cfe4 --- /dev/null +++ b/src/parse/pkl.cc @@ -0,0 +1,51 @@ +/* + Copyright (C) 2012 Carl Hetherington + + 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/pkl_file.cc + * @brief Classes used to parse a PKL. + */ + +#include +#include "pkl.h" + +using namespace std; +using namespace boost; +using namespace libdcp::parse; + +PKL::PKL (string file) +{ + cxml::File f (file, "PackingList"); + + id = f.string_child ("Id"); + annotation_text = f.optional_string_child ("AnnotationText").get_value_or (""); + issue_date = f.string_child ("IssueDate"); + issuer = f.string_child ("Issuer"); + creator = f.string_child ("Creator"); + assets = type_grand_children (f, "AssetList", "Asset"); +} + +PKLAsset::PKLAsset (boost::shared_ptr node) +{ + id = node->string_child ("Id"); + annotation_text = node->optional_string_child ("AnnotationText").get_value_or (""); + hash = node->string_child ("Hash"); + size = node->number_child ("Size"); + type = node->string_child ("Type"); + original_file_name = node->optional_string_child ("OriginalFileName").get_value_or (""); +} diff --git a/src/parse/pkl.h b/src/parse/pkl.h new file mode 100644 index 00000000..13d87fa1 --- /dev/null +++ b/src/parse/pkl.h @@ -0,0 +1,60 @@ +/* + Copyright (C) 2012 Carl Hetherington + + 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/parse/pkl.h + * @brief Classes used to parse a PKL + */ + +#include +#include "../xml.h" + +namespace libdcp { + +namespace parse { + +class PKLAsset +{ +public: + PKLAsset () {} + PKLAsset (boost::shared_ptr); + + std::string id; + std::string annotation_text; + std::string hash; + int64_t size; + std::string type; + std::string original_file_name; +}; + +class PKL +{ +public: + PKL (std::string file); + + std::string id; + std::string annotation_text; + std::string issue_date; + std::string issuer; + std::string creator; + std::list > assets; +}; + +} + +} diff --git a/src/parse/subtitle.cc b/src/parse/subtitle.cc new file mode 100644 index 00000000..471d62b7 --- /dev/null +++ b/src/parse/subtitle.cc @@ -0,0 +1,135 @@ +/* + Copyright (C) 2012-2013 Carl Hetherington + + 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 +#include +#include "subtitle.h" +#include "../types.h" + +using std::string; +using std::list; +using boost::shared_ptr; +using boost::optional; +using boost::lexical_cast; +using namespace libdcp; +using namespace libdcp::parse; + +Font::Font (shared_ptr node) +{ + text = node->content (); + + id = node->optional_string_attribute ("Id").get_value_or (""); + size = node->optional_number_attribute ("Size").get_value_or (0); + italic = node->optional_bool_attribute ("Italic").get_value_or (false); + optional c = node->optional_string_attribute ("Color"); + if (c) { + color = Color (c.get ()); + } + optional const e = node->optional_string_attribute ("Effect"); + if (e) { + effect = string_to_effect (e.get ()); + } + c = node->optional_string_attribute ( "EffectColor"); + if (c) { + effect_color = Color (c.get ()); + } + subtitle_nodes = type_children (node, "Subtitle"); + font_nodes = type_children (node, "Font"); + text_nodes = type_children (node, "Text"); +} + +Font::Font (list > const & font_nodes) + : size (0) + , italic (false) + , color ("FFFFFFFF") + , effect_color ("FFFFFFFF") +{ + for (list >::const_iterator i = font_nodes.begin(); i != font_nodes.end(); ++i) { + if (!(*i)->id.empty ()) { + id = (*i)->id; + } + if ((*i)->size != 0) { + size = (*i)->size; + } + if ((*i)->italic) { + italic = (*i)->italic.get (); + } + if ((*i)->color) { + color = (*i)->color.get (); + } + if ((*i)->effect) { + effect = (*i)->effect.get (); + } + if ((*i)->effect_color) { + effect_color = (*i)->effect_color.get (); + } + } +} + +LoadFont::LoadFont (shared_ptr node) +{ + id = node->string_attribute ("Id"); + uri = node->string_attribute ("URI"); +} + + +Subtitle::Subtitle (shared_ptr node) +{ + in = Time (node->string_attribute ("TimeIn")); + out = Time (node->string_attribute ("TimeOut")); + font_nodes = type_children (node, "Font"); + text_nodes = type_children (node, "Text"); + fade_up_time = fade_time (node, "FadeUpTime"); + fade_down_time = fade_time (node, "FadeDownTime"); +} + +Time +Subtitle::fade_time (shared_ptr node, string name) +{ + string const u = node->optional_string_attribute (name).get_value_or (""); + Time t; + + if (u.empty ()) { + t = Time (0, 0, 0, 20); + } else if (u.find (":") != string::npos) { + t = Time (u); + } else { + t = Time (0, 0, 0, lexical_cast (u)); + } + + if (t > Time (0, 0, 8, 0)) { + t = Time (0, 0, 8, 0); + } + + return t; +} + +Text::Text (shared_ptr node) + : v_align (CENTER) +{ + text = node->content (); + v_position = node->number_attribute ("VPosition"); + optional v = node->optional_string_attribute ("VAlign"); + if (v) { + v_align = string_to_valign (v.get ()); + } + + font_nodes = type_children (node, "Font"); +} + diff --git a/src/parse/subtitle.h b/src/parse/subtitle.h new file mode 100644 index 00000000..34321545 --- /dev/null +++ b/src/parse/subtitle.h @@ -0,0 +1,93 @@ +/* + Copyright (C) 2012 Carl Hetherington + + 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 "../xml.h" +#include "../dcp_time.h" +#include "../types.h" + +namespace libdcp +{ + +namespace parse +{ + +class Font; + +class Text +{ +public: + Text () {} + Text (boost::shared_ptr node); + + float v_position; + VAlign v_align; + std::string text; + std::list > font_nodes; +}; + +class Subtitle +{ +public: + Subtitle () {} + Subtitle (boost::shared_ptr node); + + Time in; + Time out; + Time fade_up_time; + Time fade_down_time; + std::list > font_nodes; + std::list > text_nodes; + +private: + Time fade_time (boost::shared_ptr, std::string name); +}; + +class Font +{ +public: + Font () {} + Font (boost::shared_ptr node); + Font (std::list > const & font_nodes); + + std::string text; + std::string id; + int size; + boost::optional italic; + boost::optional color; + boost::optional effect; + boost::optional effect_color; + + std::list > subtitle_nodes; + std::list > font_nodes; + std::list > text_nodes; +}; + +class LoadFont +{ +public: + LoadFont () {} + LoadFont (boost::shared_ptr node); + + std::string id; + std::string uri; +}; + +} + +} diff --git a/src/pkl_file.cc b/src/pkl_file.cc deleted file mode 100644 index 9119d883..00000000 --- a/src/pkl_file.cc +++ /dev/null @@ -1,51 +0,0 @@ -/* - Copyright (C) 2012 Carl Hetherington - - 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/pkl_file.cc - * @brief Classes used to parse a PKL. - */ - -#include -#include "pkl_file.h" - -using namespace std; -using namespace boost; -using namespace libdcp; - -PKLFile::PKLFile (string file) -{ - cxml::File f (file, "PackingList"); - - id = f.string_child ("Id"); - annotation_text = f.optional_string_child ("AnnotationText").get_value_or (""); - issue_date = f.string_child ("IssueDate"); - issuer = f.string_child ("Issuer"); - creator = f.string_child ("Creator"); - assets = type_grand_children (f, "AssetList", "Asset"); -} - -PKLAsset::PKLAsset (boost::shared_ptr node) -{ - id = node->string_child ("Id"); - annotation_text = node->optional_string_child ("AnnotationText").get_value_or (""); - hash = node->string_child ("Hash"); - size = node->number_child ("Size"); - type = node->string_child ("Type"); - original_file_name = node->optional_string_child ("OriginalFileName").get_value_or (""); -} diff --git a/src/pkl_file.h b/src/pkl_file.h deleted file mode 100644 index 77b83fca..00000000 --- a/src/pkl_file.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - Copyright (C) 2012 Carl Hetherington - - 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/pkl_file.h - * @brief Classes used to parse a PKL - */ - -#include -#include "xml.h" - -namespace libdcp { - -class PKLAsset -{ -public: - PKLAsset () {} - PKLAsset (boost::shared_ptr); - - std::string id; - std::string annotation_text; - std::string hash; - int64_t size; - std::string type; - std::string original_file_name; -}; - -class PKLFile -{ -public: - PKLFile (std::string file); - - std::string id; - std::string annotation_text; - std::string issue_date; - std::string issuer; - std::string creator; - std::list > assets; -}; - -} diff --git a/src/subtitle_asset.cc b/src/subtitle_asset.cc index 1eae1fcc..d89d52de 100644 --- a/src/subtitle_asset.cc +++ b/src/subtitle_asset.cc @@ -63,8 +63,8 @@ SubtitleAsset::read_xml (string xml_file) xml->ignore_child ("LoadFont"); - list > font_nodes = type_children (xml, "Font"); - _load_font_nodes = type_children (xml, "LoadFont"); + list > font_nodes = type_children (xml, "Font"); + _load_font_nodes = type_children (xml, "LoadFont"); /* Now make Subtitle objects to represent the raw XML nodes in a sane way. @@ -77,16 +77,16 @@ SubtitleAsset::read_xml (string xml_file) void SubtitleAsset::examine_font_nodes ( shared_ptr xml, - list > const & font_nodes, + list > const & font_nodes, ParseState& parse_state ) { - for (list >::const_iterator i = font_nodes.begin(); i != font_nodes.end(); ++i) { + for (list >::const_iterator i = font_nodes.begin(); i != font_nodes.end(); ++i) { parse_state.font_nodes.push_back (*i); maybe_add_subtitle ((*i)->text, parse_state); - for (list >::iterator j = (*i)->subtitle_nodes.begin(); j != (*i)->subtitle_nodes.end(); ++j) { + for (list >::iterator j = (*i)->subtitle_nodes.begin(); j != (*i)->subtitle_nodes.end(); ++j) { parse_state.subtitle_nodes.push_back (*j); examine_text_nodes (xml, (*j)->text_nodes, parse_state); examine_font_nodes (xml, (*j)->font_nodes, parse_state); @@ -103,11 +103,11 @@ SubtitleAsset::examine_font_nodes ( void SubtitleAsset::examine_text_nodes ( shared_ptr xml, - list > const & text_nodes, + list > const & text_nodes, ParseState& parse_state ) { - for (list >::const_iterator i = text_nodes.begin(); i != text_nodes.end(); ++i) { + for (list >::const_iterator i = text_nodes.begin(); i != text_nodes.end(); ++i) { parse_state.text_nodes.push_back (*i); maybe_add_subtitle ((*i)->text, parse_state); examine_font_nodes (xml, (*i)->font_nodes, parse_state); @@ -129,9 +129,9 @@ SubtitleAsset::maybe_add_subtitle (string text, ParseState const & parse_state) assert (!parse_state.text_nodes.empty ()); assert (!parse_state.subtitle_nodes.empty ()); - FontNode effective_font (parse_state.font_nodes); - TextNode effective_text (*parse_state.text_nodes.back ()); - SubtitleNode effective_subtitle (*parse_state.subtitle_nodes.back ()); + libdcp::parse::Font effective_font (parse_state.font_nodes); + libdcp::parse::Text effective_text (*parse_state.text_nodes.back ()); + libdcp::parse::Subtitle effective_subtitle (*parse_state.subtitle_nodes.back ()); _subtitles.push_back ( shared_ptr ( @@ -154,109 +154,6 @@ SubtitleAsset::maybe_add_subtitle (string text, ParseState const & parse_state) ); } -FontNode::FontNode (shared_ptr node) -{ - text = node->content (); - - id = node->optional_string_attribute ("Id").get_value_or (""); - size = node->optional_number_attribute ("Size").get_value_or (0); - italic = node->optional_bool_attribute ("Italic").get_value_or (false); - optional c = node->optional_string_attribute ("Color"); - if (c) { - color = Color (c.get ()); - } - optional const e = node->optional_string_attribute ("Effect"); - if (e) { - effect = string_to_effect (e.get ()); - } - c = node->optional_string_attribute ( "EffectColor"); - if (c) { - effect_color = Color (c.get ()); - } - subtitle_nodes = type_children (node, "Subtitle"); - font_nodes = type_children (node, "Font"); - text_nodes = type_children (node, "Text"); -} - -FontNode::FontNode (list > const & font_nodes) - : size (0) - , italic (false) - , color ("FFFFFFFF") - , effect_color ("FFFFFFFF") -{ - for (list >::const_iterator i = font_nodes.begin(); i != font_nodes.end(); ++i) { - if (!(*i)->id.empty ()) { - id = (*i)->id; - } - if ((*i)->size != 0) { - size = (*i)->size; - } - if ((*i)->italic) { - italic = (*i)->italic.get (); - } - if ((*i)->color) { - color = (*i)->color.get (); - } - if ((*i)->effect) { - effect = (*i)->effect.get (); - } - if ((*i)->effect_color) { - effect_color = (*i)->effect_color.get (); - } - } -} - -LoadFontNode::LoadFontNode (shared_ptr node) -{ - id = node->string_attribute ("Id"); - uri = node->string_attribute ("URI"); -} - - -SubtitleNode::SubtitleNode (shared_ptr node) -{ - in = Time (node->string_attribute ("TimeIn")); - out = Time (node->string_attribute ("TimeOut")); - font_nodes = type_children (node, "Font"); - text_nodes = type_children (node, "Text"); - fade_up_time = fade_time (node, "FadeUpTime"); - fade_down_time = fade_time (node, "FadeDownTime"); -} - -Time -SubtitleNode::fade_time (shared_ptr node, string name) -{ - string const u = node->optional_string_attribute (name).get_value_or (""); - Time t; - - if (u.empty ()) { - t = Time (0, 0, 0, 20); - } else if (u.find (":") != string::npos) { - t = Time (u); - } else { - t = Time (0, 0, 0, lexical_cast (u)); - } - - if (t > Time (0, 0, 8, 0)) { - t = Time (0, 0, 8, 0); - } - - return t; -} - -TextNode::TextNode (shared_ptr node) - : v_align (CENTER) -{ - text = node->content (); - v_position = node->number_attribute ("VPosition"); - optional v = node->optional_string_attribute ("VAlign"); - if (v) { - v_align = string_to_valign (v.get ()); - } - - font_nodes = type_children (node, "Font"); -} - list > SubtitleAsset::subtitles_at (Time t) const { @@ -273,7 +170,7 @@ SubtitleAsset::subtitles_at (Time t) const std::string SubtitleAsset::font_id_to_name (string id) const { - list >::const_iterator i = _load_font_nodes.begin(); + list >::const_iterator i = _load_font_nodes.begin(); while (i != _load_font_nodes.end() && (*i)->id != id) { ++i; } diff --git a/src/subtitle_asset.h b/src/subtitle_asset.h index 591985d1..0d662d6c 100644 --- a/src/subtitle_asset.h +++ b/src/subtitle_asset.h @@ -20,71 +20,11 @@ #include "asset.h" #include "xml.h" #include "dcp_time.h" +#include "parse/subtitle.h" namespace libdcp { -class FontNode; - -class TextNode -{ -public: - TextNode () {} - TextNode (boost::shared_ptr node); - - float v_position; - VAlign v_align; - std::string text; - std::list > font_nodes; -}; - -class SubtitleNode -{ -public: - SubtitleNode () {} - SubtitleNode (boost::shared_ptr node); - - Time in; - Time out; - Time fade_up_time; - Time fade_down_time; - std::list > font_nodes; - std::list > text_nodes; - -private: - Time fade_time (boost::shared_ptr, std::string name); -}; - -class FontNode -{ -public: - FontNode () {} - FontNode (boost::shared_ptr node); - FontNode (std::list > const & font_nodes); - - std::string text; - std::string id; - int size; - boost::optional italic; - boost::optional color; - boost::optional effect; - boost::optional effect_color; - - std::list > subtitle_nodes; - std::list > font_nodes; - std::list > text_nodes; -}; - -class LoadFontNode -{ -public: - LoadFontNode () {} - LoadFontNode (boost::shared_ptr node); - - std::string id; - std::string uri; -}; - class Subtitle { public: @@ -210,22 +150,22 @@ private: std::string escape (std::string) const; struct ParseState { - std::list > font_nodes; - std::list > text_nodes; - std::list > subtitle_nodes; + std::list > font_nodes; + std::list > text_nodes; + std::list > subtitle_nodes; }; void maybe_add_subtitle (std::string text, ParseState const & parse_state); void examine_font_nodes ( boost::shared_ptr xml, - std::list > const & font_nodes, + std::list > const & font_nodes, ParseState& parse_state ); void examine_text_nodes ( boost::shared_ptr xml, - std::list > const & text_nodes, + std::list > const & text_nodes, ParseState& parse_state ); @@ -233,7 +173,7 @@ private: /* strangely, this is sometimes a string */ std::string _reel_number; std::string _language; - std::list > _load_font_nodes; + std::list > _load_font_nodes; std::list > _subtitles; bool _need_sort; diff --git a/src/wscript b/src/wscript index fb8f688e..37151e51 100644 --- a/src/wscript +++ b/src/wscript @@ -11,8 +11,6 @@ def build(bld): obj.use = 'libkumu-libdcp libasdcp-libdcp' obj.source = """ asset.cc - asset_map.cc - cpl_file.cc dcp.cc cpl.cc dcp_time.cc @@ -21,7 +19,6 @@ def build(bld): mxf_asset.cc picture_asset.cc picture_frame.cc - pkl_file.cc reel.cc argb_frame.cc sound_asset.cc @@ -30,6 +27,10 @@ def build(bld): types.cc util.cc version.cc + parse/asset_map.cc + parse/cpl.cc + parse/pkl.cc + parse/subtitle.cc """ headers = """ @@ -55,3 +56,4 @@ def build(bld): bld.install_files('${PREFIX}/include/libdcp', headers) if bld.env.STATIC: bld.install_files('${PREFIX}/lib', 'libdcp.a') + -- cgit v1.2.3 From 8526058d24faec5f83ffd66758fef8d8c8159f73 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 13 May 2013 15:57:00 +0100 Subject: Use libxml++ for writing XML. --- src/asset.cc | 37 +++++++-------- src/asset.h | 7 +-- src/cpl.cc | 75 +++++++++++++++---------------- src/cpl.h | 5 ++- src/dcp.cc | 92 ++++++++++++++++++-------------------- src/picture_asset.cc | 21 +++++---- src/picture_asset.h | 6 +-- src/reel.cc | 17 +++---- src/reel.h | 3 +- src/sound_asset.cc | 17 ++++--- src/sound_asset.h | 6 +-- src/subtitle_asset.cc | 121 ++++++++++++++++++++++---------------------------- src/subtitle_asset.h | 5 +-- 13 files changed, 192 insertions(+), 220 deletions(-) (limited to 'src/dcp.cc') diff --git a/src/asset.cc b/src/asset.cc index 58c821a7..84bdd2bd 100644 --- a/src/asset.cc +++ b/src/asset.cc @@ -25,6 +25,7 @@ #include #include #include +#include #include "AS_DCP.h" #include "KM_util.h" #include "asset.h" @@ -50,31 +51,27 @@ Asset::Asset (string directory, string file_name, int edit_rate, int intrinsic_d } void -Asset::write_to_pkl (ostream& s) const +Asset::write_to_pkl (xmlpp::Node* node) const { - s << " \n" - << " urn:uuid:" << _uuid << "\n" - << " " << _file_name << "\n" - << " " << digest() << "\n" - << " " << filesystem::file_size(path()) << "\n" - << " application/mxf\n" - << " \n"; + xmlpp::Node* asset = node->add_child ("Asset"); + asset->add_child("Id")->add_child_text ("urn:uuid:" + _uuid); + asset->add_child("AnnotationText")->add_child_text (_file_name); + asset->add_child("Hash")->add_child_text (digest ()); + asset->add_child("Size")->add_child_text (lexical_cast (filesystem::file_size(path()))); + asset->add_child("Type")->add_child_text ("application/mxf"); } void -Asset::write_to_assetmap (ostream& s) const +Asset::write_to_assetmap (xmlpp::Node* node) const { - s << " \n" - << " urn:uuid:" << _uuid << "\n" - << " \n" - << " \n" - << " " << _file_name << "\n" - << " 1\n" - << " 0\n" - << " " << filesystem::file_size(path()) << "\n" - << " \n" - << " \n" - << " \n"; + xmlpp::Node* asset = node->add_child ("Asset"); + asset->add_child("Id")->add_child_text ("urn:uuid:" + _uuid); + xmlpp::Node* chunk_list = asset->add_child ("ChunkList"); + xmlpp::Node* chunk = chunk_list->add_child ("Chunk"); + chunk->add_child("Path")->add_child_text (_file_name); + chunk->add_child("VolumeIndex")->add_child_text ("1"); + chunk->add_child("Offset")->add_child_text ("0"); + chunk->add_child("Length")->add_child_text (lexical_cast (filesystem::file_size(path()))); } filesystem::path diff --git a/src/asset.h b/src/asset.h index 06c66356..3bc713a3 100644 --- a/src/asset.h +++ b/src/asset.h @@ -28,6 +28,7 @@ #include #include #include +#include #include "types.h" namespace ASDCP { @@ -55,17 +56,17 @@ public: /** Write details of the asset to a CPL stream. * @param s Stream. */ - virtual void write_to_cpl (std::ostream& s) const = 0; + virtual void write_to_cpl (xmlpp::Node *) const = 0; /** Write details of the asset to a PKL stream. * @param s Stream. */ - void write_to_pkl (std::ostream& s) const; + void write_to_pkl (xmlpp::Node *) const; /** Write details of the asset to a ASSETMAP stream. * @param s Stream. */ - void write_to_assetmap (std::ostream& s) const; + void write_to_assetmap (xmlpp::Node *) const; std::string uuid () const { return _uuid; diff --git a/src/cpl.cc b/src/cpl.cc index 3a2ad0b3..e7eb1ced 100644 --- a/src/cpl.cc +++ b/src/cpl.cc @@ -34,6 +34,7 @@ using std::ofstream; using std::ostream; using std::list; using boost::shared_ptr; +using boost::lexical_cast; using namespace libdcp; CPL::CPL (string directory, string name, ContentKind content_kind, int length, int frames_per_second) @@ -180,45 +181,42 @@ CPL::write_xml (XMLMetadata const & metadata) const stringstream s; s << _uuid << "_cpl.xml"; p /= s.str(); - ofstream os (p.string().c_str()); - - os << "\n" - << "\n" - << " urn:uuid:" << _uuid << "\n" - << " " << _name << "\n" - << " " << metadata.issue_date << "\n" - << " " << metadata.creator << "\n" - << " " << _name << "\n" - << " " << content_kind_to_string (_content_kind) << "\n" - << " \n" - << " urn:uri:" << _uuid << "_" << metadata.issue_date << "\n" - << " " << _uuid << "_" << metadata.issue_date << "\n" - << " \n" - << " \n" - << " \n"; + + xmlpp::Document doc; + xmlpp::Element* root = doc.create_root_node ("CompositionPlaylist", "http://www.smpte-ra.org/schemas/429-7/2006/CPL"); + root->add_child("Id")->add_child_text ("urn:uuid:" + _uuid); + root->add_child("AnnotationText")->add_child_text (_name); + root->add_child("IssueDate")->add_child_text (metadata.issue_date); + root->add_child("Creator")->add_child_text (metadata.creator); + root->add_child("ContentTitleText")->add_child_text (_name); + root->add_child("ContentKind")->add_child_text (content_kind_to_string (_content_kind)); + { + xmlpp::Node* cv = root->add_child ("ContentVersion"); + cv->add_child ("Id")->add_child_text ("urn:uri:" + _uuid + "_" + metadata.issue_date); + cv->add_child ("LabelText")->add_child_text (_uuid + "_" + metadata.issue_date); + } + root->add_child("RatingList"); + + xmlpp::Node* reel_list = root->add_child ("ReelList"); for (list >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) { - (*i)->write_to_cpl (os); + (*i)->write_to_cpl (reel_list); } - os << " \n" - << "\n"; - - os.close (); + doc.write_to_file_formatted (p.string (), "UTF-8"); _digest = make_digest (p.string ()); _length = boost::filesystem::file_size (p.string ()); } void -CPL::write_to_pkl (ostream& s) const +CPL::write_to_pkl (xmlpp::Node* node) const { - s << " \n" - << " urn:uuid:" << _uuid << "\n" - << " " << _digest << "\n" - << " " << _length << "\n" - << " text/xml\n" - << " \n"; + xmlpp::Node* asset = node->add_child ("Asset"); + asset->add_child("Id")->add_child_text ("urn:uuid:" + _uuid); + asset->add_child("Hash")->add_child_text (_digest); + asset->add_child("Size")->add_child_text (lexical_cast (_length)); + asset->add_child("Type")->add_child_text ("text/xml"); } list > @@ -241,19 +239,16 @@ CPL::assets () const } void -CPL::write_to_assetmap (ostream& s) const +CPL::write_to_assetmap (xmlpp::Node* node) const { - s << " \n" - << " urn:uuid:" << _uuid << "\n" - << " \n" - << " \n" - << " " << _uuid << "_cpl.xml\n" - << " 1\n" - << " 0\n" - << " " << _length << "\n" - << " \n" - << " \n" - << " \n"; + xmlpp::Node* asset = node->add_child ("Asset"); + asset->add_child("Id")->add_child_text ("urn:uuid:" + _uuid); + xmlpp::Node* chunk_list = asset->add_child ("ChunkList"); + xmlpp::Node* chunk = chunk_list->add_child ("Chunk"); + chunk->add_child("Path")->add_child_text (_uuid + "_cpl.xml"); + chunk->add_child("VolumeIndex")->add_child_text ("1"); + chunk->add_child("Offset")->add_child_text("0"); + chunk->add_child("Length")->add_child_text(lexical_cast (_length)); } diff --git a/src/cpl.h b/src/cpl.h index c04fd6ad..0c86b91e 100644 --- a/src/cpl.h +++ b/src/cpl.h @@ -20,6 +20,7 @@ #include #include #include +#include #include "types.h" namespace libdcp { @@ -74,8 +75,8 @@ public: bool equals (CPL const & other, EqualityOptions options, boost::function note) const; void write_xml (XMLMetadata const &) const; - void write_to_assetmap (std::ostream& s) const; - void write_to_pkl (std::ostream& s) const; + void write_to_assetmap (xmlpp::Node *) const; + void write_to_pkl (xmlpp::Node *) const; private: std::string _directory; diff --git a/src/dcp.cc b/src/dcp.cc index 7a43e9b2..c7634b5d 100644 --- a/src/dcp.cc +++ b/src/dcp.cc @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "dcp.h" #include "asset.h" @@ -48,6 +49,7 @@ using std::stringstream; using std::ofstream; using std::ostream; using boost::shared_ptr; +using boost::lexical_cast; using namespace libdcp; DCP::DCP (string directory) @@ -80,30 +82,29 @@ DCP::write_pkl (string pkl_uuid, XMLMetadata const & metadata) const stringstream s; s << pkl_uuid << "_pkl.xml"; p /= s.str(); - ofstream pkl (p.string().c_str()); - - pkl << "\n" - << "\n" - << " urn:uuid:" << pkl_uuid << "\n" - /* XXX: this is a bit of a hack */ - << " " << _cpls.front()->name() << "\n" - << " " << metadata.issue_date << "\n" - << " " << metadata.issuer << "\n" - << " " << metadata.creator << "\n" - << " \n"; + + xmlpp::Document doc; + xmlpp::Element* root = doc.create_root_node ("PackingList", "http://www.smpte-ra.org/schemas/429-8/2007/PKL"); + + root->add_child("Id")->add_child_text ("urn:uuid:" + pkl_uuid); + /* XXX: this is a bit of a hack */ + root->add_child("AnnotationText")->add_child_text (_cpls.front()->name()); + root->add_child("IssueDate")->add_child_text (metadata.issue_date); + root->add_child("Issuer")->add_child_text (metadata.issuer); + root->add_child("Creator")->add_child_text (metadata.creator); + + xmlpp::Node* asset_list = root->add_child ("AssetList"); list > a = assets (); for (list >::const_iterator i = a.begin(); i != a.end(); ++i) { - (*i)->write_to_pkl (pkl); + (*i)->write_to_pkl (asset_list); } for (list >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) { - (*i)->write_to_pkl (pkl); + (*i)->write_to_pkl (asset_list); } - pkl << " \n" - << "\n"; - + doc.write_to_file_formatted (p.string (), "UTF-8"); return p.string (); } @@ -113,12 +114,11 @@ DCP::write_volindex () const boost::filesystem::path p; p /= _directory; p /= "VOLINDEX.xml"; - ofstream vi (p.string().c_str()); - vi << "\n" - << "\n" - << " 1\n" - << "\n"; + xmlpp::Document doc; + xmlpp::Element* root = doc.create_root_node ("VolumeIndex", "http://www.smpte-ra.org/schemas/429-9/2007/AM"); + root->add_child("Index")->add_child_text ("1"); + doc.write_to_file_formatted (p.string (), "UTF-8"); } void @@ -127,41 +127,37 @@ DCP::write_assetmap (string pkl_uuid, int pkl_length, XMLMetadata const & metada boost::filesystem::path p; p /= _directory; p /= "ASSETMAP.xml"; - ofstream am (p.string().c_str()); - - am << "\n" - << "\n" - << " urn:uuid:" << make_uuid() << "\n" - << " " << metadata.creator << "\n" - << " 1\n" - << " " << metadata.issue_date << "\n" - << " " << metadata.issuer << "\n" - << " \n"; - - am << " \n" - << " urn:uuid:" << pkl_uuid << "\n" - << " true\n" - << " \n" - << " \n" - << " " << pkl_uuid << "_pkl.xml\n" - << " 1\n" - << " 0\n" - << " " << pkl_length << "\n" - << " \n" - << " \n" - << " \n"; + + xmlpp::Document doc; + xmlpp::Element* root = doc.create_root_node ("AssetMap", "http://www.smpte-ra.org/schemas/429-9/2007/AM"); + + root->add_child("Id")->add_child_text ("urn:uuid:" + make_uuid()); + root->add_child("Creator")->add_child_text (metadata.creator); + root->add_child("VolumeCount")->add_child_text ("1"); + root->add_child("IssueDate")->add_child_text (metadata.issue_date); + root->add_child("Issuer")->add_child_text (metadata.issuer); + xmlpp::Node* asset_list = root->add_child ("AssetList"); + + xmlpp::Node* asset = asset_list->add_child ("Asset"); + asset->add_child("Id")->add_child_text ("urn:uuid:" + pkl_uuid); + asset->add_child("PackingList")->add_child_text ("true"); + xmlpp::Node* chunk_list = asset->add_child ("ChunkList"); + xmlpp::Node* chunk = chunk_list->add_child ("Chunk"); + chunk->add_child("Path")->add_child_text (pkl_uuid + "_pkl.xml"); + chunk->add_child("VolumeIndex")->add_child_text ("1"); + chunk->add_child("Offset")->add_child_text ("0"); + chunk->add_child("Length")->add_child_text (lexical_cast (pkl_length)); for (list >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) { - (*i)->write_to_assetmap (am); + (*i)->write_to_assetmap (asset_list); } list > a = assets (); for (list >::const_iterator i = a.begin(); i != a.end(); ++i) { - (*i)->write_to_assetmap (am); + (*i)->write_to_assetmap (asset_list); } - am << " \n" - << "\n"; + doc.write_to_file_formatted (p.string (), "UTF-8"); } diff --git a/src/picture_asset.cc b/src/picture_asset.cc index 788e3dc4..72a63173 100644 --- a/src/picture_asset.cc +++ b/src/picture_asset.cc @@ -64,18 +64,17 @@ PictureAsset::PictureAsset (string directory, string mxf_name) } void -PictureAsset::write_to_cpl (ostream& s) const +PictureAsset::write_to_cpl (xmlpp::Node* node) const { - s << " \n" - << " urn:uuid:" << _uuid << "\n" - << " " << _file_name << "\n" - << " " << _edit_rate << " 1\n" - << " " << _intrinsic_duration << "\n" - << " " << _entry_point << "\n" - << " " << _duration << "\n" - << " " << _edit_rate << " 1\n" - << " " << _size.width << " " << _size.height << "\n" - << " \n"; + xmlpp::Node* mp = node->add_child ("MainPicture"); + mp->add_child ("Id")->add_child_text ("urn:uuid:" + _uuid); + mp->add_child ("AnnotationText")->add_child_text (_file_name); + mp->add_child ("EditRate")->add_child_text (lexical_cast (_edit_rate) + " 1"); + mp->add_child ("IntrinsicDuration")->add_child_text (lexical_cast (_intrinsic_duration)); + mp->add_child ("EntryPoint")->add_child_text (lexical_cast (_entry_point)); + mp->add_child ("Duration")->add_child_text (lexical_cast (_duration)); + mp->add_child ("FrameRate")->add_child_text (lexical_cast (_edit_rate) + " 1"); + mp->add_child ("ScreenAspectRatio")->add_child_text (lexical_cast (_size.width) + " " + lexical_cast (_size.height)); } bool diff --git a/src/picture_asset.h b/src/picture_asset.h index 59c4dc00..3edf3a1c 100644 --- a/src/picture_asset.h +++ b/src/picture_asset.h @@ -59,10 +59,10 @@ public: */ PictureAsset (std::string directory, std::string mxf_name, boost::signals2::signal* progress, int fps, int intrinsic_duration, Size size); - /** Write details of this asset to a CPL stream. - * @param s Stream. + /** Write details of this asset to a CPL XML node. + * @param node Node. */ - void write_to_cpl (std::ostream& s) const; + void write_to_cpl (xmlpp::Node* node) const; bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function note) const; diff --git a/src/reel.cc b/src/reel.cc index 86533ea2..481b153b 100644 --- a/src/reel.cc +++ b/src/reel.cc @@ -27,26 +27,23 @@ using namespace std; using namespace libdcp; void -Reel::write_to_cpl (ostream& s) const +Reel::write_to_cpl (xmlpp::Node* node) const { - s << " \n" - << " urn:uuid:" << make_uuid() << "\n" - << " \n"; + xmlpp::Node* reel = node->add_child ("Reel"); + reel->add_child("Id")->add_child_text ("urn:uuid:" + make_uuid()); + xmlpp::Node* asset_list = reel->add_child ("AssetList"); if (_main_picture) { - _main_picture->write_to_cpl (s); + _main_picture->write_to_cpl (asset_list); } if (_main_sound) { - _main_sound->write_to_cpl (s); + _main_sound->write_to_cpl (asset_list); } if (_main_subtitle) { - _main_subtitle->write_to_cpl (s); + _main_subtitle->write_to_cpl (asset_list); } - - s << " \n" - << " \n"; } bool diff --git a/src/reel.h b/src/reel.h index 93dc0920..49a756ad 100644 --- a/src/reel.h +++ b/src/reel.h @@ -20,6 +20,7 @@ #include #include #include +#include #include "types.h" namespace libdcp { @@ -54,7 +55,7 @@ public: return _main_subtitle; } - void write_to_cpl (std::ostream & s) const; + void write_to_cpl (xmlpp::Node *) const; bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function notes) const; diff --git a/src/sound_asset.cc b/src/sound_asset.cc index 9b6b48aa..4a7abd4d 100644 --- a/src/sound_asset.cc +++ b/src/sound_asset.cc @@ -211,16 +211,15 @@ SoundAsset::construct (boost::function get_path, MXFMetadata c } void -SoundAsset::write_to_cpl (ostream& s) const +SoundAsset::write_to_cpl (xmlpp::Node* node) const { - s << " \n" - << " urn:uuid:" << _uuid << "\n" - << " " << _file_name << "\n" - << " " << _edit_rate << " 1\n" - << " " << _intrinsic_duration << "\n" - << " " << _entry_point << "\n" - << " " << _duration << "\n" - << " \n"; + xmlpp::Node* ms = node->add_child ("MainSound"); + ms->add_child ("Id")->add_child_text ("urn:uuid:" + _uuid); + ms->add_child ("AnnotationText")->add_child_text (_file_name); + ms->add_child ("EditRate")->add_child_text (lexical_cast (_edit_rate) + " 1"); + ms->add_child ("IntrinsicDuration")->add_child_text (lexical_cast (_intrinsic_duration)); + ms->add_child ("EntryPoint")->add_child_text (lexical_cast (_entry_point)); + ms->add_child ("Duration")->add_child_text (lexical_cast (_duration)); } bool diff --git a/src/sound_asset.h b/src/sound_asset.h index 5c230e06..1e3553a0 100644 --- a/src/sound_asset.h +++ b/src/sound_asset.h @@ -127,10 +127,10 @@ public: boost::shared_ptr start_write (MXFMetadata const & metadata = MXFMetadata ()); - /** Write details of this asset to a CPL stream. - * @param s Stream. + /** Write details of this asset to a CPL XML node. + * @param node Node. */ - void write_to_cpl (std::ostream& s) const; + void write_to_cpl (xmlpp::Node* node) const; bool equals (boost::shared_ptr other, EqualityOptions opt, boost::function note) const; diff --git a/src/subtitle_asset.cc b/src/subtitle_asset.cc index d89d52de..5decc1e3 100644 --- a/src/subtitle_asset.cc +++ b/src/subtitle_asset.cc @@ -276,15 +276,15 @@ SubtitleAsset::add (shared_ptr s) } void -SubtitleAsset::write_to_cpl (ostream& s) const +SubtitleAsset::write_to_cpl (xmlpp::Node* node) const { /* XXX: should EditRate, Duration and IntrinsicDuration be in here? */ - - s << " \n" - << " urn:uuid:" << _uuid << "\n" - << " " << _file_name << "\n" - << " 0\n" - << " \n"; + + xmlpp::Node* ms = node->add_child ("MainSubtitle"); + ms->add_child("Id")->add_child_text("urn:uuid:" + _uuid); + ms->add_child("AnnotationText")->add_child_text (_file_name); + /* XXX */ + ms->add_child("EntryPoint")->add_child_text ("0"); } struct SubtitleSorter { @@ -299,26 +299,30 @@ struct SubtitleSorter { void SubtitleAsset::write_xml () const { - ofstream f (path().string().c_str()); - write_xml (f); + ofstream s (path().string().c_str()); + write_xml (s); } void SubtitleAsset::write_xml (ostream& s) const { - s << "\n" - << "\n" - << " " << _uuid << "\n" - << " " << _movie_title << "\n" - << " " << _reel_number << "\n" - << " " << _language << "\n"; + xmlpp::Document doc; + xmlpp::Element* root = doc.create_root_node ("DCSubtitle"); + root->set_attribute ("Version", "1.0"); + + root->add_child("SubtitleID")->add_child_text (_uuid); + root->add_child("MovieTitle")->add_child_text (_movie_title); + root->add_child("ReelNumber")->add_child_text (lexical_cast (_reel_number)); + root->add_child("Language")->add_child_text (_language); if (_load_font_nodes.size() > 1) { boost::throw_exception (MiscError ("multiple LoadFont nodes not supported")); } if (!_load_font_nodes.empty ()) { - s << " id << "\" URI=\"" << _load_font_nodes.front()->uri << "\"/>\n"; + xmlpp::Element* load_font = root->add_child("LoadFont"); + load_font->set_attribute("Id", _load_font_nodes.front()->id); + load_font->set_attribute("URI", _load_font_nodes.front()->uri); } list > sorted = _subtitles; @@ -329,7 +333,6 @@ SubtitleAsset::write_xml (ostream& s) const /* XXX: multiple fonts not supported */ /* XXX: script, underlined, weight not supported */ - bool first = true; bool italic = false; Color color; int size = 0; @@ -341,66 +344,61 @@ SubtitleAsset::write_xml (ostream& s) const Time last_fade_up_time; Time last_fade_down_time; + xmlpp::Element* font = 0; + xmlpp::Element* subtitle = 0; + for (list >::iterator i = sorted.begin(); i != sorted.end(); ++i) { /* We will start a new ... whenever some font property changes. - I suppose should really make an optimal hierarchy of tags, but + I suppose we should really make an optimal hierarchy of tags, but that seems hard. */ - bool const font_changed = first || + bool const font_changed = italic != (*i)->italic() || color != (*i)->color() || size != (*i)->size() || effect != (*i)->effect() || effect_color != (*i)->effect_color(); - stringstream a; if (font_changed) { italic = (*i)->italic (); - a << "Italic=\"" << (italic ? "yes" : "no") << "\" "; color = (*i)->color (); - a << "Color=\"" << color.to_argb_string() << "\" "; size = (*i)->size (); - a << "Size=\"" << size << "\" "; effect = (*i)->effect (); - a << "Effect=\"" << effect_to_string(effect) << "\" "; effect_color = (*i)->effect_color (); - a << "EffectColor=\"" << effect_color.to_argb_string() << "\" "; - a << "Script=\"normal\" Underlined=\"no\" Weight=\"normal\""; } - if (first || font_changed || + if (!font || font_changed) { + font = root->add_child ("Font"); + string id = "theFontId"; + if (!_load_font_nodes.empty()) { + id = _load_font_nodes.front()->id; + } + font->set_attribute ("Id", id); + font->set_attribute ("Italic", italic ? "yes" : "no"); + font->set_attribute ("Color", color.to_argb_string()); + font->set_attribute ("Size", lexical_cast (size)); + font->set_attribute ("Effect", effect_to_string (effect)); + font->set_attribute ("EffectColor", effect_color.to_argb_string()); + font->set_attribute ("Script", "normal"); + font->set_attribute ("Underlined", "no"); + font->set_attribute ("Weight", "normal"); + } + + if (!subtitle || (last_in != (*i)->in() || last_out != (*i)->out() || last_fade_up_time != (*i)->fade_up_time() || last_fade_down_time != (*i)->fade_down_time() )) { - if (!first) { - s << " \n"; - } - - if (font_changed) { - if (!first) { - s << " \n"; - } - - string id = "theFontId"; - if (!_load_font_nodes.empty()) { - id = _load_font_nodes.front()->id; - } - - s << " \n"; - } - - s << " in().to_string() << "\" " - << "TimeOut=\"" << (*i)->out().to_string() << "\" " - << "FadeUpTime=\"" << (*i)->fade_up_time().to_ticks() << "\" " - << "FadeDownTime=\"" << (*i)->fade_down_time().to_ticks() << "\"" - << ">\n"; + subtitle = font->add_child ("Subtitle"); + subtitle->set_attribute ("SpotNumber", lexical_cast (spot_number++)); + subtitle->set_attribute ("TimeIn", (*i)->in().to_string()); + subtitle->set_attribute ("TimeOut", (*i)->out().to_string()); + subtitle->set_attribute ("FadeUpTime", lexical_cast ((*i)->fade_up_time().to_ticks())); + subtitle->set_attribute ("FadeDownTime", lexical_cast ((*i)->fade_down_time().to_ticks())); last_in = (*i)->in (); last_out = (*i)->out (); @@ -408,23 +406,12 @@ SubtitleAsset::write_xml (ostream& s) const last_fade_down_time = (*i)->fade_down_time (); } - s << " v_align()) << "\" " - << "VPosition=\"" << (*i)->v_position() << "\"" - << ">" << escape ((*i)->text()) << "\n"; - - first = false; + xmlpp::Element* text = subtitle->add_child ("Text"); + text->set_attribute ("VAlign", valign_to_string ((*i)->v_align())); + text->set_attribute ("VPosition", lexical_cast ((*i)->v_position())); + text->add_child_text ((*i)->text()); } - s << " \n"; - s << " \n"; - s << "\n"; + doc.write_to_stream_formatted (s); } -/** XXX: Another reason why we should be writing with libxml++ */ -string -SubtitleAsset::escape (string s) const -{ - boost::replace_all (s, "&", "&"); - return s; -} diff --git a/src/subtitle_asset.h b/src/subtitle_asset.h index 0d662d6c..2da1ce7b 100644 --- a/src/subtitle_asset.h +++ b/src/subtitle_asset.h @@ -123,7 +123,7 @@ public: SubtitleAsset (std::string directory, std::string xml_file); SubtitleAsset (std::string directory, std::string movie_title, std::string language); - void write_to_cpl (std::ostream&) const; + void write_to_cpl (xmlpp::Node *) const; virtual bool equals (boost::shared_ptr, EqualityOptions, boost::function note) const { /* XXX */ note (ERROR, "subtitle assets not compared yet"); @@ -143,11 +143,10 @@ public: void read_xml (std::string); void write_xml () const; - void write_xml (std::ostream& s) const; + void write_xml (std::ostream &) const; private: std::string font_id_to_name (std::string id) const; - std::string escape (std::string) const; struct ParseState { std::list > font_nodes; -- cgit v1.2.3