A few missing checks on the return value of fopen_boost.
[dcpomatic.git] / src / lib / audio_analysis.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 #include "audio_analysis.h"
21 #include "dcpomatic_assert.h"
22 #include "cross.h"
23 #include <boost/filesystem.hpp>
24 #include <stdint.h>
25 #include <cmath>
26 #include <cassert>
27 #include <cstdio>
28 #include <iostream>
29
30 using std::ostream;
31 using std::istream;
32 using std::string;
33 using std::vector;
34 using std::cout;
35 using std::max;
36 using std::list;
37
38 AudioPoint::AudioPoint ()
39 {
40         for (int i = 0; i < COUNT; ++i) {
41                 _data[i] = 0;
42         }
43 }
44
45 AudioPoint::AudioPoint (FILE* f)
46 {
47         for (int i = 0; i < COUNT; ++i) {
48                 int n = fscanf (f, "%f", &_data[i]);
49                 if (n != 1) {
50                         _data[i] = 0;
51                 }
52         }
53 }
54
55 AudioPoint::AudioPoint (AudioPoint const & other)
56 {
57         for (int i = 0; i < COUNT; ++i) {
58                 _data[i] = other._data[i];
59         }
60 }
61
62 AudioPoint &
63 AudioPoint::operator= (AudioPoint const & other)
64 {
65         if (this == &other) {
66                 return *this;
67         }
68         
69         for (int i = 0; i < COUNT; ++i) {
70                 _data[i] = other._data[i];
71         }
72
73         return *this;
74 }
75
76 void
77 AudioPoint::write (FILE* f) const
78 {
79         for (int i = 0; i < COUNT; ++i) {
80                 fprintf (f, "%f\n", _data[i]);
81         }
82 }
83         
84
85 AudioAnalysis::AudioAnalysis (int channels)
86 {
87         _data.resize (channels);
88 }
89
90 AudioAnalysis::AudioAnalysis (boost::filesystem::path filename)
91 {
92         FILE* f = fopen_boost (filename, "r");
93         if (!f) {
94                 throw OpenFileError (filename);
95         }
96
97         int channels = 0;
98         fscanf (f, "%d", &channels);
99         _data.resize (channels);
100
101         for (int i = 0; i < channels; ++i) {
102                 int points;
103                 fscanf (f, "%d", &points);
104                 if (feof (f)) {
105                         fclose (f);
106                         return;
107                 }
108                 
109                 for (int j = 0; j < points; ++j) {
110                         _data[i].push_back (AudioPoint (f));
111                         if (feof (f)) {
112                                 fclose (f);
113                                 return;
114                         }
115                 }
116         }
117
118         fclose (f);
119 }
120
121 void
122 AudioAnalysis::add_point (int c, AudioPoint const & p)
123 {
124         DCPOMATIC_ASSERT (c < channels ());
125         _data[c].push_back (p);
126 }
127
128 AudioPoint
129 AudioAnalysis::get_point (int c, int p) const
130 {
131         DCPOMATIC_ASSERT (p < points (c));
132         return _data[c][p];
133 }
134
135 int
136 AudioAnalysis::channels () const
137 {
138         return _data.size ();
139 }
140
141 int
142 AudioAnalysis::points (int c) const
143 {
144         DCPOMATIC_ASSERT (c < channels ());
145         return _data[c].size ();
146 }
147
148 void
149 AudioAnalysis::write (boost::filesystem::path filename)
150 {
151         boost::filesystem::path tmp = filename;
152         tmp.replace_extension (".tmp");
153
154         FILE* f = fopen_boost (tmp, "w");
155         if (!f) {
156                 throw OpenFileError (tmp);
157         }
158
159         fprintf (f, "%ld\n", _data.size ());
160         for (vector<vector<AudioPoint> >::iterator i = _data.begin(); i != _data.end(); ++i) {
161                 fprintf (f, "%ld\n", i->size ());
162                 for (vector<AudioPoint>::iterator j = i->begin(); j != i->end(); ++j) {
163                         j->write (f);
164                 }
165         }
166
167         fclose (f);
168         boost::filesystem::rename (tmp, filename);
169 }