Bump libdcp for some API improvements.
[dcpomatic.git] / src / lib / types.cc
1 /*
2     Copyright (C) 2013-2019 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
6     DCP-o-matic 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     DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21 #include "types.h"
22 #include "compose.hpp"
23 #include "dcpomatic_assert.h"
24 #include "warnings.h"
25 #include <dcp/raw_convert.h>
26 #include <dcp/cpl.h>
27 #include <dcp/dcp.h>
28 #include <dcp/reel_file_asset.h>
29 #include <dcp/reel_encryptable_asset.h>
30 #include <dcp/reel_asset.h>
31 DCPOMATIC_DISABLE_WARNINGS
32 #include <libxml++/libxml++.h>
33 DCPOMATIC_ENABLE_WARNINGS
34 #include <libcxml/cxml.h>
35
36 #include "i18n.h"
37
38 using std::max;
39 using std::min;
40 using std::string;
41 using std::list;
42 using std::shared_ptr;
43 using std::vector;
44 using dcp::raw_convert;
45
46 bool operator== (Crop const & a, Crop const & b)
47 {
48         return (a.left == b.left && a.right == b.right && a.top == b.top && a.bottom == b.bottom);
49 }
50
51 bool operator!= (Crop const & a, Crop const & b)
52 {
53         return !(a == b);
54 }
55
56 /** @param r Resolution.
57  *  @return Untranslated string representation.
58  */
59 string
60 resolution_to_string (Resolution r)
61 {
62         switch (r) {
63         case Resolution::TWO_K:
64                 return "2K";
65         case Resolution::FOUR_K:
66                 return "4K";
67         }
68
69         DCPOMATIC_ASSERT (false);
70         return "";
71 }
72
73
74 Resolution
75 string_to_resolution (string s)
76 {
77         if (s == "2K") {
78                 return Resolution::TWO_K;
79         }
80
81         if (s == "4K") {
82                 return Resolution::FOUR_K;
83         }
84
85         DCPOMATIC_ASSERT (false);
86         return Resolution::TWO_K;
87 }
88
89 Crop::Crop (shared_ptr<cxml::Node> node)
90 {
91         left = node->number_child<int> ("LeftCrop");
92         right = node->number_child<int> ("RightCrop");
93         top = node->number_child<int> ("TopCrop");
94         bottom = node->number_child<int> ("BottomCrop");
95 }
96
97 void
98 Crop::as_xml (xmlpp::Node* node) const
99 {
100         node->add_child("LeftCrop")->add_child_text (raw_convert<string> (left));
101         node->add_child("RightCrop")->add_child_text (raw_convert<string> (right));
102         node->add_child("TopCrop")->add_child_text (raw_convert<string> (top));
103         node->add_child("BottomCrop")->add_child_text (raw_convert<string> (bottom));
104 }
105
106 TextType
107 string_to_text_type (string s)
108 {
109         if (s == "unknown") {
110                 return TextType::UNKNOWN;
111         } else if (s == "open-subtitle") {
112                 return TextType::OPEN_SUBTITLE;
113         } else if (s == "closed-caption") {
114                 return TextType::CLOSED_CAPTION;
115         } else {
116                 throw MetadataError (String::compose ("Unknown text type %1", s));
117         }
118 }
119
120 string
121 text_type_to_string (TextType t)
122 {
123         switch (t) {
124         case TextType::UNKNOWN:
125                 return "unknown";
126         case TextType::OPEN_SUBTITLE:
127                 return "open-subtitle";
128         case TextType::CLOSED_CAPTION:
129                 return "closed-caption";
130         default:
131                 DCPOMATIC_ASSERT (false);
132         }
133 }
134
135 string
136 text_type_to_name (TextType t)
137 {
138         switch (t) {
139         case TextType::UNKNOWN:
140                 return _("Timed text");
141         case TextType::OPEN_SUBTITLE:
142                 return _("Open subtitles");
143         case TextType::CLOSED_CAPTION:
144                 return _("Closed captions");
145         default:
146                 DCPOMATIC_ASSERT (false);
147         }
148 }
149
150 string
151 video_frame_type_to_string (VideoFrameType t)
152 {
153         switch (t) {
154         case VideoFrameType::TWO_D:
155                 return "2d";
156         case VideoFrameType::THREE_D:
157                 return "3d";
158         case VideoFrameType::THREE_D_LEFT_RIGHT:
159                 return "3d-left-right";
160         case VideoFrameType::THREE_D_TOP_BOTTOM:
161                 return "3d-top-bottom";
162         case VideoFrameType::THREE_D_ALTERNATE:
163                 return "3d-alternate";
164         case VideoFrameType::THREE_D_LEFT:
165                 return "3d-left";
166         case VideoFrameType::THREE_D_RIGHT:
167                 return "3d-right";
168         default:
169                 DCPOMATIC_ASSERT (false);
170         }
171
172         DCPOMATIC_ASSERT (false);
173 }
174
175 VideoFrameType
176 string_to_video_frame_type (string s)
177 {
178         if (s == "2d") {
179                 return VideoFrameType::TWO_D;
180         } else if (s == "3d") {
181                 return VideoFrameType::THREE_D;
182         } else if (s == "3d-left-right") {
183                 return VideoFrameType::THREE_D_LEFT_RIGHT;
184         } else if (s == "3d-top-bottom") {
185                 return VideoFrameType::THREE_D_TOP_BOTTOM;
186         } else if (s == "3d-alternate") {
187                 return VideoFrameType::THREE_D_ALTERNATE;
188         } else if (s == "3d-left") {
189                 return VideoFrameType::THREE_D_LEFT;
190         } else if (s == "3d-right") {
191                 return VideoFrameType::THREE_D_RIGHT;
192         }
193
194         DCPOMATIC_ASSERT (false);
195 }
196
197 CPLSummary::CPLSummary (boost::filesystem::path p)
198         : dcp_directory (p.leaf().string())
199 {
200         dcp::DCP dcp (p);
201
202         vector<dcp::VerificationNote> notes;
203         dcp.read (&notes);
204         for (auto i: notes) {
205                 if (i.code() != dcp::VerificationNote::Code::EXTERNAL_ASSET) {
206                         /* It's not just a warning about this DCP being a VF */
207                         throw dcp::ReadError(dcp::note_to_string(i));
208                 }
209         }
210
211         cpl_id = dcp.cpls().front()->id();
212         cpl_annotation_text = dcp.cpls().front()->annotation_text();
213         cpl_file = dcp.cpls().front()->file().get();
214
215         encrypted = false;
216         for (auto j: dcp.cpls()) {
217                 for (auto k: j->reel_encryptable_assets()) {
218                         if (k->key_id()) {
219                                 encrypted = true;
220                         }
221                 }
222         }
223
224         boost::system::error_code ec;
225         auto last_write = boost::filesystem::last_write_time (p, ec);
226         last_write_time = ec ? 0 : last_write;
227 }
228
229
230 bool operator== (NamedChannel const& a, NamedChannel const& b)
231 {
232         return a.name == b.name && a.index == b.index;
233 }
234
235
236 string
237 video_range_to_string (VideoRange r)
238 {
239         switch (r) {
240         case VideoRange::FULL:
241                 return "full";
242         case VideoRange::VIDEO:
243                 return "video";
244         default:
245                 DCPOMATIC_ASSERT (false);
246         }
247 }
248
249
250 VideoRange
251 string_to_video_range (string s)
252 {
253         if (s == "full") {
254                 return VideoRange::FULL;
255         } else if (s == "video") {
256                 return VideoRange::VIDEO;
257         }
258
259         DCPOMATIC_ASSERT (false);
260         return VideoRange::FULL;
261 }
262