summaryrefslogtreecommitdiff
path: root/src/wx
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2021-01-20 23:42:28 +0100
committerCarl Hetherington <cth@carlh.net>2021-01-20 23:42:28 +0100
commitcb6729aa79b555b219974207fbe2ff0510f9d3ea (patch)
tree973024e5dbf8bd8d873850909665e6229138ef57 /src/wx
parentd24251b2e0d82236f93ee5415b72849dee2a0ac8 (diff)
Bump libdcp for better verification, and make API adjustments.
Diffstat (limited to 'src/wx')
-rw-r--r--src/wx/content_menu.cc4
-rw-r--r--src/wx/kdm_cpl_panel.cc2
-rw-r--r--src/wx/markers_dialog.cc25
-rw-r--r--src/wx/verify_dcp_dialog.cc334
-rw-r--r--src/wx/verify_dcp_dialog.h3
5 files changed, 276 insertions, 92 deletions
diff --git a/src/wx/content_menu.cc b/src/wx/content_menu.cc
index d93fd31b2..1ac13b143 100644
--- a/src/wx/content_menu.cc
+++ b/src/wx/content_menu.cc
@@ -142,7 +142,7 @@ ContentMenu::popup (weak_ptr<Film> film, ContentList c, TimelineContentViewList
_set_dcp_settings->Enable (static_cast<bool>(dcp));
try {
DCPExaminer ex (dcp, true);
- list<shared_ptr<dcp::CPL> > cpls = ex.cpls ();
+ auto cpls = ex.cpls ();
_choose_cpl->Enable (cpls.size() > 1);
/* We can't have 0 as a menu item ID on OS X */
int id = 1;
@@ -151,7 +151,7 @@ ContentMenu::popup (weak_ptr<Film> film, ContentList c, TimelineContentViewList
id++,
wxString::Format (
"%s (%s)",
- std_to_wx(i->annotation_text()).data(),
+ std_to_wx(i->annotation_text().get_value_or("")).data(),
std_to_wx(i->id()).data()
)
);
diff --git a/src/wx/kdm_cpl_panel.cc b/src/wx/kdm_cpl_panel.cc
index be5e42dd8..8bb73f783 100644
--- a/src/wx/kdm_cpl_panel.cc
+++ b/src/wx/kdm_cpl_panel.cc
@@ -92,7 +92,7 @@ KDMCPLPanel::update_cpl_summary ()
_dcp_directory->SetLabel (std_to_wx (_cpls[n].dcp_directory));
_cpl_id->SetLabel (std_to_wx (_cpls[n].cpl_id));
- _cpl_annotation_text->SetLabel (std_to_wx (_cpls[n].cpl_annotation_text));
+ _cpl_annotation_text->SetLabel (std_to_wx(_cpls[n].cpl_annotation_text.get_value_or("")));
}
void
diff --git a/src/wx/markers_dialog.cc b/src/wx/markers_dialog.cc
index 31789af2c..7f675f215 100644
--- a/src/wx/markers_dialog.cc
+++ b/src/wx/markers_dialog.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2019-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
@@ -32,10 +32,11 @@
#include <iostream>
using std::cout;
-using boost::bind;
using std::shared_ptr;
using std::weak_ptr;
+using std::make_shared;
using boost::optional;
+using boost::bind;
using dcpomatic::DCPTime;
class Marker
@@ -113,16 +114,16 @@ MarkersDialog::MarkersDialog (wxWindow* parent, weak_ptr<Film> film, weak_ptr<Fi
wxGridBagSizer* grid = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
int r = 0;
- _markers.push_back (shared_ptr<Marker>(new Marker(this, grid, r++, film, viewer, _("First frame of composition"), dcp::FFOC)));
- _markers.push_back (shared_ptr<Marker>(new Marker(this, grid, r++, film, viewer, _("Last frame of composition"), dcp::LFOC)));
- _markers.push_back (shared_ptr<Marker>(new Marker(this, grid, r++, film, viewer, _("First frame of title credits"), dcp::FFTC)));
- _markers.push_back (shared_ptr<Marker>(new Marker(this, grid, r++, film, viewer, _("Last frame of title credits"), dcp::LFTC)));
- _markers.push_back (shared_ptr<Marker>(new Marker(this, grid, r++, film, viewer, _("First frame of intermission"), dcp::FFOI)));
- _markers.push_back (shared_ptr<Marker>(new Marker(this, grid, r++, film, viewer, _("Last frame of intermission"), dcp::LFOI)));
- _markers.push_back (shared_ptr<Marker>(new Marker(this, grid, r++, film, viewer, _("First frame of end credits"), dcp::FFEC)));
- _markers.push_back (shared_ptr<Marker>(new Marker(this, grid, r++, film, viewer, _("Last frame of end credits"), dcp::LFEC)));
- _markers.push_back (shared_ptr<Marker>(new Marker(this, grid, r++, film, viewer, _("First frame of moving credits"), dcp::FFMC)));
- _markers.push_back (shared_ptr<Marker>(new Marker(this, grid, r++, film, viewer, _("Last frame of moving credits"), dcp::LFMC)));
+ _markers.push_back (make_shared<Marker>(this, grid, r++, film, viewer, _("First frame of composition"), dcp::Marker::FFOC));
+ _markers.push_back (make_shared<Marker>(this, grid, r++, film, viewer, _("Last frame of composition"), dcp::Marker::LFOC));
+ _markers.push_back (make_shared<Marker>(this, grid, r++, film, viewer, _("First frame of title credits"), dcp::Marker::FFTC));
+ _markers.push_back (make_shared<Marker>(this, grid, r++, film, viewer, _("Last frame of title credits"), dcp::Marker::LFTC));
+ _markers.push_back (make_shared<Marker>(this, grid, r++, film, viewer, _("First frame of intermission"), dcp::Marker::FFOI));
+ _markers.push_back (make_shared<Marker>(this, grid, r++, film, viewer, _("Last frame of intermission"), dcp::Marker::LFOI));
+ _markers.push_back (make_shared<Marker>(this, grid, r++, film, viewer, _("First frame of end credits"), dcp::Marker::FFEC));
+ _markers.push_back (make_shared<Marker>(this, grid, r++, film, viewer, _("Last frame of end credits"), dcp::Marker::LFEC));
+ _markers.push_back (make_shared<Marker>(this, grid, r++, film, viewer, _("First frame of moving credits"), dcp::Marker::FFMC));
+ _markers.push_back (make_shared<Marker>(this, grid, r++, film, viewer, _("Last frame of moving credits"), dcp::Marker::LFMC));
sizer->Add (grid, 0, wxALL, 8);
SetSizerAndFit (sizer);
diff --git a/src/wx/verify_dcp_dialog.cc b/src/wx/verify_dcp_dialog.cc
index 55360dc39..50fd4be0c 100644
--- a/src/wx/verify_dcp_dialog.cc
+++ b/src/wx/verify_dcp_dialog.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2018 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2018-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
@@ -23,21 +23,36 @@
#include "lib/verify_dcp_job.h"
#include "lib/warnings.h"
#include <dcp/verify.h>
+#include <dcp/raw_convert.h>
DCPOMATIC_DISABLE_WARNINGS
#include <wx/richtext/richtextctrl.h>
+#include <wx/notebook.h>
DCPOMATIC_ENABLE_WARNINGS
using std::list;
+using std::map;
using std::shared_ptr;
+using std::string;
VerifyDCPDialog::VerifyDCPDialog (wxWindow* parent, shared_ptr<VerifyDCPJob> job)
- : wxDialog (parent, wxID_ANY, _("DCP verification"))
+ : wxDialog (parent, wxID_ANY, _("DCP verification"), wxDefaultPosition, {600, 400})
{
- wxBoxSizer* sizer = new wxBoxSizer (wxVERTICAL);
- _text = new wxRichTextCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (400, 300), wxRE_READONLY);
- sizer->Add (_text, 1, wxEXPAND | wxALL, 6);
+ auto sizer = new wxBoxSizer (wxVERTICAL);
+ auto notebook = new wxNotebook (this, wxID_ANY);
+ sizer->Add (notebook, 1, wxEXPAND | wxALL, DCPOMATIC_DIALOG_BORDER);
- wxStdDialogButtonSizer* buttons = CreateStdDialogButtonSizer (0);
+ map<dcp::VerificationNote::Type, wxRichTextCtrl*> pages;
+ pages[dcp::VerificationNote::VERIFY_ERROR] = new wxRichTextCtrl (notebook, wxID_ANY, wxEmptyString, wxDefaultPosition, {400, 300}, wxRE_READONLY);
+ notebook->AddPage (pages[dcp::VerificationNote::VERIFY_ERROR], _("Errors"));
+ pages[dcp::VerificationNote::VERIFY_BV21_ERROR] = new wxRichTextCtrl (notebook, wxID_ANY, wxEmptyString, wxDefaultPosition, {400, 300}, wxRE_READONLY);
+ notebook->AddPage (pages[dcp::VerificationNote::VERIFY_BV21_ERROR], _("SMPTE Bv2.1 errors"));
+ pages[dcp::VerificationNote::VERIFY_WARNING] = new wxRichTextCtrl (notebook, wxID_ANY, wxEmptyString, wxDefaultPosition, {400, 300}, wxRE_READONLY);
+ notebook->AddPage (pages[dcp::VerificationNote::VERIFY_WARNING], _("Warnings"));
+
+ auto summary = new wxStaticText (this, wxID_ANY, wxT(""));
+ sizer->Add (summary, 0, wxALL, DCPOMATIC_DIALOG_BORDER);
+
+ auto buttons = CreateStdDialogButtonSizer (0);
sizer->Add (CreateSeparatedSizer(buttons), wxSizerFlags().Expand().DoubleBorder());
buttons->SetAffirmativeButton (new wxButton (this, wxID_OK));
buttons->Realize ();
@@ -46,114 +61,281 @@ VerifyDCPDialog::VerifyDCPDialog (wxWindow* parent, shared_ptr<VerifyDCPJob> job
sizer->Layout ();
sizer->SetSizeHints (this);
- _text->GetCaret()->Hide ();
+ for (auto const& i: pages) {
+ i.second->GetCaret()->Hide();
+ }
if (job->finished_ok() && job->notes().empty()) {
- _text->BeginStandardBullet (N_("standard/circle"), 1, 50);
- _text->WriteText (_("DCP validates OK."));
- _text->EndStandardBullet ();
+ summary->SetLabel (_("DCP validates OK."));
return;
}
- /* We might have an error that did not come from dcp::verify; report it if so */
+ map<dcp::VerificationNote::Type, int> counts;
+ counts[dcp::VerificationNote::VERIFY_WARNING] = 0;
+ counts[dcp::VerificationNote::VERIFY_BV21_ERROR] = 0;
+ counts[dcp::VerificationNote::VERIFY_ERROR] = 0;
+
+ auto add_bullet = [&pages](dcp::VerificationNote::Type type, wxString message) {
+ pages[type]->BeginStandardBullet(N_("standard/diamond"), 1, 50);
+ pages[type]->WriteText (message);
+ pages[type]->Newline ();
+ pages[type]->EndStandardBullet ();
+ };
+
+ auto add = [&counts, &add_bullet](dcp::VerificationNote note, wxString message) {
+ if (note.note()) {
+ message.Replace("%n", std_to_wx(note.note().get()));
+ }
+ if (note.file()) {
+ message.Replace("%f", std_to_wx(note.file()->filename().string()));
+ }
+ if (note.line()) {
+ message.Replace("%l", std_to_wx(dcp::raw_convert<string>(note.line().get())));
+ }
+ add_bullet (note.type(), message);
+ counts[note.type()]++;
+ };
+
if (job->finished_in_error() && job->error_summary() != "") {
- _text->BeginSymbolBullet (N_("!"), 1, 50);
- _text->WriteText(std_to_wx(job->error_summary()));
- _text->Newline();
+ /* We have an error that did not come from dcp::verify */
+ add_bullet (dcp::VerificationNote::VERIFY_ERROR, std_to_wx(job->error_summary()));
}
for (auto i: job->notes()) {
- switch (i.type()) {
- case dcp::VerificationNote::VERIFY_WARNING:
- _text->BeginStandardBullet (N_("standard/diamond"), 1, 50);
- break;
- case dcp::VerificationNote::VERIFY_ERROR:
- _text->BeginSymbolBullet (N_("!"), 1, 50);
- break;
- }
-
- wxString text;
switch (i.code()) {
- case dcp::VerificationNote::GENERAL_READ:
- text = std_to_wx(*i.note());
+ case dcp::VerificationNote::FAILED_READ:
+ add (i, std_to_wx(*i.note()));
break;
- case dcp::VerificationNote::CPL_HASH_INCORRECT:
- text = _("The hash of the CPL in the PKL does not agree with the CPL file. This probably means that the CPL file is corrupt.");
+ case dcp::VerificationNote::MISMATCHED_CPL_HASHES:
+ add(i, _("The hash of the CPL %n in the PKL does not agree with the CPL file. This probably means that the CPL file is corrupt."));
break;
case dcp::VerificationNote::INVALID_PICTURE_FRAME_RATE:
- text = _("The picture in a reel has an invalid frame rate");
+ add(i, _("The picture in a reel has a frame rate of %n, which is not valid."));
break;
- case dcp::VerificationNote::PICTURE_HASH_INCORRECT:
- text = wxString::Format(
- _("The hash of the picture asset %s does not agree with the PKL file. This probably means that the asset file is corrupt."),
- std_to_wx(i.file()->filename().string())
- );
+ case dcp::VerificationNote::INCORRECT_PICTURE_HASH:
+ add(i, _("The hash of the picture asset %f does not agree with the PKL file. This probably means that the asset file is corrupt."));
break;
- case dcp::VerificationNote::PKL_CPL_PICTURE_HASHES_DISAGREE:
- text = _("The PKL and CPL hashes disagree for a picture asset.");
+ case dcp::VerificationNote::MISMATCHED_PICTURE_HASHES:
+ add(i, _("The PKL and CPL hashes disagree for picture asset %f."));
break;
- case dcp::VerificationNote::SOUND_HASH_INCORRECT:
- text = wxString::Format(
- _("The hash of the sound asset %s does not agree with the PKL file. This probably means that the asset file is corrupt."),
- std_to_wx(i.file()->filename().string())
- );
+ case dcp::VerificationNote::INCORRECT_SOUND_HASH:
+ add(i, _("The hash of the sound asset %f does not agree with the PKL file. This probably means that the asset file is corrupt."));
break;
- case dcp::VerificationNote::PKL_CPL_SOUND_HASHES_DISAGREE:
- text = _("The PKL and CPL hashes disagree for a sound asset.");
+ case dcp::VerificationNote::MISMATCHED_SOUND_HASHES:
+ add(i, _("The PKL and CPL hashes disagree for sound asset %f."));
break;
case dcp::VerificationNote::EMPTY_ASSET_PATH:
- text = _("An asset has an empty path in the ASSETMAP.");
+ add(i, _("An asset has an empty path in the ASSETMAP."));
break;
case dcp::VerificationNote::MISSING_ASSET:
- text = _("An asset is missing.");
+ add(i, _("The asset %f is missing."));
break;
case dcp::VerificationNote::MISMATCHED_STANDARD:
- text = _("Parts of the DCP are written according to the Interop standard and parts according to SMPTE.");
+ add(i, _("Parts of the DCP are written according to the Interop standard and parts according to SMPTE."));
break;
- case dcp::VerificationNote::XML_VALIDATION_ERROR:
+ case dcp::VerificationNote::INVALID_XML:
if (i.line()) {
- text = wxString::Format(
- _("The XML in %s is malformed on line %" PRIu64 "."),
- std_to_wx(i.file()->filename().string()),
- i.line().get()
- );
+ add(i, _("The XML in %f is malformed on line %l (%n)."));
} else {
- text = wxString::Format(
- _("The XML in %s is malformed."),
- std_to_wx(i.file()->filename().string())
- );
+ add(i, _("The XML in %f is malformed (%n)."));
}
break;
case dcp::VerificationNote::MISSING_ASSETMAP:
- text = _("No ASSETMAP or ASSETMAP.xml file was found.");
+ add(i, _("No ASSETMAP or ASSETMAP.xml file was found."));
break;
- case dcp::VerificationNote::INTRINSIC_DURATION_TOO_SMALL:
- text = _("An asset has an instrinsic duration of less than 1 second, which is invalid.");
+ case dcp::VerificationNote::INVALID_INTRINSIC_DURATION:
+ add(i, _("The asset %n has an instrinsic duration of less than 1 second, which is invalid."));
break;
- case dcp::VerificationNote::DURATION_TOO_SMALL:
- text = _("An asset has a duration of less than 1 second, which is invalid.");
+ case dcp::VerificationNote::INVALID_DURATION:
+ add(i, _("The asset %n has a duration of less than 1 second, which is invalid."));
break;
- case dcp::VerificationNote::PICTURE_FRAME_TOO_LARGE:
- text = _("At least one frame of the video data is over the limit of 250Mbit/s.");
+ case dcp::VerificationNote::INVALID_PICTURE_FRAME_SIZE_IN_BYTES:
+ add(i, _("At least one frame of the video asset %f is over the limit of 250Mbit/s."));
break;
- case dcp::VerificationNote::PICTURE_FRAME_NEARLY_TOO_LARGE:
- text = _("At least one frame of the video data is close to the limit of 250MBit/s.");
+ case dcp::VerificationNote::NEARLY_INVALID_PICTURE_FRAME_SIZE_IN_BYTES:
+ add(i, _("At least one frame of the video asset %f is close to the limit of 250MBit/s."));
break;
case dcp::VerificationNote::EXTERNAL_ASSET:
- text = _("This DCP refers to at least one asset in another DCP, so it is a \"version file\" (VF)");
+ add(i, _("This DCP refers to at the asset %n in another DCP (and perhaps others), so it is a \"version file\" (VF)"));
break;
- }
-
- _text->WriteText (text);
- _text->Newline ();
-
- switch (i.type()) {
- case dcp::VerificationNote::VERIFY_WARNING:
- _text->EndStandardBullet ();
+ case dcp::VerificationNote::INVALID_STANDARD:
+ add(i, _("This DCP uses the Interop standard, but it should be made with SMPTE."));
+ break;
+ case dcp::VerificationNote::INVALID_LANGUAGE:
+ add(i, _("The invalid language tag %n is used."));
+ break;
+ case dcp::VerificationNote::INVALID_PICTURE_SIZE_IN_PIXELS:
+ add(i, _("The video asset %f uses the invalid image size %n."));
+ break;
+ case dcp::VerificationNote::INVALID_PICTURE_FRAME_RATE_FOR_2K:
+ add(i, _("The video asset %f uses the invalid frame rate %n."));
+ break;
+ case dcp::VerificationNote::INVALID_PICTURE_FRAME_RATE_FOR_4K:
+ add(i, _("The video asset %f uses the frame rate %n which is invalid for 4K video."));
+ break;
+ case dcp::VerificationNote::INVALID_PICTURE_ASSET_RESOLUTION_FOR_3D:
+ add(i, _("The video asset %f uses the frame rate %n which is invalid for 3D video."));
+ break;
+ case dcp::VerificationNote::INVALID_CLOSED_CAPTION_XML_SIZE_IN_BYTES:
+ add(i, _("The XML in the closed caption asset %f takes up %n bytes which is over the 256KB limit."));
+ break;
+ case dcp::VerificationNote::INVALID_TIMED_TEXT_SIZE_IN_BYTES:
+ add(i, _("The timed text asset %f takes up %n bytes which is over the 115MB limit."));
+ break;
+ case dcp::VerificationNote::INVALID_TIMED_TEXT_FONT_SIZE_IN_BYTES:
+ add(i, _("The fonts in the timed text asset %f take up %n bytes which is over the 10MB limit."));
+ break;
+ case dcp::VerificationNote::MISSING_SUBTITLE_LANGUAGE:
+ add(i, _("The subtitle asset %f contains no <Language> tag."));
+ break;
+ case dcp::VerificationNote::MISMATCHED_SUBTITLE_LANGUAGES:
+ add(i, _("Not all subtitle assets specify the same <Language> tag."));
+ break;
+ case dcp::VerificationNote::MISSING_SUBTITLE_START_TIME:
+ add(i, _("The subtitle asset %f contains no <StartTime> tag."));
+ break;
+ case dcp::VerificationNote::INVALID_SUBTITLE_START_TIME:
+ add(i, _("The subtitle asset %f has a <StartTime> which is not zero."));
+ break;
+ case dcp::VerificationNote::INVALID_SUBTITLE_FIRST_TEXT_TIME:
+ add(i, _("The first subtitle or closed caption happens before 4s into the first reel."));
+ break;
+ case dcp::VerificationNote::INVALID_SUBTITLE_DURATION:
+ add(i, _("At least one subtitle lasts less than 15 frames."));
+ break;
+ case dcp::VerificationNote::INVALID_SUBTITLE_SPACING:
+ add(i, _("At least one pair of subtitles is separated by less than 2 frames."));
+ break;
+ case dcp::VerificationNote::INVALID_SUBTITLE_LINE_COUNT:
+ add(i, _("There are more than 3 subtitle lines in at least one place."));
+ break;
+ case dcp::VerificationNote::NEARLY_INVALID_SUBTITLE_LINE_LENGTH:
+ add(i, _("There are more than 52 characters in at least one subtitle line."));
+ break;
+ case dcp::VerificationNote::INVALID_SUBTITLE_LINE_LENGTH:
+ add(i, _("There are more than 79 characters in at least one subtitle line."));
+ break;
+ case dcp::VerificationNote::INVALID_CLOSED_CAPTION_LINE_COUNT:
+ add(i, _("There are more than 3 closed caption lines in at least one place."));
+ break;
+ case dcp::VerificationNote::INVALID_CLOSED_CAPTION_LINE_LENGTH:
+ add(i, _("There are more than 32 characters in at least one closed caption line."));
+ break;
+ case dcp::VerificationNote::INVALID_SOUND_FRAME_RATE:
+ add(i, _("The sound asset %f has an invalid frame rate of %n."));
break;
- case dcp::VerificationNote::VERIFY_ERROR:
- _text->EndSymbolBullet ();
+ case dcp::VerificationNote::MISSING_CPL_ANNOTATION_TEXT:
+ add(i, _("The CPL %n has no <AnnotationText> tag."));
+ break;
+ case dcp::VerificationNote::MISMATCHED_CPL_ANNOTATION_TEXT:
+ add(i, _("The CPL %n has an <AnnotationText> which is not the same as its <ContentTitleText>."));
+ break;
+ case dcp::VerificationNote::MISMATCHED_ASSET_DURATION:
+ add(i, _("At least one asset in a reel does not have the same duration as the others."));
+ break;
+ case dcp::VerificationNote::MISSING_MAIN_SUBTITLE_FROM_SOME_REELS:
+ add(i, _("The DCP has subtitles but at least one reel has no subtitle asset."));
+ break;
+ case dcp::VerificationNote::MISMATCHED_CLOSED_CAPTION_ASSET_COUNTS:
+ add(i, _("The DCP has closed captions but not every reel has the same number of closed caption assets."));
+ break;
+ case dcp::VerificationNote::MISSING_SUBTITLE_ENTRY_POINT:
+ add(i, _("The subtitle asset %n has no <EntryPoint> tag."));
+ break;
+ case dcp::VerificationNote::INCORRECT_SUBTITLE_ENTRY_POINT:
+ add(i, _("Subtitle asset %n has a non-zero <EntryPoint>."));
+ break;
+ case dcp::VerificationNote::MISSING_CLOSED_CAPTION_ENTRY_POINT:
+ add(i, _("The closed caption asset %n has no <EntryPoint> tag."));
+ break;
+ case dcp::VerificationNote::INCORRECT_CLOSED_CAPTION_ENTRY_POINT:
+ add(i, _("Closed caption asset %n has a non-zero <EntryPoint>."));
+ break;
+ case dcp::VerificationNote::MISSING_HASH:
+ add(i, _("The asset %n has no <Hash> in the CPL."));
+ break;
+ case dcp::VerificationNote::MISSING_FFEC_IN_FEATURE:
+ add(i, _("The DCP is a feature but has no FFEC (first frame of end credits) marker."));
+ break;
+ case dcp::VerificationNote::MISSING_FFMC_IN_FEATURE:
+ add(i, _("The DCP is a feature but has no FFMC (first frame of moving credits) marker."));
+ break;
+ case dcp::VerificationNote::MISSING_FFOC:
+ add(i, _("The DCP has no FFOC (first frame of content) marker."));
+ break;
+ case dcp::VerificationNote::MISSING_LFOC:
+ add(i, _("The DCP has no LFOC (last frame of content) marker."));
+ break;
+ case dcp::VerificationNote::INCORRECT_FFOC:
+ add(i, _("The DCP has a FFOC of %n instead of 1."));
+ break;
+ case dcp::VerificationNote::INCORRECT_LFOC:
+ add(i, _("The DCP has a LFOC of %n instead of the reel duration minus one."));
+ break;
+ case dcp::VerificationNote::MISSING_CPL_METADATA:
+ add(i, _("The CPL %n has no CPL metadata tag."));
+ break;
+ case dcp::VerificationNote::MISSING_CPL_METADATA_VERSION_NUMBER:
+ add(i, _("The CPL %n has no CPL metadata version number tag."));
+ break;
+ case dcp::VerificationNote::MISSING_EXTENSION_METADATA:
+ add(i, _("The CPL %n has no CPL extension metadata tag."));
+ break;
+ case dcp::VerificationNote::INVALID_EXTENSION_METADATA:
+ add(i, _("The CPL %f has an invalid CPL extension metadata tag (%n)"));
+ break;
+ case dcp::VerificationNote::UNSIGNED_CPL_WITH_ENCRYPTED_CONTENT:
+ add(i, _("The CPL %n has encrypted content but is not signed."));
+ break;
+ case dcp::VerificationNote::UNSIGNED_PKL_WITH_ENCRYPTED_CONTENT:
+ add(i, _("The PKL %n has encrypted content but is not signed."));
+ break;
+ case dcp::VerificationNote::MISMATCHED_PKL_ANNOTATION_TEXT_WITH_CPL:
+ add(i, _("The PKL %n has an <AnnotationText> which does not match its CPL's <ContentTitleText>."));
+ break;
+ case dcp::VerificationNote::PARTIALLY_ENCRYPTED:
+ add(i, _("The DCP has encrypted content, but not all its assets are encrypted."));
break;
}
}
+
+ wxString summary_text;
+
+ if (counts[dcp::VerificationNote::VERIFY_ERROR] == 1) {
+ /// TRANSLATORS: this will be used at the start of a string like "1 error, 2 Bv2.1 errors and 3 warnings."
+ summary_text = _("1 error, ");
+ } else {
+ /// TRANSLATORS: this will be used at the start of a string like "1 error, 2 Bv2.1 errors and 3 warnings."
+ summary_text = wxString::Format("%d errors, ", counts[dcp::VerificationNote::VERIFY_ERROR]);
+ }
+
+ if (counts[dcp::VerificationNote::VERIFY_BV21_ERROR] == 1) {
+ /// TRANSLATORS: this will be used in the middle of a string like "1 error, 2 Bv2.1 errors and 3 warnings."
+ summary_text += _("1 Bv2.1 error, ");
+ } else {
+ /// TRANSLATORS: this will be used in the middle of a string like "1 error, 2 Bv2.1 errors and 3 warnings."
+ summary_text += wxString::Format("%d Bv2.1 errors, ", counts[dcp::VerificationNote::VERIFY_BV21_ERROR]);
+ }
+
+ if (counts[dcp::VerificationNote::VERIFY_WARNING] == 1) {
+ /// TRANSLATORS: this will be used at the end of a string like "1 error, 2 Bv2.1 errors and 3 warnings."
+ summary_text += _("and 1 warning.");
+ } else {
+ /// TRANSLATORS: this will be used at the end of a string like "1 error, 2 Bv2.1 errors and 3 warnings."
+ summary_text += wxString::Format("and %d warnings.", counts[dcp::VerificationNote::VERIFY_WARNING]);
+ }
+
+ summary->SetLabel(summary_text);
+
+ if (counts[dcp::VerificationNote::VERIFY_ERROR] == 0) {
+ add_bullet (dcp::VerificationNote::VERIFY_ERROR, _("No errors found."));
+ }
+
+ if (counts[dcp::VerificationNote::VERIFY_BV21_ERROR] == 0) {
+ add_bullet (dcp::VerificationNote::VERIFY_BV21_ERROR, _("No SMPTE Bv2.1 errors found."));
+ }
+
+ if (counts[dcp::VerificationNote::VERIFY_WARNING] == 0) {
+ add_bullet (dcp::VerificationNote::VERIFY_WARNING, _("No warnings found."));
+ }
}
diff --git a/src/wx/verify_dcp_dialog.h b/src/wx/verify_dcp_dialog.h
index 2d3bac24f..ecc7d2277 100644
--- a/src/wx/verify_dcp_dialog.h
+++ b/src/wx/verify_dcp_dialog.h
@@ -34,5 +34,6 @@ public:
VerifyDCPDialog (wxWindow* parent, std::shared_ptr<VerifyDCPJob> job);
private:
- wxRichTextCtrl* _text;
+ wxStaticText* _summary;
+ std::map<dcp::VerificationNote::Type, wxRichTextCtrl*> _pages;
};