+ /* Read the XML */
+ shared_ptr<parse::CPL> cpl;
+ try {
+ cpl.reset (new parse::CPL (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;
+
+ /* Trim urn:uuid: off the front */
+ _id = cpl->id.substr (9);
+
+ for (list<shared_ptr<parse::Reel> >::iterator i = cpl->reels.begin(); i != cpl->reels.end(); ++i) {
+
+ shared_ptr<parse::Picture> 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<PictureAsset> picture;
+ shared_ptr<SoundAsset> sound;
+ shared_ptr<SubtitleAsset> 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 {
+ pair<string, shared_ptr<const parse::AssetMapAsset> > asset = asset_from_id (asset_maps, p->id);
+
+ picture.reset (new MonoPictureAsset (asset.first, asset.second->chunks.front()->path));
+
+ picture->read ();
+ picture->set_edit_rate (_fps);
+ picture->set_entry_point (p->entry_point);
+ picture->set_duration (p->duration);
+ if (p->key_id.length() > 9) {
+ /* Trim urn:uuid: */
+ picture->set_key_id (p->key_id.substr (9));
+ }
+ } catch (MXFFileError) {
+ if (require_mxfs) {
+ throw;
+ }
+ }
+
+ } else {
+ try {
+ pair<string, shared_ptr<const parse::AssetMapAsset> > asset = asset_from_id (asset_maps, p->id);
+
+ picture.reset (new StereoPictureAsset (asset.first, asset.second->chunks.front()->path));
+
+ picture->read ();
+ picture->set_edit_rate (_fps);
+ picture->set_entry_point (p->entry_point);
+ picture->set_duration (p->duration);
+ if (p->key_id.length() > 9) {
+ /* Trim urn:uuid: */
+ picture->set_key_id (p->key_id.substr (9));
+ }
+
+ } catch (MXFFileError) {
+ if (require_mxfs) {
+ throw;
+ }
+ }
+
+ }
+
+ if ((*i)->asset_list->main_sound) {
+
+ try {
+ pair<string, shared_ptr<const parse::AssetMapAsset> > asset = asset_from_id (asset_maps, (*i)->asset_list->main_sound->id);
+
+ sound.reset (new SoundAsset (asset.first, asset.second->chunks.front()->path));
+ shared_ptr<parse::MainSound> s = (*i)->asset_list->main_sound;
+
+ sound->read ();
+ sound->set_entry_point (s->entry_point);
+ sound->set_duration (s->duration);
+ if (s->key_id.length() > 9) {
+ /* Trim urn:uuid: */
+ sound->set_key_id (s->key_id.substr (9));
+ }
+ } catch (MXFFileError) {
+ if (require_mxfs) {
+ throw;
+ }
+ }
+ }
+
+ if ((*i)->asset_list->main_subtitle) {
+
+ pair<string, shared_ptr<const parse::AssetMapAsset> > asset = asset_from_id (asset_maps, (*i)->asset_list->main_subtitle->id);
+
+ subtitle.reset (new SubtitleAsset (asset.first, asset.second->chunks.front()->path));
+
+ subtitle->set_entry_point ((*i)->asset_list->main_subtitle->entry_point);
+ subtitle->set_duration ((*i)->asset_list->main_subtitle->duration);
+ }
+
+ _reels.push_back (shared_ptr<Reel> (new Reel (picture, sound, subtitle)));
+ }