Make some not-so-important CPL read errors non-fatal (DoM #2797).
[libdcp.git] / src / cpl.h
1 /*
2     Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
3
4     This file is part of libdcp.
5
6     libdcp is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     libdcp is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with libdcp.  If not, see <http://www.gnu.org/licenses/>.
18
19     In addition, as a special exception, the copyright holders give
20     permission to link the code of portions of this program with the
21     OpenSSL library under certain conditions as described in each
22     individual source file, and distribute linked combinations
23     including the two.
24
25     You must obey the GNU General Public License in all respects
26     for all of the code used other than OpenSSL.  If you modify
27     file(s) with this exception, you may extend this exception to your
28     version of the file(s), but you are not obligated to do so.  If you
29     do not wish to do so, delete this exception statement from your
30     version.  If you delete this exception statement from all source
31     files in the program, then also delete it here.
32 */
33
34
35 /** @file  src/cpl.h
36  *  @brief CPL class
37  */
38
39
40 #ifndef LIBDCP_CPL_H
41 #define LIBDCP_CPL_H
42
43
44 #include "asset.h"
45 #include "certificate.h"
46 #include "content_kind.h"
47 #include "key.h"
48 #include "language_tag.h"
49 #include "rating.h"
50 #include "verify.h"
51 #include <boost/filesystem.hpp>
52 #include <boost/function.hpp>
53 #include <boost/optional.hpp>
54 #include <memory>
55 #include <vector>
56
57
58 struct verify_invalid_language3;
59
60
61 namespace dcp {
62
63
64 class CertificateChain;
65 class DecryptedKDM;
66 class MXFMetadata;
67 class Reel;
68 class ReelFileAsset;
69 class SoundAsset;
70
71
72 /** @class CPL
73  *  @brief A Composition Playlist
74  *
75  *  A CPL contains some metadata and a list of Reel objects, each of which may contain picture, sound and other assets
76  *  such as subtitles and closed captions.
77  *
78  *  After creating a CPL you can add Reel objects with add(), and write an XML file describing the CPL with
79  *  write_xml().
80  */
81 class CPL : public Asset
82 {
83 public:
84         CPL (std::string annotation_text, ContentKind content_kind, Standard standard);
85
86         /** Construct a CPL object from a XML file.
87          *  If notes is not null, non-fatal errors will be added.
88          *  Exceptions will be thrown on non-recoverable errors.
89          */
90         explicit CPL(boost::filesystem::path file, std::vector<dcp::VerificationNote>* notes = nullptr);
91
92         bool equals (
93                 std::shared_ptr<const Asset> other,
94                 EqualityOptions const& options,
95                 NoteHandler note
96                 ) const override;
97
98         /** Add a reel to this CPL
99          *  @param reel Reel to add
100          */
101         void add (std::shared_ptr<Reel> reel);
102
103         void set (std::vector<std::shared_ptr<Reel>> reels);
104
105         /** Add a KDM to this CPL.  If the KDM is for any of this CPLs assets it will be used
106          *  to decrypt those assets.
107          *  @param kdm KDM.
108          */
109         void add (DecryptedKDM const &);
110
111         /** @return the reels in this CPL */
112         std::vector<std::shared_ptr<Reel>> reels () const {
113                 return _reels;
114         }
115
116         /** @return the ReelFileAssets in this CPL in all reels */
117         std::vector<std::shared_ptr<const ReelFileAsset>> reel_file_assets () const;
118         std::vector<std::shared_ptr<ReelFileAsset>> reel_file_assets ();
119
120         /** @return true if we have any encrypted content */
121         bool any_encrypted () const;
122
123         /** @return true if we have all our encryptable content is encrypted */
124         bool all_encrypted () const;
125
126         /** Write a CompositionPlaylist XML file
127          *
128          *  @param file Filename to write
129          *  @param signer Signer to sign the CPL, or 0 to add no signature
130          *  @param include_mca_subdescriptors true to add a MCASubDescriptors tag to metadata,
131          *  false to omit it.
132          */
133         void write_xml (
134                 boost::filesystem::path file,
135                 std::shared_ptr<const CertificateChain>,
136                 bool include_mca_subdescriptors = true
137                 ) const;
138
139         void resolve_refs (std::vector<std::shared_ptr<Asset>>);
140
141         int64_t duration () const;
142
143         std::string issuer () const {
144                 return _issuer;
145         }
146
147         void set_issuer (std::string issuer) {
148                 _issuer = issuer;
149         }
150
151         std::string creator () const {
152                 return _creator;
153         }
154
155         void set_creator (std::string creator) {
156                 _creator = creator;
157         }
158
159         void set_issue_date (std::string issue_date) {
160                 _issue_date = issue_date;
161         }
162
163         /** @return contents of the &lt;AnnotationText&gt; node, if present */
164         boost::optional<std::string> annotation_text () const {
165                 return _annotation_text;
166         }
167
168         void set_annotation_text (std::string at) {
169                 _annotation_text = at;
170         }
171
172         /** @return contents of the &lt;ContentTitleText&gt; node */
173         std::string content_title_text () const {
174                 return _content_title_text;
175         }
176
177         void set_content_title_text (std::string ct) {
178                 _content_title_text = ct;
179         }
180
181         void set_content_kind (dcp::ContentKind k) {
182                 _content_kind = k;
183         }
184
185         /** @return the type of the content, used by media servers
186          *  to categorise things (e.g. feature, trailer, etc.)
187          */
188         ContentKind content_kind () const {
189                 return _content_kind;
190         }
191
192         boost::optional<ContentVersion> content_version () const;
193
194         std::vector<ContentVersion> content_versions () const {
195                 return _content_versions;
196         }
197
198         void set_content_version (ContentVersion v) {
199                 _content_versions.clear ();
200                 _content_versions.push_back (v);
201         }
202
203         void set_content_versions (std::vector<ContentVersion> v);
204
205         std::vector<Rating> ratings () const {
206                 return _ratings;
207         }
208
209         void set_ratings (std::vector<Rating> r) {
210                 _ratings = r;
211         }
212
213         boost::optional<std::string> full_content_title_text () const {
214                 return _full_content_title_text;
215         }
216
217         void set_full_content_title_text (std::string t) {
218                 _full_content_title_text = t;
219         }
220
221         boost::optional<std::string> full_content_title_text_language () const {
222                 return _full_content_title_text_language;
223         }
224
225         void set_full_content_title_text_language (dcp::LanguageTag l) {
226                 _full_content_title_text_language = l.to_string();
227         }
228
229         boost::optional<std::string> release_territory () const {
230                 return _release_territory;
231         }
232
233         void set_release_territory (dcp::LanguageTag::RegionSubtag t) {
234                 _release_territory = t.subtag();
235         }
236
237         boost::optional<std::string> release_territory_scope () const {
238                 return _release_territory_scope;
239         }
240
241         boost::optional<int> version_number () const {
242                 return _version_number;
243         }
244
245         void set_version_number (int v);
246
247         void unset_version_number ();
248
249         boost::optional<Status> status () const {
250                 return _status;
251         }
252
253         void set_status (Status s) {
254                 _status = s;
255         }
256
257         boost::optional<std::string> chain () const {
258                 return _chain;
259         }
260
261         void set_chain (std::string c) {
262                 _chain = c;
263         }
264
265         boost::optional<std::string> distributor () const {
266                 return _distributor;
267         }
268
269         void set_distributor (std::string d) {
270                 _distributor = d;
271         }
272
273         boost::optional<std::string> facility () const {
274                 return _facility;
275         }
276
277         void set_facility (std::string f) {
278                 _facility = f;
279         }
280
281         boost::optional<Luminance> luminance () const {
282                 return _luminance;
283         }
284
285         void set_luminance (Luminance l) {
286                 _luminance = l;
287         }
288
289         boost::optional<dcp::MainSoundConfiguration> main_sound_configuration () const {
290                 return _main_sound_configuration;
291         }
292
293         void set_main_sound_configuration(dcp::MainSoundConfiguration c) {
294                 _main_sound_configuration = c;
295         }
296
297         boost::optional<int> main_sound_sample_rate () const {
298                 return _main_sound_sample_rate;
299         }
300
301         void set_main_sound_sample_rate (int r) {
302                 _main_sound_sample_rate = r;
303         }
304
305         boost::optional<dcp::Size> main_picture_stored_area () const {
306                 return _main_picture_stored_area;
307         }
308
309         void set_main_picture_stored_area (dcp::Size s) {
310                 _main_picture_stored_area = s;
311         }
312
313         boost::optional<dcp::Size> main_picture_active_area () const {
314                 return _main_picture_active_area;
315         }
316
317         void set_main_picture_active_area(dcp::Size area);
318
319         std::vector<std::string> additional_subtitle_languages () const {
320                 return _additional_subtitle_languages;
321         }
322
323         void set_additional_subtitle_languages (std::vector<dcp::LanguageTag> const& lang);
324
325         void set_sign_language_video_language (dcp::LanguageTag lang) {
326                 _sign_language_video_language = lang.to_string();
327         }
328
329         boost::optional<std::string> sign_language_video_language () const {
330                 return _sign_language_video_language;
331         }
332
333         void set_dolby_edr_image_transfer_function(std::string function) {
334                 _dolby_edr_image_transfer_function = function;
335         }
336
337         boost::optional<std::string> dolby_edr_image_transfer_function() const {
338                 return _dolby_edr_image_transfer_function;
339         }
340
341         Standard standard () const {
342                 return _standard;
343         }
344
345         /** @return true iff this CPL was read from a file and it contained
346          *  a CompositionMetadataAsset node.
347          */
348         bool read_composition_metadata() const {
349                 return _read_composition_metadata;
350         }
351
352         static std::string static_pkl_type (Standard standard);
353
354 protected:
355         /** @return type string for PKLs for this asset */
356         std::string pkl_type (Standard standard) const override;
357
358 private:
359         friend struct ::verify_invalid_language3;
360
361         void maybe_write_composition_metadata_asset(xmlpp::Element* node, bool include_mca_subdescriptors) const;
362         void read_composition_metadata_asset (cxml::ConstNodePtr node);
363         void write_mca_subdescriptors(xmlpp::Element* parent, std::shared_ptr<const SoundAsset> asset) const;
364
365         std::string _issuer;
366         std::string _creator;
367         std::string _issue_date;
368         boost::optional<std::string> _annotation_text;
369         std::string _content_title_text;            ///< &lt;ContentTitleText&gt;
370         ContentKind _content_kind;                  ///< &lt;ContentKind&gt;
371         std::vector<ContentVersion> _content_versions;
372         std::vector<Rating> _ratings;
373         /** ID for CompositionMetadataAsset tag; either a random one, ready for writing a new tag,
374          *  or the one read in from the existing CPL.
375          */
376         std::string _cpl_metadata_id = make_uuid();
377         /** Human-readable name of the composition, without any metadata (i.e. no -FTR-EN-XX- etc.) */
378         boost::optional<std::string> _full_content_title_text;
379         boost::optional<std::string> _full_content_title_text_language;
380         /** This is stored and returned as a string so that we can tolerate non-RFC-5646 strings,
381          *  but must be set as a dcp::LanguageTag to try to ensure that we create compliant output.
382          */
383         boost::optional<std::string> _release_territory;
384         boost::optional<std::string> _release_territory_scope;
385         boost::optional<int> _version_number;
386         boost::optional<Status> _status;
387         boost::optional<std::string> _chain;
388         boost::optional<std::string> _distributor;
389         boost::optional<std::string> _facility;
390         boost::optional<Luminance> _luminance;
391         boost::optional<MainSoundConfiguration> _main_sound_configuration;
392         boost::optional<int> _main_sound_sample_rate;
393         boost::optional<dcp::Size> _main_picture_stored_area;
394         boost::optional<dcp::Size> _main_picture_active_area;
395         /* See note for _release_territory above */
396         std::vector<std::string> _additional_subtitle_languages;
397         boost::optional<std::string> _sign_language_video_language;
398         boost::optional<std::string> _dolby_edr_image_transfer_function;
399         bool _read_composition_metadata = false;
400
401         std::vector<std::shared_ptr<Reel>> _reels;
402
403         /** Standard of CPL that was read in */
404         Standard _standard;
405 };
406
407
408 }
409
410
411 #endif