Update for new libdcp; add some more formats; fix compile with old boost.
[dcpomatic.git] / src / lib / format.cc
1 /*
2     Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 /** @file src/format.cc
21  *  @brief Class to describe a format (aspect ratio) that a Film should
22  *  be shown in.
23  */
24
25 #include <sstream>
26 #include <cstdlib>
27 #include <cassert>
28 #include <iomanip>
29 #include <iostream>
30 #include "format.h"
31
32 using namespace std;
33
34 vector<Format const *> Format::_formats;
35
36 /** @param r Ratio multiplied by 100 (e.g. 185)
37  *  @param dcp Size (in pixels) of the images that we should put in a DCP.
38  *  @param id ID (e.g. 185)
39  *  @param n Nick name (e.g. Flat)
40  */
41 Format::Format (int r, Size dcp, string id, string n)
42         : _ratio (r)
43         , _dcp_size (dcp)
44         , _id (id)
45         , _nickname (n)
46 {
47
48 }
49
50 /** @return A name to be presented to the user */
51 string
52 Format::name () const
53 {
54         stringstream s;
55         if (!_nickname.empty ()) {
56                 s << _nickname << " (";
57         }
58
59         s << setprecision(3) << (_ratio / 100.0) << ":1";
60
61         if (!_nickname.empty ()) {
62                 s << ")";
63         }
64
65         return s.str ();
66 }
67
68 /** @return Identifier for this format as metadata for a Film's metadata file */
69 string
70 Format::as_metadata () const
71 {
72         return _id;
73 }
74
75 /** Fill our _formats vector with all available formats */
76 void
77 Format::setup_formats ()
78 {
79         _formats.push_back (new Format (119, Size (1285, 1080), "119", "1.19"));
80         _formats.push_back (new Format (133, Size (1436, 1080), "133", "1.33"));
81         _formats.push_back (new Format (138, Size (1485, 1080), "138", "1.375"));
82         _formats.push_back (new Format (133, Size (1998, 1080), "133-in-flat", "4:3 within Flat"));
83         _formats.push_back (new Format (137, Size (1480, 1080), "137", "Academy"));
84         _formats.push_back (new Format (166, Size (1793, 1080), "166", "1.66"));
85         _formats.push_back (new Format (178, Size (1998, 1080), "178-in-flat", "16:9 within Flat"));
86         _formats.push_back (new Format (185, Size (1998, 1080), "185", "Flat"));
87         _formats.push_back (new Format (239, Size (2048, 858), "239", "Scope"));
88 }
89
90 /** @param r Ratio multiplied by 100.
91  *  @return Matching Format, or 0.
92  */
93 Format const *
94 Format::from_ratio (int r)
95 {
96         vector<Format const *>::iterator i = _formats.begin ();
97         while (i != _formats.end() && (*i)->ratio_as_integer() != r) {
98                 ++i;
99         }
100
101         if (i == _formats.end ()) {
102                 return 0;
103         }
104
105         return *i;
106 }
107
108 /** @param n Nickname.
109  *  @return Matching Format, or 0.
110  */
111 Format const *
112 Format::from_nickname (string n)
113 {
114         vector<Format const *>::iterator i = _formats.begin ();
115         while (i != _formats.end() && (*i)->nickname() != n) {
116                 ++i;
117         }
118
119         if (i == _formats.end ()) {
120                 return 0;
121         }
122
123         return *i;
124 }
125
126 /** @param i Id.
127  *  @return Matching Format, or 0.
128  */
129 Format const *
130 Format::from_id (string i)
131 {
132         vector<Format const *>::iterator j = _formats.begin ();
133         while (j != _formats.end() && (*j)->id() != i) {
134                 ++j;
135         }
136
137         if (j == _formats.end ()) {
138                 return 0;
139         }
140
141         return *j;
142 }
143
144
145 /** @param m Metadata, as returned from as_metadata().
146  *  @return Matching Format, or 0.
147  */
148 Format const *
149 Format::from_metadata (string m)
150 {
151         return from_id (m);
152 }
153
154 /** @param f A Format.
155  *  @return Index of f within our static list, or -1.
156  */
157 int
158 Format::as_index (Format const * f)
159 {
160         vector<Format*>::size_type i = 0;
161         while (i < _formats.size() && _formats[i] != f) {
162                 ++i;
163         }
164
165         if (i == _formats.size ()) {
166                 return -1;
167         }
168
169         return i;
170 }
171
172 /** @param i An index returned from as_index().
173  *  @return Corresponding Format.
174  */
175 Format const *
176 Format::from_index (int i)
177 {
178         assert (i >= 0 && i < int(_formats.size ()));
179         return _formats[i];
180 }
181
182 /** @return All available formats */
183 vector<Format const *>
184 Format::all ()
185 {
186         return _formats;
187 }
188
189 int
190 Format::dcp_padding () const
191 {
192         int p = rint ((_dcp_size.width - (_dcp_size.height * _ratio / 100.0)) / 2.0);
193
194         /* This comes out -ve for Scope; bodge it */
195         if (p < 0) {
196                 p = 0;
197         }
198         
199         return p;
200 }