Rename Content::_file to path and support md5sums of directories.
authorCarl Hetherington <cth@carlh.net>
Wed, 24 Jul 2013 09:32:52 +0000 (10:32 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 24 Jul 2013 09:32:52 +0000 (10:32 +0100)
14 files changed:
src/lib/analyse_audio_job.cc
src/lib/content.cc
src/lib/content.h
src/lib/ffmpeg.cc
src/lib/ffmpeg_content.cc
src/lib/sndfile_content.cc
src/lib/sndfile_decoder.cc
src/lib/still_image_content.cc
src/lib/still_image_decoder.cc
src/lib/still_image_examiner.cc
src/lib/util.cc
src/lib/util.h
src/wx/audio_dialog.cc
src/wx/timeline.cc

index 3902ec537a6bde1985acaff6d7de303ddb99b9d5..df67b37d6144ea48740bd9fe2275de9d3b380072 100644 (file)
@@ -50,7 +50,7 @@ AnalyseAudioJob::name () const
                return "";
        }
        
-       return String::compose (_("Analyse audio of %1"), content->file().filename());
+       return String::compose (_("Analyse audio of %1"), content->path());
 }
 
 void
index 0db93d5e358622a33f4aa73127e2e30ff7b5331d..372be30205fa2dfa857ff6f080383ed0c31a0e44 100644 (file)
@@ -43,7 +43,7 @@ Content::Content (shared_ptr<const Film> f, Time s)
 
 Content::Content (shared_ptr<const Film> f, boost::filesystem::path p)
        : _film (f)
-       , _file (p)
+       , _path (p)
        , _start (0)
        , _change_signals_frequent (false)
 {
@@ -54,7 +54,7 @@ Content::Content (shared_ptr<const Film> f, shared_ptr<const cxml::Node> node)
        : _film (f)
        , _change_signals_frequent (false)
 {
-       _file = node->string_child ("File");
+       _path = node->string_child ("Path");
        _digest = node->string_child ("Digest");
        _start = node->number_child<Time> ("Start");
 }
@@ -63,7 +63,7 @@ void
 Content::as_xml (xmlpp::Node* node) const
 {
        boost::mutex::scoped_lock lm (_mutex);
-       node->add_child("File")->add_child_text (_file.string());
+       node->add_child("Path")->add_child_text (_path.string());
        node->add_child("Digest")->add_child_text (_digest);
        node->add_child("Start")->add_child_text (lexical_cast<string> (_start));
 }
@@ -71,7 +71,13 @@ Content::as_xml (xmlpp::Node* node) const
 void
 Content::examine (shared_ptr<Job>)
 {
-       string const d = md5_digest (_file);
+       string d;
+       if (boost::filesystem::is_regular_file (_path)) {
+               d = md5_digest (_path);
+       } else {
+               d = md5_digest_directory (_path);
+       }
+       
        boost::mutex::scoped_lock lm (_mutex);
        _digest = d;
 }
@@ -113,5 +119,5 @@ Content::clone () const
 string
 Content::technical_summary () const
 {
-       return String::compose ("%1 %2 %3", file(), digest(), start());
+       return String::compose ("%1 %2 %3", path(), digest(), start());
 }
index 33af0a6246d73743ac97f5cda295e00a8b60ebd4..78b80e2540ec35cdc5f03dfb0ea4c8679249a46f 100644 (file)
@@ -59,12 +59,12 @@ public:
 
        boost::shared_ptr<Content> clone () const;
        
-       boost::filesystem::path file () const {
+       boost::filesystem::path path () const {
                boost::mutex::scoped_lock lm (_mutex);
-               return _file;
+               return _path;
        }
 
-       /** @return MD5 digest of the content's file */
+       /** @return MD5 digest of the content's file(s) */
        std::string digest () const {
                boost::mutex::scoped_lock lm (_mutex);
                return _digest;
@@ -94,7 +94,8 @@ protected:
        mutable boost::mutex _mutex;
 
 private:
-       boost::filesystem::path _file;
+       /** Path of a file or a directory containing files */
+       boost::filesystem::path _path;
        std::string _digest;
        Time _start;
        bool _change_signals_frequent;
index 77bf7501840afb8213bd613c7d63b67c6981ecd4..c97b79a719bb6b540971c324bc906bdffca644ab 100644 (file)
@@ -68,8 +68,8 @@ FFmpeg::setup_general ()
 {
        av_register_all ();
 
-       if (avformat_open_input (&_format_context, _ffmpeg_content->file().string().c_str(), 0, 0) < 0) {
-               throw OpenFileError (_ffmpeg_content->file().string ());
+       if (avformat_open_input (&_format_context, _ffmpeg_content->path().string().c_str(), 0, 0) < 0) {
+               throw OpenFileError (_ffmpeg_content->path().string ());
        }
 
        if (avformat_find_stream_info (_format_context, 0) < 0) {
index 00499cf135a737be9672cfec85b503485bc9bf49..901cb53cf6ac8454995745703866e2af32c668d8 100644 (file)
@@ -166,7 +166,7 @@ FFmpegContent::examine (shared_ptr<Job> job)
 string
 FFmpegContent::summary () const
 {
-       return String::compose (_("%1 [movie]"), file().filename().string());
+       return String::compose (_("%1 [movie]"), path());
 }
 
 string
index ee55ede91f34228df06ed89f77dc6c58500c43c9..713b80dcb331d815f7c30e0dabdea25389c651cc 100644 (file)
@@ -55,7 +55,7 @@ SndfileContent::SndfileContent (shared_ptr<const Film> f, shared_ptr<const cxml:
 string
 SndfileContent::summary () const
 {
-       return String::compose (_("%1 [audio]"), file().filename().string());
+       return String::compose (_("%1 [audio]"), path().filename().string());
 }
 
 string
index bfa163c6c6c7f41696543e582c44aca9ac56d736..1fc1ecaf2cc66c1cbcb650f0af9cad0f0d2a82fc 100644 (file)
@@ -40,7 +40,7 @@ SndfileDecoder::SndfileDecoder (shared_ptr<const Film> f, shared_ptr<const Sndfi
        , _deinterleave_buffer (0)
 {
        _info.format = 0;
-       _sndfile = sf_open (_sndfile_content->file().string().c_str(), SFM_READ, &_info);
+       _sndfile = sf_open (_sndfile_content->path().string().c_str(), SFM_READ, &_info);
        if (!_sndfile) {
                throw DecodeError (_("could not open audio file for reading"));
        }
index 804a5c0f6d559186ee470485f7e97a58705bf0b1..e829e205d49b3cbe04442e9bca3710840de26d0b 100644 (file)
@@ -48,7 +48,7 @@ StillImageContent::StillImageContent (shared_ptr<const Film> f, shared_ptr<const
 string
 StillImageContent::summary () const
 {
-       return String::compose (_("%1 [still]"), file().filename().string());
+       return String::compose (_("%1 [still]"), path());
 }
 
 string
index 10e34427bc45edba311724650530d09111720c02..1dd68463947f36c142dd1d6b81edf2d281302071 100644 (file)
@@ -52,7 +52,7 @@ StillImageDecoder::pass ()
                return;
        }
 
-       Magick::Image* magick_image = new Magick::Image (_still_image_content->file().string ());
+       Magick::Image* magick_image = new Magick::Image (_still_image_content->path().string ());
        _video_size = libdcp::Size (magick_image->columns(), magick_image->rows());
        
        _image.reset (new Image (PIX_FMT_RGB24, _video_size.get(), false));
index 07848d7b9870198647568f7959a0c9c63a9ecc32..5f45d63650bb33bbf6eb5d6883edbec2082611ff 100644 (file)
@@ -33,7 +33,7 @@ StillImageExaminer::StillImageExaminer (shared_ptr<const Film> f, shared_ptr<con
        , _film (f)
 {
        using namespace MagickCore;
-       Magick::Image* image = new Magick::Image (_still_image_content->file().string());
+       Magick::Image* image = new Magick::Image (_still_image_content->path().string());
        _video_size = libdcp::Size (image->columns(), image->rows());
        delete image;
 }
index 7e7e579a4b5ac4d20bef402c43bec455ea05021d..affbe3b002db82d96cbf2064a279e289f1cf01e5 100644 (file)
@@ -407,6 +407,44 @@ md5_digest (boost::filesystem::path file)
        return s.str ();
 }
 
+string
+md5_digest_directory (boost::filesystem::path directory)
+{
+       int const buffer_size = 64 * 1024;
+       char buffer[buffer_size];
+
+       MD5_CTX md5_context;
+       MD5_Init (&md5_context);
+       
+       for (boost::filesystem::directory_iterator i(directory); i != boost::filesystem::directory_iterator(); ++i) {
+               ifstream f (i->path().string().c_str(), std::ios::binary);
+               if (!f.good ()) {
+                       throw OpenFileError (i->path().string());
+               }
+       
+               f.seekg (0, std::ios::end);
+               int bytes = f.tellg ();
+               f.seekg (0, std::ios::beg);
+
+               while (bytes > 0) {
+                       int const t = min (bytes, buffer_size);
+                       f.read (buffer, t);
+                       MD5_Update (&md5_context, buffer, t);
+                       bytes -= t;
+               }
+       }
+
+       unsigned char digest[MD5_DIGEST_LENGTH];
+       MD5_Final (digest, &md5_context);
+
+       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 ();
+}
+
 static bool
 about_equal (float a, float b)
 {
index 4888a023f2bf6359f607206029fa5c17e1192b1c..65fb3d0dd25bd8318d738f0d10821000fe6e9875 100644 (file)
@@ -63,6 +63,7 @@ extern void dcpomatic_setup ();
 extern void dcpomatic_setup_gettext_i18n (std::string);
 extern std::vector<std::string> split_at_spaces_considering_quotes (std::string);
 extern std::string md5_digest (boost::filesystem::path);
+extern std::string md5_digest_directory (boost::filesystem::path);
 extern std::string md5_digest (void const *, int);
 extern void ensure_ui_thread ();
 extern std::string audio_channel_name (int);
index 22e09cc7a8c1988973c21011a2027f064803ad38..d885e2d4d08148635a0e4aaf3b37825e32f7e0ce 100644 (file)
@@ -94,7 +94,7 @@ AudioDialog::set_content (shared_ptr<AudioContent> c)
 
        _content_changed_connection = _content->Changed.connect (bind (&AudioDialog::content_changed, this, _2));
 
-       SetTitle (wxString::Format (_("DCP-o-matic audio - %s"), std_to_wx(_content->file().filename().string()).data()));
+       SetTitle (wxString::Format (_("DCP-o-matic audio - %s"), std_to_wx(_content->path().filename().string()).data()));
 }
 
 void
index 7227fcffc2ab598edc81cc34cd6ab0e6f5680210..90fcf8d5c74c26340a3f60e5371023e505a0c801 100644 (file)
@@ -156,7 +156,7 @@ private:
                gc->StrokePath (path);
                gc->FillPath (path);
 
-               wxString name = wxString::Format (wxT ("%s [%s]"), std_to_wx (cont->file().filename().string()).data(), type().data());
+               wxString name = wxString::Format (wxT ("%s [%s]"), std_to_wx (cont->path().filename().string()).data(), type().data());
                wxDouble name_width;
                wxDouble name_height;
                wxDouble name_descent;