#include <fstream>
#include <iomanip>
#include <cassert>
+#include <iostream>
#include <boost/filesystem.hpp>
+#include <libxml++/libxml++.h>
#include "dcp.h"
#include "asset.h"
#include "sound_asset.h"
#include "picture_asset.h"
+#include "subtitle_asset.h"
#include "util.h"
#include "metadata.h"
#include "exceptions.h"
#include "cpl.h"
#include "pkl.h"
#include "asset_map.h"
+#include "reel.h"
using namespace std;
using namespace boost;
}
void
-DCP::add_sound_asset (vector<string> const & files)
+DCP::add_reel (shared_ptr<const Reel> reel)
{
- _assets.push_back (shared_ptr<SoundAsset> (new SoundAsset (files, _directory, "audio.mxf", &Progress, _fps, _length)));
-}
-
-void
-DCP::add_sound_asset (sigc::slot<string, Channel> get_path, int channels)
-{
- _assets.push_back (shared_ptr<SoundAsset> (new SoundAsset (get_path, _directory, "audio.mxf", &Progress, _fps, _length, channels)));
-}
-
-void
-DCP::add_picture_asset (vector<string> const & files, int width, int height)
-{
- _assets.push_back (shared_ptr<PictureAsset> (new PictureAsset (files, _directory, "video.mxf", &Progress, _fps, _length, width, height)));
-}
-
-void
-DCP::add_picture_asset (sigc::slot<string, int> get_path, int width, int height)
-{
- _assets.push_back (shared_ptr<PictureAsset> (new PictureAsset (get_path, _directory, "video.mxf", &Progress, _fps, _length, width, height)));
+ _reels.push_back (reel);
}
void
<< " <RatingList/>\n"
<< " <ReelList>\n";
- cpl << " <Reel>\n"
- << " <Id>urn:uuid:" << make_uuid() << "</Id>\n"
- << " <AssetList>\n";
-
- for (list<shared_ptr<Asset> >::const_iterator i = _assets.begin(); i != _assets.end(); ++i) {
+ for (list<shared_ptr<const Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) {
(*i)->write_to_cpl (cpl);
}
<< " <Creator>" << Metadata::instance()->creator << "</Creator>\n"
<< " <AssetList>\n";
- for (list<shared_ptr<Asset> >::const_iterator i = _assets.begin(); i != _assets.end(); ++i) {
+ for (list<shared_ptr<const Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) {
(*i)->write_to_pkl (pkl);
}
<< " </ChunkList>\n"
<< " </Asset>\n";
- for (list<shared_ptr<Asset> >::const_iterator i = _assets.begin(); i != _assets.end(); ++i) {
+ for (list<shared_ptr<const Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) {
(*i)->write_to_assetmap (am);
}
DCP::DCP (string directory)
: _directory (directory)
{
- string cpl_file;
- string pkl_file;
- string asset_map_file;
-
- for (filesystem::directory_iterator i = filesystem::directory_iterator(directory); i != filesystem::directory_iterator(); ++i) {
- string const t = i->path().string ();
- if (ends_with (t, "_cpl.xml")) {
- if (cpl_file.empty ()) {
- cpl_file = t;
- } else {
- throw DCPReadError ("duplicate CPLs found");
- }
- } else if (ends_with (t, "_pkl.xml")) {
- if (pkl_file.empty ()) {
- pkl_file = t;
- } else {
- throw DCPReadError ("duplicate PKLs found");
- }
- } else if (ends_with (t, "ASSETMAP.xml")) {
- if (asset_map_file.empty ()) {
- asset_map_file = t;
- } else {
- throw DCPReadError ("duplicate AssetMaps found");
- }
- }
- }
+ Files files;
+ scan (files, directory);
- if (cpl_file.empty ()) {
+ if (files.cpl.empty ()) {
throw FileError ("no CPL file found", "");
}
- if (pkl_file.empty ()) {
+ if (files.pkl.empty ()) {
throw FileError ("no PKL file found", "");
}
- if (asset_map_file.empty ()) {
+ if (files.asset_map.empty ()) {
throw FileError ("no AssetMap file found", "");
}
/* Read the XML */
shared_ptr<CPL> cpl;
try {
- cpl.reset (new CPL (cpl_file));
+ cpl.reset (new CPL (files.cpl));
} catch (FileError& e) {
- throw FileError ("could not load CPL file", cpl_file);
+ throw FileError ("could not load CPL file", files.cpl);
}
shared_ptr<PKL> pkl;
try {
- pkl.reset (new PKL (pkl_file));
+ pkl.reset (new PKL (files.pkl));
} catch (FileError& e) {
- throw FileError ("could not load PKL file", pkl_file);
+ throw FileError ("could not load PKL file", files.pkl);
}
shared_ptr<AssetMap> asset_map;
try {
- asset_map.reset (new AssetMap (asset_map_file));
+ asset_map.reset (new AssetMap (files.asset_map));
} catch (FileError& e) {
- throw FileError ("could not load AssetMap file", asset_map_file);
+ throw FileError ("could not load AssetMap file", files.asset_map);
}
/* Cross-check */
_name = cpl->annotation_text;
_content_kind = cpl->content_kind;
+ _length = 0;
+ _fps = 0;
- shared_ptr<CPLAssetList> cpl_assets = cpl->reels.front()->asset_list;
+ for (list<shared_ptr<CPLReel> >::iterator i = cpl->reels.begin(); i != cpl->reels.end(); ++i) {
+ assert (_fps == 0 || _fps == (*i)->asset_list->main_picture->frame_rate.numerator);
+ _fps = (*i)->asset_list->main_picture->frame_rate.numerator;
+ _length += (*i)->asset_list->main_picture->duration;
- /* XXX */
- _fps = cpl_assets->main_picture->frame_rate.numerator;
- _length = cpl_assets->main_picture->duration;
-
- _assets.push_back (shared_ptr<PictureAsset> (
- new PictureAsset (
- _directory,
- cpl_assets->main_picture->annotation_text,
- _fps,
- _length,
- cpl_assets->main_picture->screen_aspect_ratio.numerator,
- cpl_assets->main_picture->screen_aspect_ratio.denominator
- )
- ));
-
- if (cpl_assets->main_sound) {
- _assets.push_back (shared_ptr<SoundAsset> (
- new SoundAsset (
- _directory,
- cpl_assets->main_sound->annotation_text,
- _fps,
- _length
- )
- ));
+ string n = pkl->asset_from_id ((*i)->asset_list->main_picture->id)->original_file_name;
+ if (n.empty ()) {
+ n = (*i)->asset_list->main_picture->annotation_text;
+ }
+
+ shared_ptr<PictureAsset> picture (new PictureAsset (
+ _directory,
+ n,
+ _fps,
+ (*i)->asset_list->main_picture->duration
+ )
+ );
+
+ shared_ptr<SoundAsset> sound;
+
+ if ((*i)->asset_list->main_sound) {
+
+ n = pkl->asset_from_id ((*i)->asset_list->main_sound->id)->original_file_name;
+ if (n.empty ()) {
+ n = (*i)->asset_list->main_sound->annotation_text;
+ }
+
+ sound.reset (new SoundAsset (
+ _directory,
+ n,
+ _fps,
+ (*i)->asset_list->main_sound->duration
+ )
+ );
+ }
+
+ assert (files.subtitles.size() < 2);
+
+ shared_ptr<SubtitleAsset> subtitle;
+ if (!files.subtitles.empty ()) {
+ string const l = files.subtitles.front().substr (_directory.length ());
+ subtitle.reset (new SubtitleAsset (_directory, l));
+ }
+
+ _reels.push_back (shared_ptr<Reel> (new Reel (picture, sound, subtitle)));
+ }
+}
+
+
+void
+DCP::scan (Files& files, string directory) const
+{
+ for (filesystem::directory_iterator i = filesystem::directory_iterator(directory); i != filesystem::directory_iterator(); ++i) {
+
+ string const t = i->path().string ();
+
+ if (filesystem::is_directory (*i)) {
+ scan (files, t);
+ continue;
+ }
+
+ if (ends_with (t, ".mxf") || ends_with (t, ".ttf")) {
+ continue;
+ }
+
+ xmlpp::DomParser* p = new xmlpp::DomParser;
+
+ try {
+ p->parse_file (t);
+ } catch (std::exception& e) {
+ delete p;
+ continue;
+ }
+
+ if (!p) {
+ delete p;
+ continue;
+ }
+
+ string const root = p->get_document()->get_root_node()->get_name ();
+ delete p;
+
+ if (root == "CompositionPlaylist") {
+ if (files.cpl.empty ()) {
+ files.cpl = t;
+ } else {
+ throw DCPReadError ("duplicate CPLs found");
+ }
+ } else if (root == "PackingList") {
+ if (files.pkl.empty ()) {
+ files.pkl = t;
+ } else {
+ throw DCPReadError ("duplicate PKLs found");
+ }
+ } else if (root == "AssetMap") {
+ if (files.asset_map.empty ()) {
+ files.asset_map = t;
+ } else {
+ throw DCPReadError ("duplicate AssetMaps found");
+ }
+ files.asset_map = t;
+ } else if (root == "DCSubtitle") {
+ files.subtitles.push_back (t);
+ }
}
}
+
list<string>
-DCP::equals (DCP const & other, EqualityFlags flags) const
+DCP::equals (DCP const & other, EqualityOptions opt) const
{
list<string> notes;
- if (flags & LIBDCP_METADATA) {
+ if (opt.flags & LIBDCP_METADATA) {
if (_name != other._name) {
notes.push_back ("names differ");
}
}
}
- if (_assets.size() != other._assets.size()) {
- notes.push_back ("asset counts differ");
+ if (_reels.size() != other._reels.size()) {
+ notes.push_back ("reel counts differ");
}
- list<shared_ptr<Asset> >::const_iterator a = _assets.begin ();
- list<shared_ptr<Asset> >::const_iterator b = other._assets.begin ();
+ list<shared_ptr<const Reel> >::const_iterator a = _reels.begin ();
+ list<shared_ptr<const Reel> >::const_iterator b = other._reels.begin ();
- while (a != _assets.end ()) {
- list<string> n = (*a)->equals (*b, flags);
+ while (a != _reels.end ()) {
+ list<string> n = (*a)->equals (*b, opt);
notes.merge (n);
++a;
++b;
return notes;
}
+