2 Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
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.
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.
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.
20 /** @file src/lib/file_group.cc
21 * @brief FileGroup class.
26 #include "file_group.h"
27 #include "exceptions.h"
33 /** Construct a FileGroup with no files */
34 FileGroup::FileGroup ()
41 /** Construct a FileGroup with a single file */
42 FileGroup::FileGroup (boost::filesystem::path p)
51 /** Construct a FileGroup with multiple files */
52 FileGroup::FileGroup (vector<boost::filesystem::path> const & p)
61 /** Destroy a FileGroup, closing any open file */
62 FileGroup::~FileGroup ()
65 fclose (_current_file);
70 FileGroup::set_paths (vector<boost::filesystem::path> const & p)
77 /** Ensure that the given path index in the content is the _current_file */
79 FileGroup::ensure_open_path (size_t p) const
81 if (_current_file && _current_path == p) {
87 fclose (_current_file);
91 _current_file = fopen_boost (_paths[_current_path], "rb");
92 if (_current_file == 0) {
93 throw OpenFileError (_paths[_current_path]);
98 FileGroup::seek (int64_t pos, int whence) const
100 /* Convert pos to `full_pos', which is an offset from the start
103 int64_t full_pos = 0;
109 for (size_t i = 0; i < _current_path; ++i) {
110 full_pos += boost::filesystem::file_size (_paths[i]);
112 #ifdef DCPOMATIC_WINDOWS
113 full_pos += _ftelli64 (_current_file);
115 full_pos += ftell (_current_file);
120 full_pos = length() - pos;
124 /* Seek to full_pos */
126 int64_t sub_pos = full_pos;
127 while (i < _paths.size ()) {
128 boost::uintmax_t len = boost::filesystem::file_size (_paths[i]);
129 if (sub_pos < int64_t (len)) {
136 if (i == _paths.size ()) {
140 ensure_open_path (i);
141 dcpomatic_fseek (_current_file, sub_pos, SEEK_SET);
145 /** Try to read some data from the current position into a buffer.
146 * @param buffer Buffer to write data into.
147 * @param amount Number of bytes to read.
148 * @return Number of bytes read, or -1 in the case of error.
151 FileGroup::read (uint8_t* buffer, int amount) const
155 int const this_time = fread (buffer + read, 1, amount - read, _current_file);
157 if (read == amount) {
162 /* See if there is another file to use */
163 if ((_current_path + 1) >= _paths.size()) {
166 ensure_open_path (_current_path + 1);
172 /** @return Combined length of all the files */
174 FileGroup::length () const
177 for (size_t i = 0; i < _paths.size(); ++i) {
178 len += boost::filesystem::file_size (_paths[i]);