Remove the "simple" UI (#1868).
[dcpomatic.git] / src / lib / file_group.cc
index c2ff047af3d955c539384a5ed8105b977aa2c4cb..9863a21cbd37617c5f69fa14be7aae7bb5b55dc5 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-2018 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
  *  @brief FileGroup class.
  */
 
-#include <cstdio>
-#include <sndfile.h>
 #include "file_group.h"
 #include "exceptions.h"
 #include "cross.h"
+#include "compose.hpp"
+#include <sndfile.h>
+#include <cstdio>
 #include <iostream>
 
 using std::vector;
@@ -36,6 +37,7 @@ using std::cout;
 FileGroup::FileGroup ()
        : _current_path (0)
        , _current_file (0)
+       , _current_size (0)
 {
 
 }
@@ -44,6 +46,7 @@ FileGroup::FileGroup ()
 FileGroup::FileGroup (boost::filesystem::path p)
        : _current_path (0)
        , _current_file (0)
+       , _current_size (0)
 {
        _paths.push_back (p);
        ensure_open_path (0);
@@ -92,8 +95,9 @@ FileGroup::ensure_open_path (size_t p) const
        _current_path = p;
        _current_file = fopen_boost (_paths[_current_path], "rb");
        if (_current_file == 0) {
-               throw OpenFileError (_paths[_current_path], errno, true);
+               throw OpenFileError (_paths[_current_path], errno, OpenFileError::READ);
        }
+       _current_size = boost::filesystem::file_size (_paths[_current_path]);
 }
 
 int64_t
@@ -147,25 +151,39 @@ FileGroup::seek (int64_t pos, int whence) const
 /** Try to read some data from the current position into a buffer.
  *  @param buffer Buffer to write data into.
  *  @param amount Number of bytes to read.
- *  @return Number of bytes read, or -1 in the case of error.
+ *  @return Number of bytes read.
  */
 int
 FileGroup::read (uint8_t* buffer, int amount) const
 {
        int read = 0;
        while (true) {
-               int const this_time = fread (buffer + read, 1, amount - read, _current_file);
+               int64_t to_read = amount - read;
+#ifdef DCPOMATIC_WINDOWS
+               /* If we over-read from the file by too much on Windows we get a errno=22 rather than an feof condition,
+                * for unknown reasons.  So if we're going to over-read, we need to do it by a little bit, so that feof
+                * still gets triggered but there is no errno=22.
+                */
+               to_read = std::min(to_read, static_cast<int64_t>(_current_size - _ftelli64(_current_file) + 1));
+#endif
+               int const this_time = fread (buffer + read, 1, to_read, _current_file);
                read += this_time;
                if (read == amount) {
                        /* Done */
                        break;
                }
 
-               /* See if there is another file to use */
-               if ((_current_path + 1) >= _paths.size()) {
-                       break;
+               if (ferror(_current_file)) {
+                       throw FileError (String::compose("fread error %1", errno), _paths[_current_path]);
+               }
+
+               if (feof (_current_file)) {
+                       /* See if there is another file to use */
+                       if ((_current_path + 1) >= _paths.size()) {
+                               break;
+                       }
+                       ensure_open_path (_current_path + 1);
                }
-               ensure_open_path (_current_path + 1);
        }
 
        return read;