Merge master.
authorCarl Hetherington <cth@carlh.net>
Fri, 29 Nov 2013 21:38:08 +0000 (21:38 +0000)
committerCarl Hetherington <cth@carlh.net>
Fri, 29 Nov 2013 21:38:08 +0000 (21:38 +0000)
1  2 
src/lib/film.cc
src/lib/util.cc
src/lib/wscript
src/tools/dcpomatic.cc
src/wx/film_editor.cc
test/wscript

diff --combined src/lib/film.cc
index d53d61a633217c51e5573cdabfcedf40ab9c7f3f,b1b86898403fdbb62c39b6fe1bc9e42eed0bd9c7..71836f2540fc1fa617241cf2a622fc1e34283527
@@@ -64,8 -64,6 +64,6 @@@ using std::multimap
  using std::pair;
  using std::map;
  using std::vector;
- using std::ifstream;
- using std::ofstream;
  using std::setfill;
  using std::min;
  using std::make_pair;
@@@ -83,7 -81,7 +81,7 @@@ using boost::optional
  using libdcp::Size;
  using libdcp::Signer;
  
 -int const Film::state_version = 4;
 +int const Film::state_version = 5;
  
  /** Construct a Film object in a given directory.
   *
@@@ -374,8 -372,6 +372,8 @@@ Film::read_metadata (
  
        cxml::Document f ("Metadata");
        f.read_file (file ("metadata.xml"));
 +
 +      int const version = f.number_child<int> ("Version");
        
        _name = f.string_child ("Name");
        _use_dci_name = f.bool_child ("UseDCIName");
        _three_d = f.bool_child ("ThreeD");
        _interop = f.bool_child ("Interop");
        _key = libdcp::Key (f.string_child ("Key"));
 -      _playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist"));
 +      _playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist"), version);
  
        _dirty = false;
  }
diff --combined src/lib/util.cc
index 98dec58d7163d15d3614e319ef86408f9099a177,9dffffa9865b033cb190a5ec1ddffcb2a65a56ad..ddc0a297459cef504b49300b25f874752ec2ba64
@@@ -39,6 -39,9 +39,9 @@@
  #include <boost/lexical_cast.hpp>
  #include <boost/thread.hpp>
  #include <boost/filesystem.hpp>
+ #ifdef DCPOMATIC_WINDOWS
+ #include <boost/locale.hpp>
+ #endif
  #include <glib.h>
  #include <openjpeg.h>
  #include <openssl/md5.h>
@@@ -80,7 -83,6 +83,6 @@@ using std::endl
  using std::vector;
  using std::hex;
  using std::setw;
- using std::ifstream;
  using std::ios;
  using std::min;
  using std::max;
@@@ -89,9 -91,7 +91,8 @@@ using std::multimap
  using std::istream;
  using std::numeric_limits;
  using std::pair;
- using std::ofstream;
  using std::cout;
 +using std::streampos;
  using boost::shared_ptr;
  using boost::thread;
  using boost::lexical_cast;
@@@ -261,8 -261,11 +262,11 @@@ seconds (struct timeval t
  LONG WINAPI exception_handler(struct _EXCEPTION_POINTERS *)
  {
        dbg::stack s;
-       ofstream f (backtrace_file.string().c_str());
-       std::copy(s.begin(), s.end(), std::ostream_iterator<dbg::stack_frame>(f, "\n"));
+       FILE* f = fopen_boost (backtrace_file, "w");
+       for (dbg::stack::const_iterator i = s.begin(); i != s.end(); ++i) {
+               fprintf (f, "%p %s %d %s", i->instruction, i->function.c_str(), i->line, i->module.c_str());
+       }
+       fclose (f);
        return EXCEPTION_CONTINUE_SEARCH;
  }
  #endif
@@@ -277,6 -280,21 +281,21 @@@ dcpomatic_setup (
        backtrace_file /= g_get_user_config_dir ();
        backtrace_file /= "backtrace.txt";
        SetUnhandledExceptionFilter(exception_handler);
+       /* Dark voodoo which, I think, gets boost::filesystem::path to
+          correctly convert UTF-8 strings to paths, and also paths
+          back to UTF-8 strings (on path::string()).
+          After this, constructing boost::filesystem::paths from strings
+          converts from UTF-8 to UTF-16 inside the path.  Then
+          path::string().c_str() gives UTF-8 and
+          path::c_str()          gives UTF-16.
+          This is all Windows-only.  AFAICT Linux/OS X use UTF-8 everywhere,
+          so things are much simpler.
+       */
+       std::locale::global (boost::locale::generator().generate (""));
+       boost::filesystem::path::imbue (std::locale ());
  #endif        
        
        avfilter_register_all ();
@@@ -387,42 -405,82 +406,42 @@@ md5_digest (void const * data, int size
        return s.str ();
  }
  
 -/** @param file File name.
 - *  @return MD5 digest of file's contents.
 - */
 -string
 -md5_digest (boost::filesystem::path file)
 -{
 -      FILE* f = fopen_boost (file, "rb");
 -      if (!f) {
 -              throw OpenFileError (file.string());
 -      }
 -
 -      boost::uintmax_t bytes = boost::filesystem::file_size (file);
 -
 -      boost::uintmax_t const buffer_size = 64 * 1024;
 -      char buffer[buffer_size];
 -
 -      MD5_CTX md5_context;
 -      MD5_Init (&md5_context);
 -      while (bytes > 0) {
 -              int const t = min (bytes, buffer_size);
 -              fread (buffer, 1, t, f);
 -              MD5_Update (&md5_context, buffer, t);
 -              bytes -= t;
 -      }
 -
 -      unsigned char digest[MD5_DIGEST_LENGTH];
 -      MD5_Final (digest, &md5_context);
 -      fclose (f);
 -
 -      stringstream s;
 -      for (int i = 0; i < MD5_DIGEST_LENGTH; ++i) {
 -              s << std::hex << std::setfill('0') << std::setw(2) << ((int) digest[i]);
 -      }
 -
 -      return s.str ();
 -}
 -
  /** @param job Optional job for which to report progress */
  string
 -md5_digest_directory (boost::filesystem::path directory, shared_ptr<Job> job)
 +md5_digest (vector<boost::filesystem::path> files, shared_ptr<Job> job)
  {
-       int const buffer_size = 64 * 1024;
+       boost::uintmax_t const buffer_size = 64 * 1024;
        char buffer[buffer_size];
  
        MD5_CTX md5_context;
        MD5_Init (&md5_context);
  
 -      int files = 0;
 -      if (job) {
 -              for (boost::filesystem::directory_iterator i(directory); i != boost::filesystem::directory_iterator(); ++i) {
 -                      ++files;
 -              }
 +      vector<int64_t> sizes;
 +      for (size_t i = 0; i < files.size(); ++i) {
 +              sizes.push_back (boost::filesystem::file_size (files[i]));
        }
  
 -      int j = 0;
 -      for (boost::filesystem::directory_iterator i(directory); i != boost::filesystem::directory_iterator(); ++i) {
 -              FILE* f = fopen_boost (i->path(), "rb");
 +      for (size_t i = 0; i < files.size(); ++i) {
-               ifstream f (files[i].string().c_str(), std::ios::binary);
-               if (!f.good ()) {
++              FILE* f = fopen_boost (files[i], "rb");
+               if (!f) {
 -                      throw OpenFileError (i->path().string());
 +                      throw OpenFileError (files[i].string());
                }
-       
-               f.seekg (0, std::ios::end);
-               streampos const bytes = f.tellg ();
-               f.seekg (0, std::ios::beg);
  
-               streampos remaining = bytes;
 -              boost::uintmax_t bytes = boost::filesystem::file_size (i->path ());
++              boost::uintmax_t const bytes = boost::filesystem::file_size (files[i]);
++              boost::uintmax_t remaining = bytes;
 -              while (bytes > 0) {
 -                      int const t = min (bytes, buffer_size);
 +              while (remaining > 0) {
-                       int const t = min (remaining, streampos (buffer_size));
-                       f.read (buffer, t);
++                      int const t = min (remaining, buffer_size);
+                       fread (buffer, 1, t, f);
                        MD5_Update (&md5_context, buffer, t);
 -                      bytes -= t;
 -              }
 +                      remaining -= t;
  
 -              if (job) {
 -                      job->set_progress (float (j) / files);
 -                      ++j;
 +                      if (job) {
 +                              job->set_progress ((float (i) + 1 - float(remaining) / bytes) / files.size ());
 +                      }
                }
+               fclose (f);
        }
  
        unsigned char digest[MD5_DIGEST_LENGTH];
diff --combined src/lib/wscript
index ebd316a0c174b88420d05b95fb64aeb432532587,5098d406927d895513af5f5c5ce513ae95d383e5..1699c5ec8c6b5c1b9f782a3cf718dfcbdca8049e
@@@ -22,7 -22,6 +22,7 @@@ sources = ""
            encoder.cc
            examine_content_job.cc
            exceptions.cc
 +          file_group.cc
            filter_graph.cc
            ffmpeg.cc
            ffmpeg_content.cc
            film.cc
            filter.cc
            image.cc
 +          image_content.cc
 +          image_decoder.cc
 +          image_examiner.cc
            job.cc
            job_manager.cc
            kdm.cc
            log.cc
 -          moving_image_content.cc
 -          moving_image_decoder.cc
 -          moving_image_examiner.cc
            player.cc
            playlist.cc
            ratio.cc
@@@ -49,6 -48,9 +49,6 @@@
            sndfile_content.cc
            sndfile_decoder.cc
            sound_processor.cc
 -          still_image_content.cc
 -          still_image_decoder.cc
 -          still_image_examiner.cc
            subtitle_content.cc
            subtitle_decoder.cc
            timer.cc
@@@ -72,7 -74,7 +72,7 @@@ def build(bld)
      obj.export_includes = ['..']
      obj.uselib = """
                   AVCODEC AVUTIL AVFORMAT AVFILTER SWSCALE SWRESAMPLE 
-                  BOOST_FILESYSTEM BOOST_THREAD BOOST_DATETIME BOOST_SIGNALS2 
+                  BOOST_FILESYSTEM BOOST_THREAD BOOST_DATETIME BOOST_SIGNALS2
                   SNDFILE OPENJPEG POSTPROC TIFF MAGICK SSH DCP CXML GLIB LZMA XML++
                   CURL ZIP QUICKMAIL
                   """
@@@ -80,7 -82,7 +80,7 @@@
      obj.source = sources + ' version.cc'
  
      if bld.env.TARGET_WINDOWS:
-         obj.uselib += ' WINSOCK2 BFD DBGHELP IBERTY SHLWAPI MSWSOCK'
+         obj.uselib += ' WINSOCK2 BFD DBGHELP IBERTY SHLWAPI MSWSOCK BOOST_LOCALE'
          obj.source += ' stack.cpp'
      if bld.env.STATIC:
          obj.uselib += ' XML++'
diff --combined src/tools/dcpomatic.cc
index a4239bd2160e40861d6c47912d65c9e42aecb21c,2a0cb9cd36935a1ae53d67fafd60e8d92578b7c6..b4ec1d77da9d754db678c75e191e93af9ddba35a
@@@ -62,7 -62,6 +62,6 @@@ using std::map
  using std::make_pair;
  using std::list;
  using std::exception;
- using std::ofstream;
  using boost::shared_ptr;
  using boost::dynamic_pointer_cast;
  
@@@ -246,8 -245,23 +245,24 @@@ public
        Frame (wxString const & title)
                : wxFrame (NULL, -1, title)
                , _servers_list_dialog (0)
 +              , _hints_dialog (0)
        {
+ #ifdef DCPOMATIC_WINDOWS_CONSOLE              
+                 AllocConsole();
+               
+               HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);
+               int hCrt = _open_osfhandle((intptr_t) handle_out, _O_TEXT);
+               FILE* hf_out = _fdopen(hCrt, "w");
+               setvbuf(hf_out, NULL, _IONBF, 1);
+               *stdout = *hf_out;
+               
+               HANDLE handle_in = GetStdHandle(STD_INPUT_HANDLE);
+               hCrt = _open_osfhandle((intptr_t) handle_in, _O_TEXT);
+               FILE* hf_in = _fdopen(hCrt, "r");
+               setvbuf(hf_in, NULL, _IONBF, 128);
+               *stdin = *hf_in;
+ #endif
                wxMenuBar* bar = new wxMenuBar;
                setup_menu (bar);
                SetMenuBar (bar);
@@@ -333,7 -347,7 +348,7 @@@ private
                                            std_to_wx (
                                                    String::compose (wx_to_std (_("The directory %1 already exists and is not empty.  "
                                                                                  "Are you sure you want to use it?")),
-                                                                    d->get_path().c_str())
+                                                                    d->get_path().string().c_str())
                                                    )
                                            )) {
                                        return;
diff --combined src/wx/film_editor.cc
index 99d607731a6cb4372ac945903e72fd6663a54986,92fb9d0f37839df840f4035c979e6c178aefafeb..bf13620e53bd31b62d099a7f6769e050504e05e6
@@@ -36,7 -36,8 +36,7 @@@
  #include "lib/filter.h"
  #include "lib/ratio.h"
  #include "lib/config.h"
 -#include "lib/still_image_content.h"
 -#include "lib/moving_image_content.h"
 +#include "lib/image_content.h"
  #include "lib/ffmpeg_content.h"
  #include "lib/sndfile_content.h"
  #include "lib/dcp_content_type.h"
@@@ -150,7 -151,7 +150,7 @@@ FilmEditor::make_dcp_panel (
        }
        ++r;
  
-       _encrypted = new wxCheckBox (_dcp_panel, wxID_ANY, wxT ("Encrypted"));
+       _encrypted = new wxCheckBox (_dcp_panel, wxID_ANY, _("Encrypted"));
        grid->Add (_encrypted, wxGBPosition (r, 0), wxGBSpan (1, 2));
        ++r;
  
@@@ -730,11 -731,14 +730,14 @@@ FilmEditor::setup_content (
  void
  FilmEditor::content_add_file_clicked ()
  {
-       wxFileDialog* d = new wxFileDialog (this, _("Choose a file or files"), wxT (""), wxT (""), wxT ("*.*"), wxFD_MULTIPLE);
+       /* The wxFD_CHANGE_DIR here prevents a `could not set working directory' error 123 on Windows when using
+          non-Latin filenames or paths.
+       */
+       wxFileDialog* d = new wxFileDialog (this, _("Choose a file or files"), wxT (""), wxT (""), wxT ("*.*"), wxFD_MULTIPLE | wxFD_CHANGE_DIR);
        int const r = d->ShowModal ();
-       d->Destroy ();
  
        if (r != wxID_OK) {
+               d->Destroy ();
                return;
        }
  
        /* XXX: check for lots of files here and do something */
  
        for (unsigned int i = 0; i < paths.GetCount(); ++i) {
-               _film->examine_and_add_content (content_factory (_film, wx_to_std (paths[i])));
+               _film->examine_and_add_content (content_factory (_film, wx_to_std (d->GetPath ())));
        }
+       d->Destroy ();
  }
  
  void
@@@ -760,8 -766,8 +765,8 @@@ FilmEditor::content_add_folder_clicked 
        }
  
        _film->examine_and_add_content (
 -              shared_ptr<MovingImageContent> (
 -                      new MovingImageContent (_film, boost::filesystem::path (wx_to_std (d->GetPath ())))
 +              shared_ptr<ImageContent> (
 +                      new ImageContent (_film, boost::filesystem::path (wx_to_std (d->GetPath ())))
                        )
                );
  }
@@@ -820,9 -826,7 +825,9 @@@ FilmEditor::selected_content (
                        break;
                }
  
 -              sel.push_back (_film->content()[s]);
 +              if (s < int (_film->content().size ())) {
 +                      sel.push_back (_film->content()[s]);
 +              }
        }
  
        return sel;
diff --combined test/wscript
index 5a11149040381650393df0815487f7e233fcb0c5,76de63a523098f613d80770bfe0e67efd69e4285..4ae49b087a05b32c3dfac078a4dbfaaddcb4896b
@@@ -15,32 -15,32 +15,33 @@@ def build(bld)
      obj.uselib = 'BOOST_TEST DCP OPENJPEG AVFORMAT AVFILTER AVCODEC AVUTIL SWSCALE POSTPROC CXML'
      obj.use    = 'libdcpomatic'
      obj.source = """
 -                 test.cc
 +                 4k_test.cc
+                  audio_analysis_test.cc
 -                 scaling_test.cc
 -                 film_metadata_test.cc
 -                 frame_rate_test.cc
 -                 colour_conversion_test.cc
                   audio_delay_test.cc
 -                 silence_padding_test.cc
                   audio_merger_test.cc
 -                 resampler_test.cc
 +                 black_fill_test.cc
 +                 client_server_test.cc
 +                 colour_conversion_test.cc
                   ffmpeg_audio_test.cc
 -                 threed_test.cc
 -                 play_test.cc
 -                 ffmpeg_pts_offset.cc
 +                 ffmpeg_dcp_test.cc
                   ffmpeg_examiner_test.cc
 -                 black_fill_test.cc
 -                 ratio_test.cc
 -                 pixel_formats_test.cc
 +                 ffmpeg_pts_offset.cc
 +                 file_group_test.cc
 +                 film_metadata_test.cc
 +                 frame_rate_test.cc
 +                 image_test.cc
 +                 job_test.cc
                   make_black_test.cc
 +                 pixel_formats_test.cc
 +                 play_test.cc
 +                 ratio_test.cc
 +                 resampler_test.cc
 +                 scaling_test.cc
 +                 silence_padding_test.cc
                   stream_test.cc
 +                 test.cc
 +                 threed_test.cc
                   util_test.cc
 -                 ffmpeg_dcp_test.cc
 -                 job_test.cc
 -                 client_server_test.cc
 -                 image_test.cc
 -                 4k_test.cc
                   """
  
      obj.target = 'unit-tests'