+
+bool
+Reel::any_encrypted () const
+{
+ auto ecc = false;
+ for (auto i: _closed_captions) {
+ if (i->encrypted()) {
+ ecc = true;
+ }
+ }
+
+ return (
+ (_main_picture && _main_picture->encrypted()) ||
+ (_main_sound && _main_sound->encrypted()) ||
+ (_main_subtitle && _main_subtitle->encrypted()) ||
+ ecc ||
+ (_atmos && _atmos->encrypted())
+ );
+}
+
+
+bool
+Reel::all_encrypted () const
+{
+ auto ecc = true;
+ for (auto i: _closed_captions) {
+ if (!i->encrypted()) {
+ ecc = false;
+ }
+ }
+
+ return (
+ (!_main_picture || _main_picture->encrypted()) &&
+ (!_main_sound || _main_sound->encrypted()) &&
+ (!_main_subtitle || _main_subtitle->encrypted()) &&
+ ecc &&
+ (!_atmos || _atmos->encrypted())
+ );
+}
+
+
+void
+Reel::add (DecryptedKDM const & kdm)
+{
+ give_kdm_to_assets (kdm);
+ /* We have to keep the KDMs that we are given, as they will not be passed to unresolved assets.
+ * After we resolve some assets we will re-call give_kdm_to_assets() with all the KDMs that
+ * we have been given so far.
+ */
+ _kdms.push_back (kdm);
+}
+
+
+void
+Reel::give_kdm_to_assets (DecryptedKDM const & kdm)
+{
+ for (auto const& i: kdm.keys()) {
+ if (_main_picture && i.id() == _main_picture->key_id() && _main_picture->asset_ref().resolved()) {
+ _main_picture->asset()->set_key (i.key());
+ }
+ if (_main_sound && i.id() == _main_sound->key_id() && _main_sound->asset_ref().resolved()) {
+ _main_sound->asset()->set_key (i.key());
+ }
+ if (_main_subtitle) {
+ auto smpte = dynamic_pointer_cast<ReelSMPTESubtitleAsset>(_main_subtitle);
+ if (smpte && i.id() == smpte->key_id() && smpte->asset_ref().resolved()) {
+ smpte->smpte_asset()->set_key(i.key());
+ }
+ }
+ for (auto j: _closed_captions) {
+ auto smpte = dynamic_pointer_cast<ReelSMPTESubtitleAsset>(j);
+ if (smpte && i.id() == smpte->key_id() && smpte->asset_ref().resolved()) {
+ smpte->smpte_asset()->set_key(i.key());
+ }
+ }
+ if (_atmos && i.id() == _atmos->key_id() && _atmos->asset_ref().resolved()) {
+ _atmos->asset()->set_key (i.key());
+ }
+ }
+}
+
+
+void
+Reel::add (shared_ptr<ReelAsset> asset)
+{
+ if (auto p = dynamic_pointer_cast<ReelPictureAsset>(asset)) {
+ _main_picture = p;
+ } else if (auto so = dynamic_pointer_cast<ReelSoundAsset>(asset)) {
+ _main_sound = so;
+ } else if (auto su = dynamic_pointer_cast<ReelSubtitleAsset>(asset)) {
+ _main_subtitle = su;
+ } else if (auto m = dynamic_pointer_cast<ReelMarkersAsset>(asset)) {
+ _main_markers = m;
+ } else if (auto c = dynamic_pointer_cast<ReelClosedCaptionAsset>(asset)) {
+ _closed_captions.push_back (c);
+ } else if (auto a = dynamic_pointer_cast<ReelAtmosAsset>(asset)) {
+ _atmos = a;
+ } else {
+ DCP_ASSERT(false);
+ }
+}
+
+
+vector<shared_ptr<ReelAsset>>
+Reel::assets () const
+{
+ vector<shared_ptr<ReelAsset>> a;
+ if (_main_picture) {
+ a.push_back (_main_picture);
+ }
+ if (_main_sound) {
+ a.push_back (_main_sound);
+ }
+ if (_main_subtitle) {
+ a.push_back (_main_subtitle);
+ }
+ std::copy (_closed_captions.begin(), _closed_captions.end(), back_inserter(a));
+ if (_atmos) {
+ a.push_back (_atmos);
+ }
+ return a;
+}
+
+
+void
+Reel::resolve_refs (vector<shared_ptr<Asset>> assets)
+{
+ if (_main_picture) {
+ _main_picture->asset_ref().resolve(assets);
+ }
+
+ if (_main_sound) {
+ _main_sound->asset_ref().resolve(assets);
+ }
+
+ if (_main_subtitle) {
+ _main_subtitle->asset_ref().resolve(assets);
+
+ /* Interop subtitle handling is all special cases */
+ if (_main_subtitle->asset_ref().resolved()) {
+ auto iop = dynamic_pointer_cast<InteropSubtitleAsset> (_main_subtitle->asset_ref().asset());
+ if (iop) {
+ iop->resolve_fonts (assets);
+ }
+ }
+ }
+
+ for (auto i: _closed_captions) {
+ i->asset_ref().resolve(assets);
+
+ /* Interop subtitle handling is all special cases */
+ if (i->asset_ref().resolved()) {
+ auto iop = dynamic_pointer_cast<InteropSubtitleAsset> (i->asset_ref().asset());
+ if (iop) {
+ iop->resolve_fonts (assets);
+ }
+ }
+ }
+
+ if (_atmos) {
+ _atmos->asset_ref().resolve (assets);
+ }
+
+ for (auto const& i: _kdms) {
+ give_kdm_to_assets (i);
+ }
+}
+
+
+int64_t
+Reel::duration () const
+{
+ if (_main_picture) {
+ return _main_picture->actual_duration();
+ }
+
+ int64_t d = INT64_MAX;
+
+ if (_main_sound) {
+ d = min (d, _main_sound->actual_duration());
+ }
+ if (_main_subtitle) {
+ d = min (d, _main_subtitle->actual_duration());
+ }
+ if (_main_markers) {
+ d = min (d, _main_markers->actual_duration());
+ }
+ for (auto i: _closed_captions) {
+ d = min (d, i->actual_duration());
+ }
+ if (_atmos) {
+ d = min (d, _atmos->actual_duration());
+ }
+
+ DCP_ASSERT (d < INT64_MAX);
+
+ return d;
+}