Merge master.
authorCarl Hetherington <cth@carlh.net>
Tue, 16 Apr 2013 10:43:29 +0000 (11:43 +0100)
committerCarl Hetherington <cth@carlh.net>
Tue, 16 Apr 2013 10:43:29 +0000 (11:43 +0100)
14 files changed:
ChangeLog
src/lib/film.cc
src/lib/film.h
src/lib/po/sv_SE.po
src/lib/trimmer.cc [new file with mode: 0644]
src/lib/trimmer.h [new file with mode: 0644]
src/lib/writer.cc
src/lib/wscript
src/tools/dcpomatic.cc
src/wx/config_dialog.cc
src/wx/film_editor.cc
src/wx/film_editor.h
test/metadata.ref
test/test.cc

index 833aa085da7db137c70e73198e624c765c6aa05c..3499d97ed1fb42c94b6faf5b2d6162e6f9624116 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2013-04-15  Carl Hetherington  <cth@carlh.net>
+
+       * Fix error message on forcing language to English (#103).
+
+2013-04-13  Carl Hetherington  <cth@carlh.net>
+
+       * Use film-name-derived names for MXFs in DCPs (#54).
+
 2013-04-10  Carl Hetherington  <cth@carlh.net>
 
        * Version 0.83 released.
index 67605ffcaba2c6836fd69be1be20d7202db5792a..c8aee7a0aa6bdf6bc6b925209a6ae92043f72098 100644 (file)
@@ -98,6 +98,7 @@ Film::Film (string d, bool must_exist)
        , _scaler (Scaler::from_id ("bicubic"))
        , _trim_start (0)
        , _trim_end (0)
+       , _trim_type (CPL)
        , _ab (false)
        , _audio_gain (0)
        , _audio_delay (0)
@@ -165,6 +166,7 @@ Film::Film (Film const & o)
        , _scaler            (o._scaler)
        , _trim_start        (o._trim_start)
        , _trim_end          (o._trim_end)
+       , _trim_type         (o._trim_type)
        , _ab                (o._ab)
        , _audio_gain        (o._audio_gain)
        , _audio_delay       (o._audio_delay)
@@ -223,18 +225,46 @@ Film::info_dir () const
 }
 
 string
-Film::video_mxf_dir () const
+Film::internal_video_mxf_dir () const
 {
        boost::filesystem::path p;
        return dir ("video");
 }
 
 string
-Film::video_mxf_filename () const
+Film::internal_video_mxf_filename () const
 {
        return video_state_identifier() + ".mxf";
 }
 
+string
+Film::dcp_video_mxf_filename () const
+{
+       return filename_safe_name() + "_video.mxf";
+}
+
+string
+Film::dcp_audio_mxf_filename () const
+{
+       return filename_safe_name() + "_audio.mxf";
+}
+
+string
+Film::filename_safe_name () const
+{
+       string const n = name ();
+       string o;
+       for (size_t i = 0; i < n.length(); ++i) {
+               if (isalnum (n[i])) {
+                       o += n[i];
+               } else {
+                       o += "_";
+               }
+       }
+
+       return o;
+}
+
 string
 Film::audio_analysis_path () const
 {
@@ -385,12 +415,23 @@ Film::write_metadata () const
        root->add_child("Name")->add_child_text (_name);
        root->add_child("UseDCIName")->add_child_text (_use_dci_name ? "1" : "0");
        root->add_child("TrustContentHeaders")->add_child_text (_trust_content_headers ? "1" : "0");
+
        if (_dcp_content_type) {
                root->add_child("DCPContentType")->add_child_text (_dcp_content_type->dci_name ());
        }
+
        if (_format) {
                root->add_child("Format")->add_child_text (_format->id ());
        }
+
+       switch (_trim_type) {
+       case CPL:
+               root->add_child("TrimType")->add_child_text ("CPL");
+               break;
+       case ENCODE:
+               root->add_child("TrimType")->add_child_text ("Encode");
+       }
+                       
        root->add_child("LeftCrop")->add_child_text (boost::lexical_cast<string> (_crop.left));
        root->add_child("RightCrop")->add_child_text (boost::lexical_cast<string> (_crop.right));
        root->add_child("TopCrop")->add_child_text (boost::lexical_cast<string> (_crop.top));
@@ -455,6 +496,15 @@ Film::read_metadata ()
                }
        }
 
+       {
+               optional<string> c = f.optional_string_child ("TrimType");
+               if (!c || c.get() == "CPL") {
+                       _trim_type = CPL;
+               } else if (c && c.get() == "Encode") {
+                       _trim_type = ENCODE;
+               }
+       }
+
        _crop.left = f.number_child<int> ("LeftCrop");
        _crop.right = f.number_child<int> ("RightCrop");
        _crop.top = f.number_child<int> ("TopCrop");
@@ -847,6 +897,16 @@ Film::set_trim_end (int t)
        signal_changed (TRIM_END);
 }
 
+void
+Film::set_trim_type (TrimType t)
+{
+       {
+               boost::mutex::scoped_lock lm (_state_mutex);
+               _trim_type = t;
+       }
+       signal_changed (TRIM_TYPE);
+}
+
 void
 Film::set_ab (bool a)
 {
index ffa5d0690ef108a23a78773d660be03b62599bf8..071f474aca6f645a097dee2360e88e0a05cc6141 100644 (file)
@@ -63,11 +63,14 @@ public:
        std::string info_dir () const;
        std::string j2c_path (int f, bool t) const;
        std::string info_path (int f) const;
-       std::string video_mxf_dir () const;
-       std::string video_mxf_filename () const;
+       std::string internal_video_mxf_dir () const;
+       std::string internal_video_mxf_filename () const;
        std::string audio_analysis_path () const;
 
        void examine_content (boost::shared_ptr<Content>);
+       std::string dcp_video_mxf_filename () const;
+       std::string dcp_audio_mxf_filename () const;
+
        void analyse_audio ();
        void send_dcp_to_tms ();
        void make_dcp ();
@@ -120,6 +123,11 @@ public:
        void set_ffmpeg_subtitle_stream (FFmpegSubtitleStream);
        void set_ffmpeg_audio_stream (FFmpegAudioStream);
 
+       enum TrimType {
+               CPL,
+               ENCODE
+       };
+
        /** Identifiers for the parts of our state;
            used for signalling changes.
        */
@@ -138,6 +146,7 @@ public:
                TRIM_START,
                TRIM_END,
                AB,
+               TRIM_TYPE,
                AUDIO_GAIN,
                AUDIO_DELAY,
                WITH_SUBTITLES,
@@ -213,6 +222,11 @@ public:
                return _trim_end;
        }
 
+       TrimType trim_type () const {
+               boost::mutex::scoped_lock lm (_state_mutex);
+               return _trim_type;
+       }
+
        bool ab () const {
                boost::mutex::scoped_lock lm (_state_mutex);
                return _ab;
@@ -290,6 +304,7 @@ public:
        void set_trim_start (int);
        void set_trim_end (int);
        void set_ab (bool);
+       void set_trim_type (TrimType);
        void set_audio_gain (float);
        void set_audio_delay (int);
        void set_with_subtitles (bool);
@@ -322,6 +337,7 @@ private:
        void content_changed (boost::weak_ptr<Content>, int);
        boost::shared_ptr<FFmpegContent> ffmpeg () const;
        void setup_default_audio_mapping ();
+       std::string filename_safe_name () const;
 
        /** Log to write to */
        boost::shared_ptr<Log> _log;
@@ -356,6 +372,7 @@ private:
        int _trim_start;
        /** Frames to trim off the end of the DCP */
        int _trim_end;
+       TrimType _trim_type;
        /** true to create an A/B comparison DCP, where the left half of the image
            is the video without any filters or post-processing, and the right half
            has the specified filters and post-processing.
index c8695ce4dc24423fe05676e05d14a86e7d203ed8..f89874e35e9b952399a227c4f8999a2bbec2d025 100644 (file)
@@ -8,10 +8,9 @@ msgstr ""
 "Project-Id-Version: DCP-o-matic\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2013-04-09 11:14+0100\n"
-"PO-Revision-Date: 2013-04-09 10:13+0100\n"
+"PO-Revision-Date: 2013-04-10 15:35+0100\n"
 "Last-Translator: Adam Klotblixt <adam.klotblixt@gmail.com>\n"
 "Language-Team: \n"
-"Language: \n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
@@ -50,9 +49,8 @@ msgid "16:9 within Flat"
 msgstr "16:9 innanför Flat"
 
 #: src/lib/format.cc:115
-#, fuzzy
 msgid "16:9 within Scope"
-msgstr "16:9 innanför Flat"
+msgstr "16:9 innanför Scope"
 
 #: src/lib/filter.cc:88
 msgid "3D denoiser"
@@ -76,7 +74,7 @@ msgstr "Reklam"
 
 #: src/lib/job.cc:72
 msgid "An error occurred whilst handling the file %1."
-msgstr "Ett fel inträffade vid hantering av filen (%1)"
+msgstr "Ett fel inträffade vid hantering av filen %1"
 
 #: src/lib/analyse_audio_job.cc:49
 msgid "Analyse audio of %1"
diff --git a/src/lib/trimmer.cc b/src/lib/trimmer.cc
new file mode 100644 (file)
index 0000000..68364e5
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+    Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <boost/shared_ptr.hpp>
+#include "trimmer.h"
+
+using std::cout;
+using std::max;
+using boost::shared_ptr;
+
+/** @param audio_sample_rate Audio sampling rate, or 0 if there is no audio */
+Trimmer::Trimmer (
+       shared_ptr<Log> log,
+       int video_trim_start,
+       int video_trim_end, int video_length,
+       int audio_sample_rate,
+       float frames_per_second,
+       int dcp_frames_per_second
+       )
+       : AudioVideoProcessor (log)
+       , _video_start (video_trim_start)
+       , _video_end (video_length - video_trim_end)
+       , _video_in (0)
+       , _audio_in (0)
+{
+       FrameRateConversion frc (frames_per_second, dcp_frames_per_second);
+
+       if (frc.skip) {
+               _video_start /= 2;
+               _video_end /= 2;
+       } else if (frc.repeat) {
+               _video_start *= 2;
+               _video_end *= 2;
+       }
+
+       if (audio_sample_rate) {
+               _audio_start = video_frames_to_audio_frames (_video_start, audio_sample_rate, frames_per_second);
+               _audio_end = video_frames_to_audio_frames (_video_end, audio_sample_rate, frames_per_second);
+       }
+}
+
+void
+Trimmer::process_video (shared_ptr<Image> image, bool same, shared_ptr<Subtitle> sub)
+{
+       if (_video_in >= _video_start && _video_in <= _video_end) {
+               Video (image, same, sub);
+       }
+       
+       ++_video_in;
+}
+
+void
+Trimmer::process_audio (shared_ptr<AudioBuffers> audio)
+{
+       int64_t offset = _audio_start - _audio_in;
+       if (offset > audio->frames()) {
+               _audio_in += audio->frames ();
+               return;
+       }
+
+       if (offset < 0) {
+               offset = 0;
+       }
+
+       int64_t length = _audio_end - max (_audio_in, _audio_start);
+       if (length < 0) {
+               _audio_in += audio->frames ();
+               return;
+       }
+
+       if (length > (audio->frames() - offset)) {
+               length = audio->frames () - offset;
+       }
+
+       _audio_in += audio->frames ();
+       
+       if (offset != 0 || length != audio->frames ()) {
+               audio->move (offset, 0, length);
+               audio->set_frames (length);
+       }
+       
+       Audio (audio);
+}
+
diff --git a/src/lib/trimmer.h b/src/lib/trimmer.h
new file mode 100644 (file)
index 0000000..ff7e951
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+    Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "processor.h"
+
+class Trimmer : public AudioVideoProcessor
+{
+public:
+       Trimmer (boost::shared_ptr<Log>, int, int, int, int, float, int);
+
+       void process_video (boost::shared_ptr<Image> i, bool, boost::shared_ptr<Subtitle> s);
+       void process_audio (boost::shared_ptr<AudioBuffers>);
+
+private:
+       friend class trimmer_test;
+
+       int _video_start;
+       int _video_end;
+       int _video_in;
+       int64_t _audio_start;
+       int64_t _audio_end;
+       int64_t _audio_in;
+};
index 7258826ba1774f5a9fd3e32656bb32a2a761edd3..8e771a5e239e73044de2456310e754d042d0ff90 100644 (file)
@@ -69,8 +69,8 @@ Writer::Writer (shared_ptr<Film> f)
        
        _picture_asset.reset (
                new libdcp::MonoPictureAsset (
-                       _film->video_mxf_dir (),
-                       _film->video_mxf_filename (),
+                       _film->internal_video_mxf_dir (),
+                       _film->internal_video_mxf_filename (),
                        _film->dcp_frame_rate (),
                        _film->format()->dcp_size ()
                        )
@@ -82,7 +82,7 @@ Writer::Writer (shared_ptr<Film> f)
                _sound_asset.reset (
                        new libdcp::SoundAsset (
                                _film->dir (_film->dcp_name()),
-                               N_("audio.mxf"),
+                               _film->dcp_audio_mxf_filename (),
                                _film->dcp_frame_rate (),
                                _film->audio_mapping().dcp_channels (),
                                dcp_audio_sample_rate (_film->audio_frame_rate())
@@ -261,20 +261,25 @@ Writer::finish ()
        }
 
        int const frames = _last_written_frame + 1;
-       int const duration = frames - _film->trim_start() - _film->trim_end();
+       int duration = 0;
+       if (_film->trim_type() == Film::CPL) {
+               duration = frames - _film->trim_start() - _film->trim_end();
+               _picture_asset->set_entry_point (_film->trim_start ());
+       } else {
+               duration = frames;
+       }
        
-       _picture_asset->set_entry_point (_film->trim_start ());
        _picture_asset->set_duration (duration);
 
        /* Hard-link the video MXF into the DCP */
 
        boost::filesystem::path from;
-       from /= _film->video_mxf_dir();
-       from /= _film->video_mxf_filename();
+       from /= _film->internal_video_mxf_dir();
+       from /= _film->internal_video_mxf_filename();
        
        boost::filesystem::path to;
        to /= _film->dir (_film->dcp_name());
-       to /= N_("video.mxf");
+       to /= _film->dcp_video_mxf_filename ();
 
        boost::system::error_code ec;
        boost::filesystem::create_hard_link (from, to, ec);
@@ -287,10 +292,12 @@ Writer::finish ()
        /* And update the asset */
 
        _picture_asset->set_directory (_film->dir (_film->dcp_name ()));
-       _picture_asset->set_file_name (N_("video.mxf"));
+       _picture_asset->set_file_name (_film->dcp_video_mxf_filename ());
 
        if (_sound_asset) {
-               _sound_asset->set_entry_point (_film->trim_start ());
+               if (_film->trim_type() == Film::CPL) {
+                       _sound_asset->set_entry_point (_film->trim_start ());
+               }
                _sound_asset->set_duration (duration);
        }
        
@@ -341,8 +348,8 @@ Writer::check_existing_picture_mxf ()
 {
        /* Try to open the existing MXF */
        boost::filesystem::path p;
-       p /= _film->video_mxf_dir ();
-       p /= _film->video_mxf_filename ();
+       p /= _film->internal_video_mxf_dir ();
+       p /= _film->internal_video_mxf_filename ();
        FILE* mxf = fopen (p.string().c_str(), N_("rb"));
        if (!mxf) {
                return;
index fddebe8e648180a2744631a80ed88b6cd891ed0a..e53ac5a840d705381fafa16955a592f9cc68ff1a 100644 (file)
@@ -52,6 +52,7 @@ sources = """
           transcode_job.cc
           transcoder.cc
           types.cc
+          trimmer.cc
           ui_signaller.cc
           util.cc
           video_content.cc
index ee9f9977cb93ee1fef332fbff0728816e6f91f38..e053da5340d8fc2e45335c610e5b155f3c7cd1d4 100644 (file)
@@ -18,6 +18,7 @@
 */
 
 #include <iostream>
+#include <fstream>
 #include <boost/filesystem.hpp>
 #ifdef __WXMSW__
 #include <shellapi.h>
@@ -52,6 +53,7 @@ using std::stringstream;
 using std::map;
 using std::make_pair;
 using std::exception;
+using std::ofstream;
 using boost::shared_ptr;
 
 static FilmEditor* film_editor = 0;
@@ -458,14 +460,22 @@ setup_i18n ()
 {
        int language = wxLANGUAGE_DEFAULT;
 
-       if (Config::instance()->language()) {
-               wxLanguageInfo const * li = wxLocale::FindLanguageInfo (std_to_wx (Config::instance()->language().get()));
+       ofstream f ("c:/users/carl hetherington/foo", std::ios::app);
+       f << "Hello.\n";
+
+       boost::optional<string> config_lang = Config::instance()->language ();
+       if (config_lang && !config_lang->empty ()) {
+               f << "Configured language " << config_lang.get() << "\n";
+               wxLanguageInfo const * li = wxLocale::FindLanguageInfo (std_to_wx (config_lang.get ()));
+               f << "LanguageInfo " << li << "\n";
                if (li) {
                        language = li->Language;
+                       f << "language=" << language << " cf " << wxLANGUAGE_DEFAULT << " " << wxLANGUAGE_ENGLISH << "\n";
                }
        }
  
        if (wxLocale::IsAvailable (language)) {
+               f << "Language is available.\n";
                locale = new wxLocale (language, wxLOCALE_LOAD_DEFAULT);
 
 #ifdef DCPOMATIC_WINDOWS
@@ -476,6 +486,7 @@ setup_i18n ()
                locale->AddCatalog (wxT ("dcpomatic"));
                
                if (!locale->IsOk()) {
+                       f << "Locale is not ok.\n";
                        delete locale;
                        locale = new wxLocale (wxLANGUAGE_ENGLISH);
                        language = wxLANGUAGE_ENGLISH;
index 4ae8f1eb4bd53f2f6fa56b0ebea4ab468ca57d7f..c3eebc01515451d5a33529926bc6f039c6cbd166 100644 (file)
@@ -226,7 +226,7 @@ ConfigDialog::language_changed (wxCommandEvent &)
 {
        switch (_language->GetSelection ()) {
        case 0:
-               Config::instance()->set_language ("");
+               Config::instance()->set_language ("en");
                break;
        case 1:
                Config::instance()->set_language ("fr");
index f960abcfa02f616ef289742cfdc4b0affeae54da..ad028c930c52510b86036a2988a1a03128222c2f 100644 (file)
@@ -174,6 +174,11 @@ FilmEditor::make_film_panel ()
        }
        ++r;
 
+       add_label_to_grid_bag_sizer (grid, _film_panel, _("Trim method"), wxGBPosition (r, 0));
+       _trim_type = new wxChoice (_film_panel, wxID_ANY);
+       grid->Add (_trim_type, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
+       ++r;
+
        _ab = new wxCheckBox (_film_panel, wxID_ANY, _("A/B"));
        grid->Add (_ab, wxGBPosition (r, 0));
        ++r;
@@ -187,49 +192,53 @@ FilmEditor::make_film_panel ()
        for (list<int>::const_iterator i = dfr.begin(); i != dfr.end(); ++i) {
                _dcp_frame_rate->Append (std_to_wx (boost::lexical_cast<string> (*i)));
        }
+
+       _trim_type->Append (_("encode all frames and play the subset"));
+       _trim_type->Append (_("encode only the subset"));
 }
 
 void
 FilmEditor::connect_to_widgets ()
 {
-       _name->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (FilmEditor::name_changed), 0, this);
-       _use_dci_name->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::use_dci_name_toggled), 0, this);
-       _edit_dci_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::edit_dci_button_clicked), 0, this);
-       _format->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::format_changed), 0, this);
-       _trust_content_headers->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::trust_content_headers_changed), 0, this);
-       _content->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler (FilmEditor::content_selection_changed), 0, this);
-       _content->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler (FilmEditor::content_selection_changed), 0, this);
-       _content->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler (FilmEditor::content_activated), 0, this);
-       _content_add->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_add_clicked), 0, this);
-       _content_remove->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_remove_clicked), 0, this);
-       _content_edit->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_edit_clicked), 0, this);
-       _content_earlier->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_earlier_clicked), 0, this);
-       _content_later->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_later_clicked), 0, this);
-       _left_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::left_crop_changed), 0, this);
-       _right_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::right_crop_changed), 0, this);
-       _top_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::top_crop_changed), 0, this);
-       _bottom_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::bottom_crop_changed), 0, this);
-       _filters_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::edit_filters_clicked), 0, this);
-       _scaler->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::scaler_changed), 0, this);
-       _dcp_content_type->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_content_type_changed), 0, this);
-       _dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_frame_rate_changed), 0, this);
-       _best_dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::best_dcp_frame_rate_clicked), 0, this);
-       _ab->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::ab_toggled), 0, this);
-       _trim_start->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::trim_start_changed), 0, this);
-       _trim_end->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::trim_end_changed), 0, this);
-       _with_subtitles->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::with_subtitles_toggled), 0, this);
-       _subtitle_offset->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::subtitle_offset_changed), 0, this);
-       _subtitle_scale->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::subtitle_scale_changed), 0, this);
-       _colour_lut->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::colour_lut_changed), 0, this);
-       _j2k_bandwidth->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::j2k_bandwidth_changed), 0, this);
-       _ffmpeg_subtitle_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::ffmpeg_subtitle_stream_changed), 0, this);
-       _ffmpeg_audio_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::ffmpeg_audio_stream_changed), 0, this);
-       _audio_gain->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::audio_gain_changed), 0, this);
+       _name->Connect                   (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED,         wxCommandEventHandler (FilmEditor::name_changed), 0, this);
+       _use_dci_name->Connect           (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED,     wxCommandEventHandler (FilmEditor::use_dci_name_toggled), 0, this);
+       _edit_dci_button->Connect        (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED,       wxCommandEventHandler (FilmEditor::edit_dci_button_clicked), 0, this);
+       _format->Connect                 (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED,      wxCommandEventHandler (FilmEditor::format_changed), 0, this);
+       _trust_content_headers->Connect  (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED,     wxCommandEventHandler (FilmEditor::trust_content_headers_changed), 0, this);
+       _content->Connect                (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_SELECTED,   wxListEventHandler    (FilmEditor::content_selection_changed), 0, this);
+       _content->Connect                (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler    (FilmEditor::content_selection_changed), 0, this);
+       _content->Connect                (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_ACTIVATED,  wxListEventHandler    (FilmEditor::content_activated), 0, this);
+       _content_add->Connect            (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED,       wxCommandEventHandler (FilmEditor::content_add_clicked), 0, this);
+       _content_remove->Connect         (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED,       wxCommandEventHandler (FilmEditor::content_remove_clicked), 0, this);
+       _content_edit->Connect           (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED,       wxCommandEventHandler (FilmEditor::content_edit_clicked), 0, this);
+       _content_earlier->Connect        (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED,       wxCommandEventHandler (FilmEditor::content_earlier_clicked), 0, this);
+       _content_later->Connect          (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED,       wxCommandEventHandler (FilmEditor::content_later_clicked), 0, this);
+       _left_crop->Connect              (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED,     wxCommandEventHandler (FilmEditor::left_crop_changed), 0, this);
+       _right_crop->Connect             (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED,     wxCommandEventHandler (FilmEditor::right_crop_changed), 0, this);
+       _top_crop->Connect               (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED,     wxCommandEventHandler (FilmEditor::top_crop_changed), 0, this);
+       _bottom_crop->Connect            (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED,     wxCommandEventHandler (FilmEditor::bottom_crop_changed), 0, this);
+       _filters_button->Connect         (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED,       wxCommandEventHandler (FilmEditor::edit_filters_clicked), 0, this);
+       _scaler->Connect                 (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED,      wxCommandEventHandler (FilmEditor::scaler_changed), 0, this);
+       _dcp_content_type->Connect       (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED,      wxCommandEventHandler (FilmEditor::dcp_content_type_changed), 0, this);
+       _dcp_frame_rate->Connect         (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED,      wxCommandEventHandler (FilmEditor::dcp_frame_rate_changed), 0, this);
+       _best_dcp_frame_rate->Connect    (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED,       wxCommandEventHandler (FilmEditor::best_dcp_frame_rate_clicked), 0, this);
+       _ab->Connect                     (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED,     wxCommandEventHandler (FilmEditor::ab_toggled), 0, this);
+       _trim_start->Connect             (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED,     wxCommandEventHandler (FilmEditor::trim_start_changed), 0, this);
+       _trim_end->Connect               (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED,     wxCommandEventHandler (FilmEditor::trim_end_changed), 0, this);
+       _trim_type->Connect              (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED,      wxCommandEventHandler (FilmEditor::trim_type_changed), 0, this);
+       _with_subtitles->Connect         (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED,     wxCommandEventHandler (FilmEditor::with_subtitles_toggled), 0, this);
+       _subtitle_offset->Connect        (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED,     wxCommandEventHandler (FilmEditor::subtitle_offset_changed), 0, this);
+       _subtitle_scale->Connect         (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED,     wxCommandEventHandler (FilmEditor::subtitle_scale_changed), 0, this);
+       _colour_lut->Connect             (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED,      wxCommandEventHandler (FilmEditor::colour_lut_changed), 0, this);
+       _j2k_bandwidth->Connect          (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED,     wxCommandEventHandler (FilmEditor::j2k_bandwidth_changed), 0, this);
+       _ffmpeg_subtitle_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED,      wxCommandEventHandler (FilmEditor::ffmpeg_subtitle_stream_changed), 0, this);
+       _ffmpeg_audio_stream->Connect    (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED,      wxCommandEventHandler (FilmEditor::ffmpeg_audio_stream_changed), 0, this);
+       _audio_gain->Connect             (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED,     wxCommandEventHandler (FilmEditor::audio_gain_changed), 0, this);
        _audio_gain_calculate_button->Connect (
                wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::audio_gain_calculate_button_clicked), 0, this
                );
-       _show_audio->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::show_audio_clicked), 0, this);
-       _audio_delay->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::audio_delay_changed), 0, this);
+       _show_audio->Connect             (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED,       wxCommandEventHandler (FilmEditor::show_audio_clicked), 0, this);
+       _audio_delay->Connect            (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED,     wxCommandEventHandler (FilmEditor::audio_delay_changed), 0, this);
 }
 
 void
@@ -654,6 +663,9 @@ FilmEditor::film_changed (Film::Property p)
        case Film::TRIM_END:
                checked_set (_trim_end, _film->trim_end());
                break;
+       case Film::TRIM_TYPE:
+               checked_set (_trim_type, _film->trim_type() == Film::CPL ? 0 : 1);
+               break;
        case Film::AUDIO_GAIN:
                checked_set (_audio_gain, _film->audio_gain ());
                break;
@@ -877,6 +889,7 @@ FilmEditor::set_film (shared_ptr<Film> f)
        film_changed (Film::TRIM_START);
        film_changed (Film::TRIM_END);
        film_changed (Film::AB);
+       film_changed (Film::TRIM_TYPE);
        film_changed (Film::AUDIO_GAIN);
        film_changed (Film::AUDIO_DELAY);
        film_changed (Film::WITH_SUBTITLES);
@@ -921,6 +934,7 @@ FilmEditor::set_things_sensitive (bool s)
        _trim_start->Enable (s);
        _trim_end->Enable (s);
        _ab->Enable (s);
+       _trim_type->Enable (s);
        _colour_lut->Enable (s);
        _j2k_bandwidth->Enable (s);
        _audio_gain->Enable (s);
@@ -1454,3 +1468,9 @@ FilmEditor::setup_scaling_description ()
 
        _scaling_description->SetLabel (d);
 }
+
+void
+FilmEditor::trim_type_changed (wxCommandEvent &)
+{
+       _film->set_trim_type (_trim_type->GetSelection () == 0 ? Film::CPL : Film::ENCODE);
+}
index 0f3d8eb507a5eabc0c6e316f81fd7b03c4f6924c..ffffc1e76de853ffb03b045ff2c84d96517bb34e 100644 (file)
@@ -75,6 +75,7 @@ private:
        void format_changed (wxCommandEvent &);
        void trim_start_changed (wxCommandEvent &);
        void trim_end_changed (wxCommandEvent &);
+       void trim_type_changed (wxCommandEvent &);
        void dcp_content_type_changed (wxCommandEvent &);
        void ab_toggled (wxCommandEvent &);
        void scaler_changed (wxCommandEvent &);
@@ -176,6 +177,7 @@ private:
 
        wxSpinCtrl* _trim_start;
        wxSpinCtrl* _trim_end;
+       wxChoice* _trim_type;
        /** Selector to generate an A/B comparison DCP */
        wxCheckBox* _ab;
 
index 16e3837c8c64274a4d409f5be719c63e490e99e2..b7a03188341e1d320f35ea6ae3aa321cc1aa014e 100644 (file)
@@ -14,6 +14,7 @@ filter unsharp
 scaler bicubic
 trim_start 42
 trim_end 99
+trim_type cpl
 dcp_ab 1
 use_content_audio 1
 audio_gain 0
index 39a921d3682149a88f7485c5cc584b5688512b53..a2c0de25048443675eb61dc55c4a6a80c8fdb953 100644 (file)
@@ -41,6 +41,7 @@
 #include "ffmpeg_decoder.h"
 #include "sndfile_decoder.h"
 #include "dcp_content_type.h"
+#include "trimmer.h"
 #define BOOST_TEST_DYN_LINK
 #define BOOST_TEST_MODULE dcpomatic_test
 #include <boost/test/unit_test.hpp>
@@ -124,6 +125,55 @@ BOOST_AUTO_TEST_CASE (make_black_test)
        }
 }
 
+shared_ptr<AudioBuffers> trimmer_test_last;
+
+void
+trimmer_test_helper (shared_ptr<AudioBuffers> audio)
+{
+       trimmer_test_last = audio;
+}
+
+/** Test the audio handling of the Trimmer */
+BOOST_AUTO_TEST_CASE (trimmer_test)
+{
+       Trimmer trimmer (shared_ptr<Log> (), 25, 75, 200, 48000, 25, 25);
+
+       trimmer.Audio.connect (bind (&trimmer_test_helper, _1));
+
+       /* 21 video frames-worth of audio frames; should be completely stripped */
+       trimmer_test_last.reset ();
+       shared_ptr<AudioBuffers> audio (new AudioBuffers (6, 21 * 1920));
+       trimmer.process_audio (audio);
+       BOOST_CHECK (trimmer_test_last == 0);
+
+       /* 42 more video frames-worth, 4 should be stripped from the start */
+       audio.reset (new AudioBuffers (6, 42 * 1920));
+       trimmer.process_audio (audio);
+       BOOST_CHECK (trimmer_test_last);
+       BOOST_CHECK_EQUAL (trimmer_test_last->frames(), 38 * 1920);
+
+       /* 42 more video frames-worth, should be kept as-is */
+       trimmer_test_last.reset ();
+       audio.reset (new AudioBuffers (6, 42 * 1920));
+       trimmer.process_audio (audio);
+       BOOST_CHECK (trimmer_test_last);
+       BOOST_CHECK_EQUAL (trimmer_test_last->frames(), 42 * 1920);
+
+       /* 25 more video frames-worth, 5 should be trimmed from the end */
+       trimmer_test_last.reset ();
+       audio.reset (new AudioBuffers (6, 25 * 1920));
+       trimmer.process_audio (audio);
+       BOOST_CHECK (trimmer_test_last);
+       BOOST_CHECK_EQUAL (trimmer_test_last->frames(), 20 * 1920);
+
+       /* Now some more; all should be trimmed */
+       trimmer_test_last.reset ();
+       audio.reset (new AudioBuffers (6, 100 * 1920));
+       trimmer.process_audio (audio);
+       BOOST_CHECK (trimmer_test_last == 0);
+}
+
+
 BOOST_AUTO_TEST_CASE (film_metadata_test)
 {
        setup_test_config ();
@@ -435,7 +485,7 @@ BOOST_AUTO_TEST_CASE (have_dcp_test)
        BOOST_CHECK (f.have_dcp());
 
        p /= f.dcp_name();
-       p /= "video.mxf";
+       p /= f.dcp_video_mxf_filename();
        boost::filesystem::remove (p);
        BOOST_CHECK (!f.have_dcp ());
 }
@@ -794,3 +844,4 @@ BOOST_AUTO_TEST_CASE (aligned_image_test)
        delete t;
        delete u;
 }
+