summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--benchmark/image_benchmark.cc40
-rw-r--r--benchmark/wscript8
-rwxr-xr-xrun/benchmarks8
-rw-r--r--src/lib/audio_mapping.cc32
-rw-r--r--src/lib/film.cc30
-rw-r--r--src/lib/film.h2
-rw-r--r--src/lib/image.cc20
-rw-r--r--src/lib/memory_util.cc46
-rw-r--r--src/lib/memory_util.h7
-rw-r--r--src/lib/po/zh_CN.po63
-rw-r--r--src/lib/reel_writer.cc30
-rw-r--r--src/tools/dcpomatic.cc773
-rw-r--r--src/tools/po/zh_CN.po42
-rw-r--r--src/wx/film_name_location_dialog.cc5
-rw-r--r--src/wx/po/zh_CN.po95
-rw-r--r--src/wx/supporters.cc3
-rw-r--r--test/audio_mapping_test.cc64
-rw-r--r--test/film_test.cc21
-rw-r--r--test/memory_util_test.cc72
-rw-r--r--test/vf_test.cc96
-rw-r--r--test/wscript1
-rw-r--r--wscript1
22 files changed, 882 insertions, 577 deletions
diff --git a/benchmark/image_benchmark.cc b/benchmark/image_benchmark.cc
new file mode 100644
index 000000000..5067e1e06
--- /dev/null
+++ b/benchmark/image_benchmark.cc
@@ -0,0 +1,40 @@
+/*
+ Copyright (C) 2026 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic 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.
+
+ DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "lib/image.h"
+#include "lib/timer.h"
+
+
+int main()
+{
+ auto constexpr TRIALS = 1024;
+
+ {
+ auto image = std::make_shared<Image>(AV_PIX_FMT_UYVY422, dcp::Size{ 3996, 2160 }, Image::Alignment::COMPACT);
+ PeriodTimer timer("Image::make_black AV_PIX_FMT_UYVY422");
+ for (auto i = 0; i < TRIALS; ++i) {
+ image->make_black();
+ }
+ }
+
+ return 0;
+}
+
diff --git a/benchmark/wscript b/benchmark/wscript
new file mode 100644
index 000000000..9b1e776b4
--- /dev/null
+++ b/benchmark/wscript
@@ -0,0 +1,8 @@
+def build(bld):
+ for benchmark in ['image']:
+ obj = bld(features='cxx cxxprogram')
+ obj.uselib = 'DCP AVFORMAT AVFILTER SWSCALE LWEXT4 SUB SWRESAMPLE LEQM_NRT POSTPROC GLIB CURL ICU NETTLE CXML '
+ obj.uselib += 'XMLPP BOOST_FILESYSTEM FONTCONFIG XMLSEC SSH SAMPLERATE BOOST_THREAD CAIROMM PANGOMM ZIP SQLITE3 '
+ obj.use = ['libdcpomatic2']
+ obj.source = '%s_benchmark.cc' % benchmark
+ obj.target = '%s_benchmark' % benchmark
diff --git a/run/benchmarks b/run/benchmarks
new file mode 100755
index 000000000..1138e9e0f
--- /dev/null
+++ b/run/benchmarks
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+set -e
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
+source $DIR/environment
+
+build/benchmark/image_benchmark
diff --git a/src/lib/audio_mapping.cc b/src/lib/audio_mapping.cc
index 4e13d1adb..c926437ea 100644
--- a/src/lib/audio_mapping.cc
+++ b/src/lib/audio_mapping.cc
@@ -85,13 +85,13 @@ AudioMapping::make_zero()
struct ChannelRegex
{
- ChannelRegex(string regex_, int channel_)
+ ChannelRegex(string regex_, dcp::Channel channel_)
: regex(regex_)
, channel(channel_)
{}
string regex;
- int channel;
+ dcp::Channel channel;
};
@@ -99,19 +99,19 @@ void
AudioMapping::make_default(AudioProcessor const * processor, optional<boost::filesystem::path> filename)
{
static ChannelRegex const regex[] = {
- ChannelRegex(".*[\\._-]L[\\._-].*", 0),
- ChannelRegex(".*[\\._-]R[\\._-].*", 1),
- ChannelRegex(".*[\\._-]C[\\._-].*", 2),
- ChannelRegex(".*[\\._-]Lfe[\\._-].*", 3),
- ChannelRegex(".*[\\._-]LFE[\\._-].*", 3),
- ChannelRegex(".*[\\._-]Lss[\\._-].*", 4),
- ChannelRegex(".*[\\._-]Lsr[\\._-].*", 6),
- ChannelRegex(".*[\\._-]Lrs[\\._-].*", 6),
- ChannelRegex(".*[\\._-]Ls[\\._-].*", 4),
- ChannelRegex(".*[\\._-]Rss[\\._-].*", 5),
- ChannelRegex(".*[\\._-]Rsr[\\._-].*", 7),
- ChannelRegex(".*[\\._-]Rrs[\\._-].*", 7),
- ChannelRegex(".*[\\._-]Rs[\\._-].*", 5),
+ ChannelRegex(".*[\\._-]L[\\._-].*", dcp::Channel::LEFT),
+ ChannelRegex(".*[\\._-]R[\\._-].*", dcp::Channel::RIGHT),
+ ChannelRegex(".*[\\._-]C[\\._-].*", dcp::Channel::CENTRE),
+ ChannelRegex(".*[\\._-]Lfe[\\._-].*", dcp::Channel::LFE),
+ ChannelRegex(".*[\\._-]LFE[\\._-].*", dcp::Channel::LFE),
+ ChannelRegex(".*[\\._-]Lss[\\._-].*", dcp::Channel::LS),
+ ChannelRegex(".*[\\._-]Lsr[\\._-].*", dcp::Channel::BSL),
+ ChannelRegex(".*[\\._-]Lrs[\\._-].*", dcp::Channel::BSL),
+ ChannelRegex(".*[\\._-]Ls[\\._-].*", dcp::Channel::LS),
+ ChannelRegex(".*[\\._-]Rss[\\._-].*", dcp::Channel::RS),
+ ChannelRegex(".*[\\._-]Rsr[\\._-].*", dcp::Channel::BSR),
+ ChannelRegex(".*[\\._-]Rrs[\\._-].*", dcp::Channel::BSR),
+ ChannelRegex(".*[\\._-]Rs[\\._-].*", dcp::Channel::RS),
};
static int const regexes = sizeof(regex) / sizeof(*regex);
@@ -127,7 +127,7 @@ AudioMapping::make_default(AudioProcessor const * processor, optional<boost::fil
if (filename) {
for (int i = 0; i < regexes; ++i) {
boost::regex e(regex[i].regex, boost::regex::icase);
- if (boost::regex_match(filename->filename().string(), e) && regex[i].channel < output_channels()) {
+ if (boost::regex_match(filename->filename().string(), e) && static_cast<int>(regex[i].channel) < output_channels()) {
set(0, regex[i].channel, 1);
guessed = true;
}
diff --git a/src/lib/film.cc b/src/lib/film.cc
index b0276086a..de6343b9c 100644
--- a/src/lib/film.cc
+++ b/src/lib/film.cc
@@ -113,6 +113,7 @@ using namespace dcpomatic;
static constexpr char metadata_file[] = "metadata.xml";
static constexpr char ui_state_file[] = "ui.xml";
static constexpr char assets_file[] = "assets.xml";
+static constexpr char info_dir[] = "info";
/* 5 -> 6
@@ -289,7 +290,7 @@ boost::filesystem::path
Film::info_file(DCPTimePeriod period) const
{
boost::filesystem::path p;
- p /= "info";
+ p /= info_dir;
p /= video_identifier() + "_" + fmt::to_string(period.from.get()) + "_" + fmt::to_string(period.to.get());
return file(p);
}
@@ -1440,7 +1441,7 @@ Film::cpls() const
for (auto const& item: dcp::filesystem::directory_iterator(dir)) {
if (
dcp::filesystem::is_directory(item) &&
- item.path().filename() != "j2c" && item.path().filename() != "video" && item.path().filename() != "info" && item.path().filename() != "analysis"
+ item.path().filename() != "j2c" && item.path().filename() != "video" && item.path().filename() != info_dir && item.path().filename() != "analysis"
) {
try {
@@ -2204,12 +2205,35 @@ Film::speed_up_range(int dcp_frame_rate) const
return _playlist->speed_up_range(dcp_frame_rate);
}
+
void
-Film::copy_from(shared_ptr<const Film> film)
+Film::copy_from(shared_ptr<const Film> film, std::function<void (float)> set_progress)
{
read_metadata(film->file(metadata_file));
+
+ auto old_assets = film->read_remembered_assets();
+ auto new_assets = std::vector<RememberedAsset>{};
+
+ /* Find source film's remembered assets that still exist and copy them to our new film */
+ for (auto path: dcp::filesystem::recursive_directory_iterator(*film->directory())) {
+ auto iter = std::find_if(old_assets.begin(), old_assets.end(), [path](RememberedAsset const& asset) {
+ return asset.filename() == path.path().filename();
+ });
+ if (iter != old_assets.end()) {
+ copy_in_bits(path, assets_path() / path.path().filename(), set_progress);
+ new_assets.push_back({path.path().filename(), iter->period(), iter->identifier()});
+ }
+ }
+
+ write_remembered_assets(new_assets);
+
+ /* To use the assets we also need the info files */
+ for (auto path: dcp::filesystem::directory_iterator(film->dir(info_dir))) {
+ dcp::filesystem::copy_file(path.path(), dir(info_dir) / path.path().filename());
+ }
}
+
bool
Film::references_dcp_video() const
{
diff --git a/src/lib/film.h b/src/lib/film.h
index ae812f6d4..09b51202c 100644
--- a/src/lib/film.h
+++ b/src/lib/film.h
@@ -122,7 +122,7 @@ public:
void write_template(boost::filesystem::path path) const;
std::shared_ptr<xmlpp::Document> metadata(bool with_content_paths = true) const;
- void copy_from(std::shared_ptr<const Film> film);
+ void copy_from(std::shared_ptr<const Film> film, std::function<void (float)> set_progress);
std::string isdcf_name(bool if_created_now) const;
std::string dcp_name(bool if_created_now = false) const;
diff --git a/src/lib/image.cc b/src/lib/image.cc
index 4a07dcdca..3a2e99c23 100644
--- a/src/lib/image.cc
+++ b/src/lib/image.cc
@@ -612,17 +612,15 @@ Image::make_black()
case AV_PIX_FMT_UYVY422:
{
- int const Y = sample_size(0).height;
- int const X = line_size()[0];
- uint8_t* p = data()[0];
- for (int y = 0; y < Y; ++y) {
- for (int x = 0; x < X / 4; ++x) {
- *p++ = eight_bit_uv; // Cb
- *p++ = 0; // Y0
- *p++ = eight_bit_uv; // Cr
- *p++ = 0; // Y1
- }
- }
+ fill_memory(
+ data()[0],
+ sample_size(0).height * line_size()[0],
+ /* Cb/Cr is eight_bit_uv, Y0/Y1 is 0 */
+ static_cast<uint64_t>(eight_bit_uv) |
+ (static_cast<uint64_t>(eight_bit_uv) << 16) |
+ (static_cast<uint64_t>(eight_bit_uv) << 32) |
+ (static_cast<uint64_t>(eight_bit_uv) << 48)
+ );
break;
}
diff --git a/src/lib/memory_util.cc b/src/lib/memory_util.cc
index 00117855d..cf8842615 100644
--- a/src/lib/memory_util.cc
+++ b/src/lib/memory_util.cc
@@ -30,12 +30,52 @@ LIBDCP_ENABLE_WARNINGS
void *
-wrapped_av_malloc (size_t s)
+wrapped_av_malloc(size_t s)
{
- auto p = av_malloc (s);
+ auto p = av_malloc(s);
if (!p) {
- throw std::bad_alloc ();
+ throw std::bad_alloc();
}
return p;
}
+
+void
+fill_memory(void* ptr, size_t bytes, uint64_t value)
+{
+ if (bytes == 0) {
+ return;
+ }
+
+ auto const start = std::min(bytes, sizeof(value) - reinterpret_cast<uintptr_t>(ptr) % sizeof(value));
+ auto start_ptr = reinterpret_cast<uint8_t*>(ptr);
+ if (start < 8) {
+ for (auto i = 0UL; i < start; ++i) {
+ *start_ptr++ = value & 0xff;
+ value = (value >> 8) | ((value & 0xff) << 56);
+ }
+
+ bytes -= start;
+ if (bytes == 0) {
+ return;
+ }
+ }
+
+ auto const main = (bytes - (bytes % sizeof(value))) / 8;
+ auto main_ptr = reinterpret_cast<uint64_t*>(start_ptr);
+ for (auto i = 0UL; i < main; ++i) {
+ *main_ptr++ = value;
+ }
+
+ bytes -= main * 8;
+ if (bytes == 0) {
+ return;
+ }
+
+ auto end_ptr = reinterpret_cast<uint8_t*>(main_ptr);
+ for (auto i = 0UL; i < bytes; ++i) {
+ *end_ptr++ = value & 0xff;
+ value = (value >> 8) | ((value & 0xff) << 56);
+ }
+}
+
diff --git a/src/lib/memory_util.h b/src/lib/memory_util.h
index eccc4a857..f6bbe0621 100644
--- a/src/lib/memory_util.h
+++ b/src/lib/memory_util.h
@@ -19,4 +19,9 @@
*/
-extern void* wrapped_av_malloc (size_t);
+#include <cstddef>
+#include <cstdint>
+
+
+extern void* wrapped_av_malloc(size_t);
+extern void fill_memory(void* ptr, size_t bytes, uint64_t value);
diff --git a/src/lib/po/zh_CN.po b/src/lib/po/zh_CN.po
index a575f752b..db2ab4731 100644
--- a/src/lib/po/zh_CN.po
+++ b/src/lib/po/zh_CN.po
@@ -13,15 +13,15 @@ msgstr ""
"Project-Id-Version: LIBDCPOMATIC\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-04-19 23:03+0200\n"
-"PO-Revision-Date: 2025-10-05 13:31+0800\n"
+"PO-Revision-Date: 2026-05-17 10:45+0800\n"
"Last-Translator: Dian Li <xslidian@gmail.com>\n"
-"Language-Team: Chinese Simplified (Rov8 branch)\n"
+"Language-Team: Chinese Simplified (Hanyuan branch)\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Poedit 3.7\n"
+"X-Generator: Poedit 3.9\n"
"X-Poedit-SourceCharset: UTF-8\n"
#: src/lib/video_content.cc:515
@@ -207,7 +207,7 @@ msgid "; {} remaining; finishing at {}{}"
msgstr "; 剩余 {} ; 完成于 {}{}"
#: src/lib/analytics.cc:58
-#, fuzzy, c++-format
+#, c++-format
msgid ""
"<h2>You have made {} DCPs with {}!</h2><img width=\"150\" height=\"193\" "
"src=\"memory:me.jpg\" align=\"center\"><font size=\"+1\"><p>Hello. I'm Carl "
@@ -429,7 +429,7 @@ msgstr "中置"
#: src/lib/exceptions.cc:196
#, c++-format
msgid "CPL {} not found"
-msgstr ""
+msgstr "未找到CPL {}"
#: src/lib/job.cc:657
msgid "Cancelled"
@@ -461,6 +461,8 @@ msgid ""
"Check the server settings in the TMS tab of preferences, or un-tick \"Upload "
"DCP to TMS after creation\" if you do not want to upload your DCP."
msgstr ""
+"在首选项的TMS页面中检查服务器设置,或者您不想要上传DCP的话,则取消选中“制作"
+"DCP后上传到TMS)复选框"
#: src/lib/transcode_job.cc:106
msgid "Check their new settings, then try again."
@@ -682,9 +684,8 @@ msgid "Copying DCPs to {}"
msgstr "复制DCP到 {}"
#: src/lib/reel_writer.cc:194
-#, fuzzy
msgid "Copying existing asset"
-msgstr "检查现有的图像数据"
+msgstr "正在拷贝已经存在的资产"
#: src/lib/copy_to_drive_job.cc:58
#, c++-format
@@ -811,9 +812,9 @@ msgid "DCP sample rate"
msgstr "DCP 采样率"
#: src/lib/frame_rate_change.cc:93
-#, fuzzy, c++-format
+#, c++-format
msgid "DCP will contain 1 out of every {} frames of the content.\n"
-msgstr "将使用隔帧打包DCP。\n"
+msgstr "DCP 将包含内容中每 {} 帧中的 1 帧。\n"
#: src/lib/frame_rate_change.cc:103
#, c-format
@@ -904,9 +905,8 @@ msgstr "下载失败 ({} error {})"
#. TRANSLATORS: this is an abbreviation for "end credits", shown next to the pair of markers
#. "FFEC" and "LFEC" ({First, Last} Frame of End Credits)
#: src/lib/layout_markers.cc:145
-#, fuzzy
msgid "EC"
-msgstr "中置"
+msgstr "片尾字幕"
#: src/lib/frame_rate_change.cc:95
msgid "Each content frame will be doubled in the DCP.\n"
@@ -1128,7 +1128,7 @@ msgstr "IEC61966-2-4"
#. "FFOI" and "LFOI" ({First, Last} Frame of Intermission)
#: src/lib/layout_markers.cc:142
msgid "IN"
-msgstr ""
+msgstr "幕间休息"
#: src/lib/hints.cc:198
msgid "If you do use 25fps you should change your DCP standard to SMPTE."
@@ -1231,9 +1231,8 @@ msgstr "左环绕"
#. TRANSLATORS: this is an abbreviation for "moving credits", shown next to the pair of markers
#. "FFMC" and "LFMC" ({First, Last} Frame of Moving Credits)
#: src/lib/layout_markers.cc:148
-#, fuzzy
msgid "MC"
-msgstr "中置"
+msgstr "滚动字幕"
#: src/lib/mid_side_decoder.cc:39
msgid "Mid-side decoder"
@@ -1279,12 +1278,11 @@ msgstr "动态隔行补偿"
#: src/lib/dcp_content.cc:212
msgid "No ASSETMAP or ASSETMAP.xml file found: is this a DCP?"
-msgstr ""
+msgstr "未找到ASSETMAP或ASSETMAP.xml文件,这是一个DCP吗?"
#: src/lib/dcp_examiner.cc:115
-#, fuzzy
msgid "No CPLs found in DCP"
-msgstr "DCP中没有找到CPL文件。"
+msgstr "DCP中没有找到CPL文件"
#: src/lib/dcp_decoder.cc:114
msgid "No CPLs found in DCP."
@@ -1362,15 +1360,15 @@ msgstr "小波降噪"
#: src/lib/colour_conversion.cc:293
msgid "P3 D60 (~6000K)"
-msgstr ""
+msgstr "P3 D60 (~6000K)"
#: src/lib/colour_conversion.cc:292
msgid "P3 D65 (~6500K)"
-msgstr ""
+msgstr "P3 D65 (~6500K)"
#: src/lib/colour_conversion.cc:291
msgid "P3 DCI (~6300K)"
-msgstr ""
+msgstr "P3 DCI (~6300K)"
#: src/lib/util.cc:1111
#, c++-format
@@ -1412,9 +1410,8 @@ msgstr "右声道"
#. TRANSLATORS: this is an abbreviation for "ratings band", shown next to the pair of markers
#. "FFOB" and "LFOB" ({First, Last} Frame of Band)
#: src/lib/layout_markers.cc:136
-#, fuzzy
msgid "RB"
-msgstr "右声道"
+msgstr "评级"
#: src/lib/ffmpeg_content.cc:644
msgid "RGB / sRGB (IEC61966-2-1)"
@@ -1503,9 +1500,8 @@ msgid "SMPTE ST 2084 for 10, 12, 14 and 16 bit systems"
msgstr "SMPTE ST 2084 10, 12, 14和16 bit"
#: src/lib/ffmpeg_content.cc:660
-#, fuzzy
msgid "SMPTE ST 2128, IPT-C2"
-msgstr "SMPTE ST 428-1"
+msgstr "SMPTE ST 2128, IPT-C2"
#: src/lib/ffmpeg_content.cc:636
msgid "SMPTE ST 428-1"
@@ -1589,14 +1585,12 @@ msgstr ""
"这些文件现在将被重新检查,因此您可能需要检查它们的设置。"
#: src/lib/check_content_job.cc:94
-#, fuzzy
msgid ""
"Some files must be re-examined due to a bug fix in DCP-o-matic. You may "
"need to check their settings."
msgstr ""
-"有些文件在添加到项目后发生了更改\n"
-"\n"
-"这些文件现在将被重新检查,因此您可能需要检查它们的设置。"
+"由于 DCP-o-matic 中的一个漏洞修复,某些文件必须重新检查。您可能需要检查它们的"
+"设置。"
#: src/lib/hints.cc:622
#, c++-format
@@ -1622,6 +1616,9 @@ msgid ""
"in doubt, set everything (picture, sound and text) to be either encrypted or "
"not."
msgstr ""
+"你的一些内容是加密的,而有些则不是。虽然一些分销商(例如 Netflix)要求字幕不"
+"能加密(即使画面和声音可以加密),但其他分销商会对由此项目生成的 DCP 标记错"
+"误。如果不确定,请将所有内容(画面、声音和文字)设置为加密或不加密。"
#: src/lib/make_dcp.cc:69
msgid "Some of your content is missing"
@@ -1670,9 +1667,8 @@ msgstr "星期日"
#. TRANSLATORS: this is an abbreviation for "title credits", shown next to the pair of markers
#. "FFTC" and "LFTC" ({First, Last} Frame of Title Credits)
#: src/lib/layout_markers.cc:139
-#, fuzzy
msgid "TC"
-msgstr "中置"
+msgstr "标题字幕"
#: src/lib/dcp_content_type.cc:60
msgid "Teaser"
@@ -1987,11 +1983,11 @@ msgstr "YCOCG"
#: src/lib/ffmpeg_content.cc:661
msgid "YCgCo-R, even addition"
-msgstr ""
+msgstr "YCgCo-R,偶数叠加编码"
#: src/lib/ffmpeg_content.cc:662
msgid "YCgCo-R, odd addition"
-msgstr ""
+msgstr "YCgCo-R,奇数叠加编码"
#: src/lib/filter.cc:98
msgid "Yet Another Deinterlacing Filter"
@@ -2313,11 +2309,10 @@ msgstr "名字"
#. TRANSLATORS: this string will follow "Cannot reference this DCP: "
#: src/lib/dcp_content.cc:829
-#, fuzzy
msgid ""
"one of its closed caption reels has a non-zero entry point so it must be re-"
"written."
-msgstr "它的一个隐藏字幕有一个非零的时间点,因此必须重写。"
+msgstr "它的一个隐藏字幕卷有一个非零的起始点,因此必须重写。"
#. TRANSLATORS: this string will follow "Cannot reference this DCP: "
#: src/lib/dcp_content.cc:823
diff --git a/src/lib/reel_writer.cc b/src/lib/reel_writer.cc
index b85b53305..76c1f8124 100644
--- a/src/lib/reel_writer.cc
+++ b/src/lib/reel_writer.cc
@@ -591,6 +591,7 @@ ReelWriter::create_reel_sound(shared_ptr<dcp::Reel> reel, list<ReferencedReelAss
}
+/** @param ensure_closed_captions List of DCPTextTracks that we need to make sure exist in this reel */
void
ReelWriter::create_reel_text(
shared_ptr<dcp::Reel> reel,
@@ -630,17 +631,30 @@ ReelWriter::create_reel_text(
}
}
- for (auto const& i: _closed_caption_assets) {
- auto a = maybe_add_text<dcp::ReelInteropTextAsset, dcp::ReelSMPTETextAsset, dcp::ReelTextAsset>(
- i.second, dcp::TextType::CLOSED_CAPTION, duration, reel, _reel_index, _reel_count, _content_summary, refs, film(), _period, output_dcp, _text_only
+ for (auto iter = ensure_closed_captions.begin(); iter != ensure_closed_captions.end(); ) {
+ /* Find any asset we wrote for this track */
+ auto written_asset = _closed_caption_assets.find(*iter);
+
+ /* Try to make a reel asset out of either written_asset or one of the referenced assets */
+ auto asset = maybe_add_text<dcp::ReelInteropTextAsset, dcp::ReelSMPTETextAsset, dcp::ReelTextAsset>(
+ written_asset == _closed_caption_assets.end() ? shared_ptr<dcp::TextAsset>() : written_asset->second,
+ dcp::TextType::CLOSED_CAPTION, duration, reel, _reel_index, _reel_count, _content_summary, refs, film(), _period, output_dcp, _text_only
);
- DCPOMATIC_ASSERT(a);
- a->set_annotation_text(i.first.name);
- if (i.first.language) {
- a->set_language(i.first.language.get());
+
+ /* Fill in some details for the reel asset if we know them */
+ if (asset && written_asset != _closed_caption_assets.end()) {
+ asset->set_annotation_text(written_asset->first.name);
+ if (written_asset->first.language) {
+ asset->set_language(written_asset->first.language.get());
+ }
}
- ensure_closed_captions.erase(i.first);
+ if (asset) {
+ /* We made a reel asset for this track, so we don't need to worry about it any more */
+ iter = ensure_closed_captions.erase(iter);
+ } else {
+ ++iter;
+ }
}
/* Make empty tracks for anything we've been asked to ensure but that we haven't added */
diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc
index 691841bbc..4c1221d60 100644
--- a/src/tools/dcpomatic.cc
+++ b/src/tools/dcpomatic.cc
@@ -107,6 +107,7 @@ LIBDCP_DISABLE_WARNINGS
#include <wx/cmdline.h>
#include <wx/generic/aboutdlgg.h>
#include <wx/preferences.h>
+#include <wx/progdlg.h>
#include <wx/splash.h>
#include <wx/stdpaths.h>
#include <wx/wxhtml.h>
@@ -153,10 +154,10 @@ using namespace boost::placeholders;
class FilmChangedClosingDialog
{
public:
- explicit FilmChangedClosingDialog (string name)
+ explicit FilmChangedClosingDialog(string name)
: _dialog(
nullptr,
- wxString::Format(_("Save changes to film \"%s\" before closing?"), std_to_wx (name).data()),
+ wxString::Format(_("Save changes to film \"%s\" before closing?"), std_to_wx(name).data()),
/// TRANSLATORS: this is the heading for a dialog box, which tells the user that the current
/// project (Film) has been changed since it was last saved.
_("Film changed"),
@@ -168,7 +169,7 @@ public:
);
}
- int run ()
+ int run()
{
return _dialog.ShowModal();
}
@@ -181,10 +182,10 @@ private:
class FilmChangedDuplicatingDialog
{
public:
- explicit FilmChangedDuplicatingDialog (string name)
+ explicit FilmChangedDuplicatingDialog(string name)
: _dialog(
nullptr,
- wxString::Format(_("Save changes to film \"%s\" before duplicating?"), std_to_wx (name).data()),
+ wxString::Format(_("Save changes to film \"%s\" before duplicating?"), std_to_wx(name).data()),
/// TRANSLATORS: this is the heading for a dialog box, which tells the user that the current
/// project (Film) has been changed since it was last saved.
_("Film changed"),
@@ -196,7 +197,7 @@ public:
);
}
- int run ()
+ int run()
{
return _dialog.ShowModal();
}
@@ -310,8 +311,8 @@ private:
class DOMFrame : public wxFrame
{
public:
- explicit DOMFrame (wxString const& title)
- : wxFrame (nullptr, -1, title)
+ explicit DOMFrame(wxString const& title)
+ : wxFrame(nullptr, -1, title)
/* Use a panel as the only child of the Frame so that we avoid
the dark-grey background on Windows.
*/
@@ -320,11 +321,11 @@ public:
, _film_viewer(_right_panel, false)
{
auto bar = new wxMenuBar;
- setup_menu (bar);
- SetMenuBar (bar);
+ setup_menu(bar);
+ SetMenuBar(bar);
#ifdef DCPOMATIC_WINDOWS
- SetIcon (wxIcon (std_to_wx ("id")));
+ SetIcon(wxIcon(std_to_wx("id")));
#endif
_config_changed_connection = Config::instance()->Changed.connect(boost::bind(&DOMFrame::config_changed, this, _1));
@@ -332,46 +333,46 @@ public:
_analytics_message_connection = Analytics::instance()->Message.connect(boost::bind(&DOMFrame::analytics_message, this, _1, _2));
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_new, this), ID_file_new);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_open, this), ID_file_open);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_save, this), ID_file_save);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_save_as_template, this), ID_file_save_as_template);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_duplicate, this), ID_file_duplicate);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_duplicate_and_open, this), ID_file_duplicate_and_open);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_close, this), ID_file_close);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_history, this, _1), ID_file_history, ID_file_history + HISTORY_SIZE);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_exit, this), wxID_EXIT);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::edit_copy, this), ID_edit_copy);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::edit_paste, this), ID_edit_paste);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::edit_select_all, this), ID_edit_select_all);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::edit_preferences, this), wxID_PREFERENCES);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_make_dcp, this), ID_jobs_make_dcp);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_make_kdms, this), ID_jobs_make_kdms);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_make_dkdms, this), ID_jobs_make_dkdms);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_make_dcp_batch, this), ID_jobs_make_dcp_batch);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_make_self_dkdm, this), ID_jobs_make_self_dkdm);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_export_video_file, this), ID_jobs_export_video_file);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_export_subtitles, this), ID_jobs_export_subtitles);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_send_dcp_to_tms, this), ID_jobs_send_dcp_to_tms);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_show_dcp, this), ID_jobs_show_dcp);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_open_dcp_in_player, this), ID_jobs_open_dcp_in_player);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::view_closed_captions, this), ID_view_closed_captions);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::view_video_waveform, this), ID_view_video_waveform);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::tools_version_file, this), ID_tools_version_file);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::tools_hints, this), ID_tools_hints);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::tools_encoding_servers, this), ID_tools_encoding_servers);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::tools_manage_templates, this), ID_tools_manage_templates);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::tools_check_for_updates, this), ID_tools_check_for_updates);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::tools_system_information, this),ID_tools_system_information);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::tools_restore_default_preferences, this), ID_tools_restore_default_preferences);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::tools_export_preferences, this), ID_tools_export_preferences);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::tools_import_preferences, this), ID_tools_import_preferences);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::help_about, this), wxID_ABOUT);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::help_user_manual, this), ID_help_user_manual);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::help_report_a_problem, this), ID_help_report_a_problem);
-
- Bind (wxEVT_CLOSE_WINDOW, boost::bind (&DOMFrame::close, this, _1));
- Bind (wxEVT_SHOW, boost::bind (&DOMFrame::show, this, _1));
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::file_new, this), ID_file_new);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::file_open, this), ID_file_open);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::file_save, this), ID_file_save);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::file_save_as_template, this), ID_file_save_as_template);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::file_duplicate, this), ID_file_duplicate);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::file_duplicate_and_open, this), ID_file_duplicate_and_open);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::file_close, this), ID_file_close);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::file_history, this, _1), ID_file_history, ID_file_history + HISTORY_SIZE);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::file_exit, this), wxID_EXIT);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::edit_copy, this), ID_edit_copy);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::edit_paste, this), ID_edit_paste);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::edit_select_all, this), ID_edit_select_all);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::edit_preferences, this), wxID_PREFERENCES);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::jobs_make_dcp, this), ID_jobs_make_dcp);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::jobs_make_kdms, this), ID_jobs_make_kdms);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::jobs_make_dkdms, this), ID_jobs_make_dkdms);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::jobs_make_dcp_batch, this), ID_jobs_make_dcp_batch);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::jobs_make_self_dkdm, this), ID_jobs_make_self_dkdm);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::jobs_export_video_file, this), ID_jobs_export_video_file);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::jobs_export_subtitles, this), ID_jobs_export_subtitles);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::jobs_send_dcp_to_tms, this), ID_jobs_send_dcp_to_tms);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::jobs_show_dcp, this), ID_jobs_show_dcp);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::jobs_open_dcp_in_player, this), ID_jobs_open_dcp_in_player);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::view_closed_captions, this), ID_view_closed_captions);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::view_video_waveform, this), ID_view_video_waveform);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::tools_version_file, this), ID_tools_version_file);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::tools_hints, this), ID_tools_hints);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::tools_encoding_servers, this), ID_tools_encoding_servers);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::tools_manage_templates, this), ID_tools_manage_templates);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::tools_check_for_updates, this), ID_tools_check_for_updates);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::tools_system_information, this),ID_tools_system_information);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::tools_restore_default_preferences, this), ID_tools_restore_default_preferences);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::tools_export_preferences, this), ID_tools_export_preferences);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::tools_import_preferences, this), ID_tools_import_preferences);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::help_about, this), wxID_ABOUT);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::help_user_manual, this), ID_help_user_manual);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::help_report_a_problem, this), ID_help_report_a_problem);
+
+ Bind(wxEVT_CLOSE_WINDOW, boost::bind(&DOMFrame::close, this, _1));
+ Bind(wxEVT_SHOW, boost::bind(&DOMFrame::show, this, _1));
auto left_panel = new wxPanel(_splitter, wxID_ANY);
@@ -386,27 +387,27 @@ public:
_controls->set_film(_film_viewer.film());
auto job_manager_view = new JobManagerView(_right_panel, false);
- auto right_sizer = new wxBoxSizer (wxVERTICAL);
+ auto right_sizer = new wxBoxSizer(wxVERTICAL);
right_sizer->Add(_film_viewer.panel(), 2, wxEXPAND | wxALL, 6);
- right_sizer->Add (_controls, 0, wxEXPAND | wxALL, 6);
- right_sizer->Add (job_manager_view, 1, wxEXPAND | wxALL, 6);
+ right_sizer->Add(_controls, 0, wxEXPAND | wxALL, 6);
+ right_sizer->Add(job_manager_view, 1, wxEXPAND | wxALL, 6);
_right_panel->SetSizer(right_sizer);
_splitter->SplitVertically(left_panel, _right_panel, Config::instance()->main_divider_sash_position().get_value_or(left_panel->GetSize().GetWidth() + 8));
- set_menu_sensitivity ();
+ set_menu_sensitivity();
- _film_editor->content_panel()->SelectionChanged.connect (boost::bind (&DOMFrame::set_menu_sensitivity, this));
- set_title ();
+ _film_editor->content_panel()->SelectionChanged.connect(boost::bind(&DOMFrame::set_menu_sensitivity, this));
+ set_title();
JobManager::instance()->ActiveJobsChanged.connect(boost::bind(&DOMFrame::active_jobs_changed, this));
UpdateChecker::instance()->StateChanged.connect(boost::bind(&DOMFrame::update_checker_state_changed, this));
- FocusManager::instance()->SetFocus.connect (boost::bind (&DOMFrame::remove_accelerators, this));
- FocusManager::instance()->KillFocus.connect (boost::bind (&DOMFrame::add_accelerators, this));
- add_accelerators ();
+ FocusManager::instance()->SetFocus.connect(boost::bind(&DOMFrame::remove_accelerators, this));
+ FocusManager::instance()->KillFocus.connect(boost::bind(&DOMFrame::add_accelerators, this));
+ add_accelerators();
}
~DOMFrame()
@@ -415,7 +416,7 @@ public:
_video_waveform_dialog.reset();
}
- void add_accelerators ()
+ void add_accelerators()
{
#ifdef __WXOSX__
int accelerators = 7;
@@ -424,63 +425,63 @@ public:
#endif
std::vector<wxAcceleratorEntry> accel(accelerators);
/* [Shortcut] Ctrl+A:Add file(s) to the film */
- accel[0].Set (wxACCEL_CTRL, static_cast<int>('A'), ID_add_file);
+ accel[0].Set(wxACCEL_CTRL, static_cast<int>('A'), ID_add_file);
/* [Shortcut] Delete:Remove selected content from film */
- accel[1].Set (wxACCEL_NORMAL, WXK_DELETE, ID_remove);
+ accel[1].Set(wxACCEL_NORMAL, WXK_DELETE, ID_remove);
/* [Shortcut] Space:Start/stop playback */
- accel[2].Set (wxACCEL_NORMAL, WXK_SPACE, ID_start_stop);
+ accel[2].Set(wxACCEL_NORMAL, WXK_SPACE, ID_start_stop);
/* [Shortcut] Ctrl+T:Open timeline window */
- accel[3].Set (wxACCEL_CTRL, static_cast<int>('T'), ID_timeline);
+ accel[3].Set(wxACCEL_CTRL, static_cast<int>('T'), ID_timeline);
/* [Shortcut] Left arrow:Move back one frame */
- accel[4].Set (wxACCEL_NORMAL, WXK_LEFT, ID_back_frame);
+ accel[4].Set(wxACCEL_NORMAL, WXK_LEFT, ID_back_frame);
/* [Shortcut] Right arrow:Move forward one frame */
- accel[5].Set (wxACCEL_NORMAL, WXK_RIGHT, ID_forward_frame);
+ accel[5].Set(wxACCEL_NORMAL, WXK_RIGHT, ID_forward_frame);
#ifdef __WXOSX__
- accel[6].Set (wxACCEL_CTRL, static_cast<int>('W'), ID_file_close);
+ accel[6].Set(wxACCEL_CTRL, static_cast<int>('W'), ID_file_close);
#endif
- Bind (wxEVT_MENU, boost::bind (&ContentPanel::add_file_clicked, _film_editor->content_panel()), ID_add_file);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::remove_clicked, this, _1), ID_remove);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::start_stop_pressed, this), ID_start_stop);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::timeline_pressed, this), ID_timeline);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::back_frame, this), ID_back_frame);
- Bind (wxEVT_MENU, boost::bind (&DOMFrame::forward_frame, this), ID_forward_frame);
- wxAcceleratorTable accel_table (accelerators, accel.data());
- SetAcceleratorTable (accel_table);
+ Bind(wxEVT_MENU, boost::bind(&ContentPanel::add_file_clicked, _film_editor->content_panel()), ID_add_file);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::remove_clicked, this, _1), ID_remove);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::start_stop_pressed, this), ID_start_stop);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::timeline_pressed, this), ID_timeline);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::back_frame, this), ID_back_frame);
+ Bind(wxEVT_MENU, boost::bind(&DOMFrame::forward_frame, this), ID_forward_frame);
+ wxAcceleratorTable accel_table(accelerators, accel.data());
+ SetAcceleratorTable(accel_table);
}
- void remove_accelerators ()
+ void remove_accelerators()
{
- SetAcceleratorTable (wxAcceleratorTable ());
+ SetAcceleratorTable(wxAcceleratorTable());
}
- void remove_clicked (wxCommandEvent& ev)
+ void remove_clicked(wxCommandEvent& ev)
{
- if (_film_editor->content_panel()->remove_clicked (true)) {
- ev.Skip ();
+ if (_film_editor->content_panel()->remove_clicked(true)) {
+ ev.Skip();
}
}
/** Make a new film in the given path, using template_name as a template
* (or the default template if it's empty).
*/
- void new_film (boost::filesystem::path path, optional<string> template_name)
+ void new_film(boost::filesystem::path path, optional<string> template_name)
{
auto film = make_shared<Film>(path);
film->use_template(template_name);
- film->set_name (path.filename().generic_string());
- film->write_metadata ();
- set_film (film);
+ film->set_name(path.filename().generic_string());
+ film->write_metadata();
+ set_film(film);
}
- void load_film (boost::filesystem::path file)
+ void load_film(boost::filesystem::path file)
try
{
auto film = make_shared<Film>(file);
- auto const notes = film->read_metadata ();
+ auto const notes = film->read_metadata();
film->read_ui_state();
if (film->state_version() == 4) {
- error_dialog (
+ error_dialog(
0,
_("This film was created with an old version of DVD-o-matic and may not load correctly "
"in this version. Please check the film's settings carefully.")
@@ -488,53 +489,53 @@ public:
}
for (auto i: notes) {
- error_dialog (0, std_to_wx(i));
+ error_dialog(0, std_to_wx(i));
}
- set_film (film);
+ set_film(film);
JobManager::instance()->add(make_shared<CheckContentJob>(film));
}
catch (FileNotFoundError& e) {
auto const dir = e.file().parent_path();
if (dcp::filesystem::exists(dir / "ASSETMAP") || dcp::filesystem::exists(dir / "ASSETMAP.xml")) {
- error_dialog (
+ error_dialog(
this, variant::wx::insert_dcpomatic(_("Could not open this folder as a %s project.")),
variant::wx::insert_dcpomatic(
_("It looks like you are trying to open a DCP. File -> Open is for loading %s projects, not DCPs. "
"To import a DCP, create a new project with File -> New and then click the \"Add DCP...\" button."))
);
} else {
- auto const p = std_to_wx(file.string ());
- error_dialog (this, wxString::Format(_("Could not open film at %s"), p.data()), std_to_wx(e.what()));
+ auto const p = std_to_wx(file.string());
+ error_dialog(this, wxString::Format(_("Could not open film at %s"), p.data()), std_to_wx(e.what()));
}
} catch (std::exception& e) {
- auto const p = std_to_wx (file.string());
- error_dialog (this, wxString::Format(_("Could not open film at %s"), p.data()), std_to_wx(e.what()));
+ auto const p = std_to_wx(file.string());
+ error_dialog(this, wxString::Format(_("Could not open film at %s"), p.data()), std_to_wx(e.what()));
}
- void set_film (shared_ptr<Film> film)
+ void set_film(shared_ptr<Film> film)
{
_film = film;
_film_viewer.set_film(_film);
_film_editor->set_film(_film);
- _controls->set_film (_film);
+ _controls->set_film(_film);
_video_waveform_dialog.reset();
- set_menu_sensitivity ();
+ set_menu_sensitivity();
if (_film && _film->directory()) {
- Config::instance()->add_to_history (_film->directory().get());
+ Config::instance()->add_to_history(_film->directory().get());
}
if (_film) {
- _film->Change.connect (boost::bind (&DOMFrame::film_change, this, _1));
- _film->Message.connect (boost::bind(&DOMFrame::film_message, this, _1));
- _film->DirtyChange.connect (boost::bind(&DOMFrame::set_title, this));
- dcpomatic_log = _film->log ();
+ _film->Change.connect(boost::bind(&DOMFrame::film_change, this, _1));
+ _film->Message.connect(boost::bind(&DOMFrame::film_message, this, _1));
+ _film->DirtyChange.connect(boost::bind(&DOMFrame::set_title, this));
+ dcpomatic_log = _film->log();
}
- set_title ();
+ set_title();
}
- shared_ptr<Film> film () const {
+ shared_ptr<Film> film() const {
return _film;
}
@@ -543,7 +544,7 @@ private:
void show (wxShowEvent& ev)
{
if (ev.IsShown() && !_first_shown_called) {
- _film_editor->first_shown ();
+ _film_editor->first_shown();
_first_shown_called = true;
#ifdef DCPOMATIC_WORKAROUND_MUTTER
signal_manager->when_idle([this]() { Maximize(); });
@@ -551,19 +552,19 @@ private:
}
}
- void film_message (string m)
+ void film_message(string m)
{
- message_dialog (this, std_to_wx(m));
+ message_dialog(this, std_to_wx(m));
}
- void film_change (ChangeType type)
+ void film_change(ChangeType type)
{
if (type == ChangeType::DONE) {
- set_menu_sensitivity ();
+ set_menu_sensitivity();
}
}
- void file_new ()
+ void file_new()
{
FilmNameLocationDialog dialog(this, _("New Film"), true);
int const r = dialog.ShowModal();
@@ -587,23 +588,23 @@ private:
wxString message = _("Could not create folder to store film.");
message += char_to_wx(" ");
if (!found_bad_chars.empty()) {
- message += wxString::Format (_("Try removing the %s characters from your folder name."), std_to_wx(found_bad_chars).data());
+ message += wxString::Format(_("Try removing the %s characters from your folder name."), std_to_wx(found_bad_chars).data());
} else {
message += variant::wx::insert_dcpomatic(_("Please check that you do not have Windows controlled folder access enabled for %s."));
}
- error_dialog (this, message, std_to_wx(e.what()));
+ error_dialog(this, message, std_to_wx(e.what()));
#else
- error_dialog (this, _("Could not create folder to store film."), std_to_wx(e.what()));
+ error_dialog(this, _("Could not create folder to store film."), std_to_wx(e.what()));
#endif
}
}
- void file_open ()
+ void file_open()
{
wxDirDialog dialog(
this,
_("Select film to open"),
- std_to_wx (Config::instance()->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()),
+ std_to_wx(Config::instance()->default_directory_or(wx_to_std(wxStandardPaths::Get().GetDocumentsDir())).string()),
wxDEFAULT_DIALOG_STYLE | wxDD_DIR_MUST_EXIST
);
@@ -611,7 +612,7 @@ private:
while (true) {
r = dialog.ShowModal();
if (r == wxID_OK && dialog.GetPath() == wxStandardPaths::Get().GetDocumentsDir()) {
- error_dialog (this, _("You did not select a folder. Make sure that you select a folder before clicking Open."));
+ error_dialog(this, _("You did not select a folder. Make sure that you select a folder before clicking Open."));
} else {
break;
}
@@ -622,16 +623,16 @@ private:
}
}
- void file_save ()
+ void file_save()
{
try {
- _film->write_metadata ();
+ _film->write_metadata();
} catch (exception& e) {
error_dialog(this, _("Could not save project."), std_to_wx(e.what()));
}
}
- void file_save_as_template ()
+ void file_save_as_template()
{
SaveTemplateDialog dialog(this);
if (dialog.ShowModal() == wxID_OK) {
@@ -647,13 +648,16 @@ private:
}
}
- void file_duplicate ()
+ void file_duplicate()
{
FilmNameLocationDialog dialog(this, _("Duplicate Film"), false);
if (dialog.ShowModal() == wxID_OK && dialog.check_path() && maybe_save_film<FilmChangedDuplicatingDialog>()) {
auto film = make_shared<Film>(dialog.path());
- film->copy_from (_film);
+ wxProgressDialog progress(variant::wx::dcpomatic(), _("Duplicating film"));
+ film->copy_from(_film, [&progress](float value) {
+ progress.Update(value * 100);
+ });
film->set_name(dialog.path().filename().generic_string());
try {
film->write_metadata();
@@ -663,26 +667,29 @@ private:
}
}
- void file_duplicate_and_open ()
+ void file_duplicate_and_open()
{
FilmNameLocationDialog dialog(this, _("Duplicate Film"), false);
if (dialog.ShowModal() == wxID_OK && dialog.check_path() && maybe_save_film<FilmChangedDuplicatingDialog>()) {
auto film = make_shared<Film>(dialog.path());
- film->copy_from (_film);
+ wxProgressDialog progress(variant::wx::dcpomatic(), _("Duplicating film"));
+ film->copy_from(_film, [&progress](float value) {
+ progress.Update(value * 100);
+ });
film->set_name(dialog.path().filename().generic_string());
try {
- film->write_metadata ();
- set_film (film);
+ film->write_metadata();
+ set_film(film);
} catch (exception& e) {
error_dialog(this, _("Could not duplicate project."), std_to_wx(e.what()));
}
}
}
- void file_close ()
+ void file_close()
{
- if (_film && _film->dirty ()) {
+ if (_film && _film->dirty()) {
FilmChangedClosingDialog dialog(_film->name());
switch (dialog.run()) {
case wxID_NO:
@@ -690,7 +697,7 @@ private:
break;
case wxID_YES:
/* Save and carry on to close */
- _film->write_metadata ();
+ _film->write_metadata();
break;
case wxID_CANCEL:
/* Stop */
@@ -698,25 +705,25 @@ private:
}
}
- set_film (shared_ptr<Film>());
+ set_film(shared_ptr<Film>());
}
- void file_history (wxCommandEvent& event)
+ void file_history(wxCommandEvent& event)
{
- auto history = Config::instance()->history ();
+ auto history = Config::instance()->history();
int n = event.GetId() - ID_file_history;
- if (n >= 0 && n < static_cast<int> (history.size ()) && maybe_save_then_delete_film<FilmChangedClosingDialog>()) {
- load_film (history[n]);
+ if (n >= 0 && n < static_cast<int>(history.size()) && maybe_save_then_delete_film<FilmChangedClosingDialog>()) {
+ load_film(history[n]);
}
}
- void file_exit ()
+ void file_exit()
{
/* false here allows the close handler to veto the close request */
- Close (false);
+ Close(false);
}
- void edit_copy ()
+ void edit_copy()
{
auto const sel = _film_editor->content_panel()->selected();
if (sel.size() == 1) {
@@ -724,7 +731,7 @@ private:
}
}
- void edit_paste ()
+ void edit_paste()
{
if (!_clipboard) {
return;
@@ -737,19 +744,19 @@ private:
for (auto i: _film_editor->content_panel()->selected()) {
if (dialog.video() && i->video) {
- DCPOMATIC_ASSERT (_clipboard->video);
- i->video->take_settings_from (_clipboard->video);
+ DCPOMATIC_ASSERT(_clipboard->video);
+ i->video->take_settings_from(_clipboard->video);
}
if (dialog.audio() && i->audio) {
- DCPOMATIC_ASSERT (_clipboard->audio);
- i->audio->take_settings_from (_clipboard->audio);
+ DCPOMATIC_ASSERT(_clipboard->audio);
+ i->audio->take_settings_from(_clipboard->audio);
}
if (dialog.text()) {
- auto j = i->text.begin ();
- auto k = _clipboard->text.begin ();
+ auto j = i->text.begin();
+ auto k = _clipboard->text.begin();
while (j != i->text.end() && k != _clipboard->text.end()) {
- (*j)->take_settings_from (*k);
+ (*j)->take_settings_from(*k);
++j;
++k;
}
@@ -757,20 +764,20 @@ private:
}
}
- void edit_select_all ()
+ void edit_select_all()
{
_film_editor->content_panel()->select_all();
}
- void edit_preferences ()
+ void edit_preferences()
{
if (!_config_dialog) {
- _config_dialog = create_full_config_dialog ();
+ _config_dialog = create_full_config_dialog();
}
- _config_dialog->Show (this);
+ _config_dialog->Show(this);
}
- void tools_restore_default_preferences ()
+ void tools_restore_default_preferences()
{
wxMessageDialog dialog(
nullptr,
@@ -780,11 +787,11 @@ private:
);
if (dialog.ShowModal() == wxID_YES) {
- Config::restore_defaults ();
+ Config::restore_defaults();
}
}
- void tools_export_preferences ()
+ void tools_export_preferences()
{
FileDialog dialog(
this, _("Specify ZIP file"), char_to_wx("ZIP files (*.zip)|*.zip"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT, "Preferences", string("dcpomatic_config.zip")
@@ -827,14 +834,14 @@ private:
Config::instance()->load_from_zip(dialog.path(), action);
}
- void jobs_make_dcp ()
+ void jobs_make_dcp()
{
double required;
double available;
if (!_film->should_be_enough_disk_space(required, available)) {
auto const message = wxString::Format(_("The DCP for this film will take up about %.1f GB, and the disk that you are using only has %.1f GB available. Do you want to continue anyway?"), required, available);
- if (!confirm_dialog (this, message)) {
+ if (!confirm_dialog(this, message)) {
return;
}
}
@@ -846,8 +853,8 @@ private:
}
}
- if (_film->encrypted ()) {
- NagDialog::maybe_nag (
+ if (_film->encrypted()) {
+ NagDialog::maybe_nag(
this,
Config::NAG_ENCRYPTED_METADATA,
_("You are making an encrypted DCP. It will not be possible to make KDMs for this DCP unless you have copies of "
@@ -858,9 +865,9 @@ private:
}
/* Remove any existing DCP if the user agrees */
- auto const dcp_dir = _film->dir (_film->dcp_name(), false);
+ auto const dcp_dir = _film->dir(_film->dcp_name(), false);
if (dcp::filesystem::exists(dcp_dir)) {
- if (!confirm_dialog (this, wxString::Format (_("Do you want to overwrite the existing DCP %s?"), std_to_wx(dcp_dir.string()).data()))) {
+ if (!confirm_dialog(this, wxString::Format(_("Do you want to overwrite the existing DCP %s?"), std_to_wx(dcp_dir.string()).data()))) {
return;
}
@@ -872,37 +879,37 @@ private:
/* It seems to make sense to auto-save metadata here, since the make DCP may last
a long time, and crashes/power failures are moderately likely.
*/
- _film->write_metadata ();
- make_dcp (_film, TranscodeJob::ChangedBehaviour::EXAMINE_THEN_STOP);
+ _film->write_metadata();
+ make_dcp(_film, TranscodeJob::ChangedBehaviour::EXAMINE_THEN_STOP);
} catch (BadSettingError& e) {
- error_dialog (this, wxString::Format (_("Bad setting for %s."), std_to_wx(e.setting()).data()), std_to_wx(e.what()));
+ error_dialog(this, wxString::Format(_("Bad setting for %s."), std_to_wx(e.setting()).data()), std_to_wx(e.what()));
} catch (std::exception& e) {
- error_dialog (this, wxString::Format (_("Could not make DCP.")), std_to_wx(e.what()));
+ error_dialog(this, wxString::Format(_("Could not make DCP.")), std_to_wx(e.what()));
}
}
- void jobs_make_kdms ()
+ void jobs_make_kdms()
{
if (!_film) {
return;
}
_kdm_dialog.reset(this, _film);
- _kdm_dialog->Show ();
+ _kdm_dialog->Show();
}
- void jobs_make_dkdms ()
+ void jobs_make_dkdms()
{
if (!_film) {
return;
}
_dkdm_dialog.reset(this, _film);
- _dkdm_dialog->Show ();
+ _dkdm_dialog->Show();
}
/** @return false if we succeeded, true if not */
- bool send_to_other_tool (int port, function<void()> start, string message)
+ bool send_to_other_tool(int port, function<void()> start, string message)
{
/* i = 0; try to connect via socket
i = 1; try again, and then try to start the tool
@@ -910,30 +917,30 @@ private:
*/
for (int i = 0; i < 8; ++i) {
try {
- Socket socket (5);
+ Socket socket(5);
socket.connect("127.0.0.1", port);
- DCPOMATIC_ASSERT (_film->directory ());
- socket.write (message.length() + 1);
- socket.write ((uint8_t *) message.c_str(), message.length() + 1);
+ DCPOMATIC_ASSERT(_film->directory());
+ socket.write(message.length() + 1);
+ socket.write((uint8_t *) message.c_str(), message.length() + 1);
/* OK\0 */
uint8_t ok[3];
- socket.read (ok, 3);
+ socket.read(ok, 3);
return false;
} catch (exception& e) {
}
if (i == 1) {
- start ();
+ start();
}
- dcpomatic_sleep_seconds (1);
+ dcpomatic_sleep_seconds(1);
}
return true;
}
- void jobs_make_dcp_batch ()
+ void jobs_make_dcp_batch()
{
if (!_film) {
return;
@@ -946,33 +953,33 @@ private:
}
}
- _film->write_metadata ();
+ _film->write_metadata();
- if (send_to_other_tool (BATCH_JOB_PORT, &start_batch_converter, _film->directory()->string())) {
+ if (send_to_other_tool(BATCH_JOB_PORT, &start_batch_converter, _film->directory()->string())) {
#ifdef DCPOMATIC_OSX
- error_dialog (this, _("Could not start the batch converter. You may need to download it from dcpomatic.com."));
+ error_dialog(this, _("Could not start the batch converter. You may need to download it from dcpomatic.com."));
#else
- error_dialog (this, _("Could not find batch converter."));
+ error_dialog(this, _("Could not find batch converter."));
#endif
}
}
- void jobs_open_dcp_in_player ()
+ void jobs_open_dcp_in_player()
{
if (!_film) {
return;
}
- if (send_to_other_tool (PLAYER_PLAY_PORT, &start_player, _film->dir(_film->dcp_name(false)).string())) {
+ if (send_to_other_tool(PLAYER_PLAY_PORT, &start_player, _film->dir(_film->dcp_name(false)).string())) {
#ifdef DCPOMATIC_OSX
- error_dialog (this, _("Could not start the player. You may need to download it from dcpomatic.com."));
+ error_dialog(this, _("Could not start the player. You may need to download it from dcpomatic.com."));
#else
- error_dialog (this, _("Could not find player."));
+ error_dialog(this, _("Could not find player."));
#endif
}
}
- void jobs_make_self_dkdm ()
+ void jobs_make_self_dkdm()
{
if (!_film) {
return;
@@ -983,10 +990,10 @@ private:
return;
}
- NagDialog::maybe_nag (
+ NagDialog::maybe_nag(
this,
Config::NAG_DKDM_CONFIG,
- wxString::Format (
+ wxString::Format(
_("You are making a DKDM which is encrypted by a private key held in"
"\n\n<tt>%s</tt>\n\nIt is <span weight=\"bold\" size=\"larger\">VITALLY IMPORTANT</span> "
"that you <span weight=\"bold\" size=\"larger\">BACK UP THIS FILE</span> since if it is lost "
@@ -995,10 +1002,10 @@ private:
);
- dcp::LocalTime from (Config::instance()->signer_chain()->leaf().not_before());
- from.add_days (1);
- dcp::LocalTime to (Config::instance()->signer_chain()->leaf().not_after());
- to.add_days (-1);
+ dcp::LocalTime from(Config::instance()->signer_chain()->leaf().not_before());
+ from.add_days(1);
+ dcp::LocalTime to(Config::instance()->signer_chain()->leaf().not_after());
+ to.add_days(-1);
auto signer = Config::instance()->signer_chain();
if (!signer->valid()) {
@@ -1013,22 +1020,22 @@ private:
if (dialog.internal()) {
auto dkdms = Config::instance()->dkdms();
dkdms->add(make_shared<DKDM>(kdm));
- Config::instance()->changed ();
+ Config::instance()->changed();
} else {
auto path = dialog.directory() / (_film->dcp_name(false) + "_DKDM.xml");
kdm.as_xml(path);
}
} catch (dcp::NotEncryptedError& e) {
- error_dialog (this, _("CPL's content is not encrypted."));
+ error_dialog(this, _("CPL's content is not encrypted."));
} catch (exception& e) {
error_dialog(this, std_to_wx(e.what()));
} catch (...) {
- error_dialog (this, _("An unknown exception occurred."));
+ error_dialog(this, _("An unknown exception occurred."));
}
}
- void jobs_export_video_file ()
+ void jobs_export_video_file()
{
ExportVideoFileDialog dialog(this, _film->isdcf_name(true));
if (dialog.ShowModal() != wxID_OK) {
@@ -1047,15 +1054,15 @@ private:
}
auto job = make_shared<TranscodeJob>(_film, TranscodeJob::ChangedBehaviour::EXAMINE_THEN_STOP);
- job->set_encoder (
+ job->set_encoder(
make_shared<FFmpegFilmEncoder>(
_film, job, dialog.path(), dialog.format(), dialog.mixdown_to_stereo(), dialog.split_reels(), dialog.split_streams(), dialog.x264_crf())
);
- JobManager::instance()->add (job);
+ JobManager::instance()->add(job);
}
- void jobs_export_subtitles ()
+ void jobs_export_subtitles()
{
ExportSubtitlesDialog dialog(this, _film->reels().size(), _film->interop());
if (dialog.ShowModal() != wxID_OK) {
@@ -1077,40 +1084,40 @@ private:
}
- void jobs_send_dcp_to_tms ()
+ void jobs_send_dcp_to_tms()
{
- _film->send_dcp_to_tms ();
+ _film->send_dcp_to_tms();
}
- void jobs_show_dcp ()
+ void jobs_show_dcp()
{
- DCPOMATIC_ASSERT (_film->directory ());
+ DCPOMATIC_ASSERT(_film->directory());
if (show_in_file_manager(_film->directory().get(), _film->dir(_film->dcp_name(false)))) {
- error_dialog (this, _("Could not show DCP."));
+ error_dialog(this, _("Could not show DCP."));
}
}
- void view_closed_captions ()
+ void view_closed_captions()
{
- _film_viewer.show_closed_captions ();
+ _film_viewer.show_closed_captions();
}
- void view_video_waveform ()
+ void view_video_waveform()
{
if (!_video_waveform_dialog) {
_video_waveform_dialog.reset(this, _film, _film_viewer);
}
- _video_waveform_dialog->Show ();
+ _video_waveform_dialog->Show();
}
- void tools_system_information ()
+ void tools_system_information()
{
if (!_system_information_dialog) {
- _system_information_dialog = new SystemInformationDialog (this, _film_viewer);
+ _system_information_dialog = new SystemInformationDialog(this, _film_viewer);
}
- _system_information_dialog->Show ();
+ _system_information_dialog->Show();
}
void tools_version_file()
@@ -1124,40 +1131,40 @@ private:
_dcp_referencing_dialog->Show();
}
- void tools_hints ()
+ void tools_hints()
{
if (!_hints_dialog) {
- _hints_dialog = new HintsDialog (this, _film, true);
+ _hints_dialog = new HintsDialog(this, _film, true);
}
- _hints_dialog->Show ();
+ _hints_dialog->Show();
}
- void tools_encoding_servers ()
+ void tools_encoding_servers()
{
if (!_servers_list_dialog) {
- _servers_list_dialog = new ServersListDialog (this);
+ _servers_list_dialog = new ServersListDialog(this);
}
- _servers_list_dialog->Show ();
+ _servers_list_dialog->Show();
}
- void tools_manage_templates ()
+ void tools_manage_templates()
{
if (!_templates_dialog) {
_templates_dialog.reset(this);
}
- _templates_dialog->Show ();
+ _templates_dialog->Show();
}
- void tools_check_for_updates ()
+ void tools_check_for_updates()
{
_update_news_requested = true;
UpdateChecker::instance()->run();
}
- void help_about ()
+ void help_about()
{
AboutDialog dialog(this);
dialog.ShowModal();
@@ -1168,7 +1175,7 @@ private:
wxLaunchDefaultBrowser(std_to_wx("https://dcpomatic.com/manual"));
}
- void help_report_a_problem ()
+ void help_report_a_problem()
{
ReportProblemDialog dialog(this, _film);
if (dialog.ShowModal() == wxID_OK) {
@@ -1176,9 +1183,9 @@ private:
}
}
- bool should_close ()
+ bool should_close()
{
- if (!JobManager::instance()->work_to_do ()) {
+ if (!JobManager::instance()->work_to_do()) {
return true;
}
@@ -1192,14 +1199,14 @@ private:
return dialog.ShowModal() == wxID_YES;
}
- void close (wxCloseEvent& ev)
+ void close(wxCloseEvent& ev)
{
- if (!should_close ()) {
- ev.Veto ();
+ if (!should_close()) {
+ ev.Veto();
return;
}
- if (_film && _film->dirty ()) {
+ if (_film && _film->dirty()) {
FilmChangedClosingDialog dialog(_film->name());
switch (dialog.run()) {
case wxID_NO:
@@ -1207,11 +1214,11 @@ private:
break;
case wxID_YES:
/* Save and carry on to close */
- _film->write_metadata ();
+ _film->write_metadata();
break;
case wxID_CANCEL:
/* Veto the event and stop */
- ev.Veto ();
+ ev.Veto();
return;
}
}
@@ -1220,15 +1227,15 @@ private:
cause the File menu to be altered, which itself will be deleted around
now (without, as far as I can see, any way for us to find out).
*/
- _config_changed_connection.disconnect ();
+ _config_changed_connection.disconnect();
/* Also stop hearing about analytics-related stuff */
- _analytics_message_connection.disconnect ();
+ _analytics_message_connection.disconnect();
FontConfig::drop();
- ev.Skip ();
- JobManager::drop ();
+ ev.Skip();
+ JobManager::drop();
}
void active_jobs_changed()
@@ -1240,16 +1247,16 @@ private:
signal_manager->when_idle(boost::bind(&DOMFrame::set_menu_sensitivity, this));
}
- void set_menu_sensitivity ()
+ void set_menu_sensitivity()
{
- auto jobs = JobManager::instance()->get ();
+ auto jobs = JobManager::instance()->get();
auto const dcp_creation = std::any_of(
jobs.begin(),
jobs.end(),
[](shared_ptr<const Job> job) {
return dynamic_pointer_cast<const DCPTranscodeJob>(job) && !job->finished();
});
- bool const have_cpl = _film && !_film->cpls().empty ();
+ bool const have_cpl = _film && !_film->cpls().empty();
bool const have_single_selected_content = _film_editor->content_panel()->selected().size() == 1;
bool const have_selected_content = !_film_editor->content_panel()->selected().empty();
bool const have_selected_video_content = !_film_editor->content_panel()->selected_video().empty();
@@ -1301,7 +1308,7 @@ private:
enabled = false;
}
- j.first->Enable (enabled);
+ j.first->Enable(enabled);
}
}
@@ -1309,7 +1316,7 @@ private:
* should continue, false to abort it.
*/
template <class T>
- bool maybe_save_film ()
+ bool maybe_save_film()
{
if (!_film) {
return true;
@@ -1338,131 +1345,131 @@ private:
}
template <class T>
- bool maybe_save_then_delete_film ()
+ bool maybe_save_then_delete_film()
{
- bool const r = maybe_save_film<T> ();
+ bool const r = maybe_save_film<T>();
if (r) {
- _film.reset ();
+ _film.reset();
}
return r;
}
- void add_item (wxMenu* menu, wxString text, int id, int sens)
+ void add_item(wxMenu* menu, wxString text, int id, int sens)
{
- auto item = menu->Append (id, text);
- menu_items.insert (make_pair (item, sens));
+ auto item = menu->Append(id, text);
+ menu_items.insert(make_pair(item, sens));
}
- void setup_menu (wxMenuBar* m)
+ void setup_menu(wxMenuBar* m)
{
_file_menu = new wxMenu;
/* [Shortcut] Ctrl+N:New film */
- add_item (_file_menu, _("New...\tCtrl-N"), ID_file_new, ALWAYS);
+ add_item(_file_menu, _("New...\tCtrl-N"), ID_file_new, ALWAYS);
/* [Shortcut] Ctrl+O:Open existing film */
- add_item (_file_menu, _("&Open...\tCtrl-O"), ID_file_open, ALWAYS);
- _file_menu->AppendSeparator ();
+ add_item(_file_menu, _("&Open...\tCtrl-O"), ID_file_open, ALWAYS);
+ _file_menu->AppendSeparator();
/* [Shortcut] Ctrl+S:Save current film */
- add_item (_file_menu, _("&Save\tCtrl-S"), ID_file_save, NEEDS_FILM);
- _file_menu->AppendSeparator ();
- add_item (_file_menu, _("Save as &template..."), ID_file_save_as_template, NEEDS_FILM);
- add_item (_file_menu, _("Duplicate..."), ID_file_duplicate, NEEDS_FILM);
- add_item (_file_menu, _("Duplicate and open..."), ID_file_duplicate_and_open, NEEDS_FILM);
+ add_item(_file_menu, _("&Save\tCtrl-S"), ID_file_save, NEEDS_FILM);
+ _file_menu->AppendSeparator();
+ add_item(_file_menu, _("Save as &template..."), ID_file_save_as_template, NEEDS_FILM);
+ add_item(_file_menu, _("Duplicate..."), ID_file_duplicate, NEEDS_FILM);
+ add_item(_file_menu, _("Duplicate and open..."), ID_file_duplicate_and_open, NEEDS_FILM);
_history_position = _file_menu->GetMenuItems().GetCount();
- _file_menu->AppendSeparator ();
+ _file_menu->AppendSeparator();
/* [Shortcut] Ctrl+W:Close current film */
- add_item (_file_menu, _("&Close\tCtrl-W"), ID_file_close, NEEDS_FILM);
+ add_item(_file_menu, _("&Close\tCtrl-W"), ID_file_close, NEEDS_FILM);
#ifndef __WXOSX__
- _file_menu->AppendSeparator ();
+ _file_menu->AppendSeparator();
#endif
#ifdef __WXOSX__
- add_item (_file_menu, _("&Exit"), wxID_EXIT, ALWAYS);
+ add_item(_file_menu, _("&Exit"), wxID_EXIT, ALWAYS);
#else
- add_item (_file_menu, _("&Quit"), wxID_EXIT, ALWAYS);
+ add_item(_file_menu, _("&Quit"), wxID_EXIT, ALWAYS);
#endif
auto edit = new wxMenu;
/* [Shortcut] Ctrl+C:Copy settings from currently selected content */
- add_item (edit, _("Copy settings\tCtrl-C"), ID_edit_copy, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_SINGLE_SELECTED_CONTENT);
+ add_item(edit, _("Copy settings\tCtrl-C"), ID_edit_copy, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_SINGLE_SELECTED_CONTENT);
/* [Shortcut] Ctrl+V:Paste settings into currently selected content */
- add_item (edit, _("Paste settings...\tCtrl-V"), ID_edit_paste, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_SELECTED_CONTENT | NEEDS_CLIPBOARD);
- edit->AppendSeparator ();
+ add_item(edit, _("Paste settings...\tCtrl-V"), ID_edit_paste, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_SELECTED_CONTENT | NEEDS_CLIPBOARD);
+ edit->AppendSeparator();
/* [Shortcut] Shift+Ctrl+A:Select all content */
- add_item (edit, _("Select all\tShift-Ctrl-A"), ID_edit_select_all, NEEDS_FILM);
+ add_item(edit, _("Select all\tShift-Ctrl-A"), ID_edit_select_all, NEEDS_FILM);
#ifdef __WXOSX__
add_item(_file_menu, _("&Preferences...\tCtrl-,"), wxID_PREFERENCES, ALWAYS);
#else
- edit->AppendSeparator ();
+ edit->AppendSeparator();
/* [Shortcut] Ctrl+P:Open preferences window */
- add_item (edit, _("&Preferences...\tCtrl-P"), wxID_PREFERENCES, ALWAYS);
+ add_item(edit, _("&Preferences...\tCtrl-P"), wxID_PREFERENCES, ALWAYS);
#endif
auto jobs_menu = new wxMenu;
/* [Shortcut] Ctrl+M:Make DCP */
- add_item (jobs_menu, _("&Make DCP\tCtrl-M"), ID_jobs_make_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION);
+ add_item(jobs_menu, _("&Make DCP\tCtrl-M"), ID_jobs_make_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION);
/* [Shortcut] Ctrl+B:Make DCP in the batch converter*/
- add_item (jobs_menu, _("Make DCP in &batch converter\tCtrl-B"), ID_jobs_make_dcp_batch, NEEDS_FILM | NOT_DURING_DCP_CREATION);
- jobs_menu->AppendSeparator ();
+ add_item(jobs_menu, _("Make DCP in &batch converter\tCtrl-B"), ID_jobs_make_dcp_batch, NEEDS_FILM | NOT_DURING_DCP_CREATION);
+ jobs_menu->AppendSeparator();
/* [Shortcut] Ctrl+K:Make KDMs */
- add_item (jobs_menu, _("Make &KDMs...\tCtrl-K"), ID_jobs_make_kdms, NEEDS_FILM);
+ add_item(jobs_menu, _("Make &KDMs...\tCtrl-K"), ID_jobs_make_kdms, NEEDS_FILM);
/* [Shortcut] Ctrl+D:Make DKDMs */
- add_item (jobs_menu, _("Make &DKDMs...\tCtrl-D"), ID_jobs_make_dkdms, NEEDS_FILM);
+ add_item(jobs_menu, _("Make &DKDMs...\tCtrl-D"), ID_jobs_make_dkdms, NEEDS_FILM);
add_item(jobs_menu, variant::wx::insert_dcpomatic(_("Make DKDM for %s...")), ID_jobs_make_self_dkdm, NEEDS_FILM | NEEDS_ENCRYPTION);
- jobs_menu->AppendSeparator ();
+ jobs_menu->AppendSeparator();
/* [Shortcut] Ctrl+E:Export video file */
- add_item (jobs_menu, _("Export video file...\tCtrl-E"), ID_jobs_export_video_file, NEEDS_FILM);
- add_item (jobs_menu, _("Export subtitles...\tShift-Ctrl-E"), ID_jobs_export_subtitles, NEEDS_FILM);
- jobs_menu->AppendSeparator ();
- add_item (jobs_menu, _("&Send DCP to TMS"), ID_jobs_send_dcp_to_tms, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_CPL);
+ add_item(jobs_menu, _("Export video file...\tCtrl-E"), ID_jobs_export_video_file, NEEDS_FILM);
+ add_item(jobs_menu, _("Export subtitles...\tShift-Ctrl-E"), ID_jobs_export_subtitles, NEEDS_FILM);
+ jobs_menu->AppendSeparator();
+ add_item(jobs_menu, _("&Send DCP to TMS"), ID_jobs_send_dcp_to_tms, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_CPL);
#if defined(DCPOMATIC_OSX)
- add_item (jobs_menu, _("S&how DCP in Finder"), ID_jobs_show_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_CPL);
+ add_item(jobs_menu, _("S&how DCP in Finder"), ID_jobs_show_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_CPL);
#elif defined(DCPOMATIC_WINDOWS)
- add_item (jobs_menu, _("S&how DCP in Explorer"), ID_jobs_show_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_CPL);
+ add_item(jobs_menu, _("S&how DCP in Explorer"), ID_jobs_show_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_CPL);
#else
- add_item (jobs_menu, _("S&how DCP in Files"), ID_jobs_show_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_CPL);
+ add_item(jobs_menu, _("S&how DCP in Files"), ID_jobs_show_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_CPL);
#endif
- add_item (jobs_menu, _("Open DCP in &player"), ID_jobs_open_dcp_in_player, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_CPL);
+ add_item(jobs_menu, _("Open DCP in &player"), ID_jobs_open_dcp_in_player, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_CPL);
auto view = new wxMenu;
- add_item (view, _("Closed captions..."), ID_view_closed_captions, NEEDS_FILM);
- add_item (view, _("Video waveform..."), ID_view_video_waveform, NEEDS_FILM);
+ add_item(view, _("Closed captions..."), ID_view_closed_captions, NEEDS_FILM);
+ add_item(view, _("Video waveform..."), ID_view_video_waveform, NEEDS_FILM);
auto tools = new wxMenu;
- add_item (tools, _("Version File (VF)..."), ID_tools_version_file, NEEDS_FILM | NEEDS_DCP_CONTENT);
- add_item (tools, _("Hints..."), ID_tools_hints, NEEDS_FILM);
- add_item (tools, _("Encoding servers..."), ID_tools_encoding_servers, 0);
- add_item (tools, _("Manage templates..."), ID_tools_manage_templates, 0);
- add_item (tools, _("Check for updates"), ID_tools_check_for_updates, 0);
- add_item (tools, _("System information..."), ID_tools_system_information, 0);
- tools->AppendSeparator ();
- add_item (tools, _("Restore default preferences"), ID_tools_restore_default_preferences, ALWAYS);
- tools->AppendSeparator ();
- add_item (tools, _("Export preferences..."), ID_tools_export_preferences, ALWAYS);
- add_item (tools, _("Import preferences..."), ID_tools_import_preferences, ALWAYS);
+ add_item(tools, _("Version File (VF)..."), ID_tools_version_file, NEEDS_FILM | NEEDS_DCP_CONTENT);
+ add_item(tools, _("Hints..."), ID_tools_hints, NEEDS_FILM);
+ add_item(tools, _("Encoding servers..."), ID_tools_encoding_servers, 0);
+ add_item(tools, _("Manage templates..."), ID_tools_manage_templates, 0);
+ add_item(tools, _("Check for updates"), ID_tools_check_for_updates, 0);
+ add_item(tools, _("System information..."), ID_tools_system_information, 0);
+ tools->AppendSeparator();
+ add_item(tools, _("Restore default preferences"), ID_tools_restore_default_preferences, ALWAYS);
+ tools->AppendSeparator();
+ add_item(tools, _("Export preferences..."), ID_tools_export_preferences, ALWAYS);
+ add_item(tools, _("Import preferences..."), ID_tools_import_preferences, ALWAYS);
wxMenu* help = new wxMenu;
#ifdef __WXOSX__
add_item(help, variant::wx::insert_dcpomatic(_("About %s")), wxID_ABOUT, ALWAYS);
#else
- add_item (help, _("About"), wxID_ABOUT, ALWAYS);
+ add_item(help, _("About"), wxID_ABOUT, ALWAYS);
#endif
add_item(help, _("User manual..."), ID_help_user_manual, ALWAYS);
if (variant::show_report_a_problem()) {
add_item(help, _("Report a problem..."), ID_help_report_a_problem, ALWAYS);
}
- m->Append (_file_menu, _("&File"));
- m->Append (edit, _("&Edit"));
- m->Append (jobs_menu, _("&Jobs"));
- m->Append (view, _("&View"));
- m->Append (tools, _("&Tools"));
- m->Append (help, _("&Help"));
+ m->Append(_file_menu, _("&File"));
+ m->Append(edit, _("&Edit"));
+ m->Append(jobs_menu, _("&Jobs"));
+ m->Append(view, _("&View"));
+ m->Append(tools, _("&Tools"));
+ m->Append(help, _("&Help"));
}
void config_changed(Config::Property what)
@@ -1471,21 +1478,21 @@ private:
try {
Config::instance()->write_config();
} catch (exception& e) {
- error_dialog (
+ error_dialog(
this,
- wxString::Format (
+ wxString::Format(
_("Could not write to config file at %s. Your changes have not been saved."),
- std_to_wx (Config::instance()->cinemas_file().string()).data()
+ std_to_wx(Config::instance()->cinemas_file().string()).data()
)
);
}
for (int i = 0; i < _history_items; ++i) {
- delete _file_menu->Remove (ID_file_history + i);
+ delete _file_menu->Remove(ID_file_history + i);
}
if (_history_separator) {
- _file_menu->Remove (_history_separator);
+ _file_menu->Remove(_history_separator);
}
delete _history_separator;
_history_separator = 0;
@@ -1493,11 +1500,11 @@ private:
int pos = _history_position;
/* Clear out non-existent history items before we re-build the menu */
- Config::instance()->clean_history ();
+ Config::instance()->clean_history();
auto history = Config::instance()->history();
- if (!history.empty ()) {
- _history_separator = _file_menu->InsertSeparator (pos++);
+ if (!history.empty()) {
+ _history_separator = _file_menu->InsertSeparator(pos++);
}
for (size_t i = 0; i < history.size(); ++i) {
@@ -1507,12 +1514,12 @@ private:
} else {
s = history[i].string();
}
- _file_menu->Insert (pos++, ID_file_history + i, std_to_wx (s));
+ _file_menu->Insert(pos++, ID_file_history + i, std_to_wx(s));
}
- _history_items = history.size ();
+ _history_items = history.size();
- dcpomatic_log->set_types (Config::instance()->log_types());
+ dcpomatic_log->set_types(Config::instance()->log_types());
#ifdef DCPOMATIC_GROK
if (what == Config::GROK) {
@@ -1523,9 +1530,9 @@ private:
#endif
}
- void update_checker_state_changed ()
+ void update_checker_state_changed()
{
- auto uc = UpdateChecker::instance ();
+ auto uc = UpdateChecker::instance();
bool const announce =
_update_news_requested ||
@@ -1550,7 +1557,7 @@ private:
_update_news_requested = false;
}
- void start_stop_pressed ()
+ void start_stop_pressed()
{
if (_film_viewer.playing()) {
_film_viewer.stop();
@@ -1559,28 +1566,28 @@ private:
}
}
- void timeline_pressed ()
+ void timeline_pressed()
{
- _film_editor->content_panel()->timeline_clicked ();
+ _film_editor->content_panel()->timeline_clicked();
}
- void back_frame ()
+ void back_frame()
{
_film_viewer.seek_by(-_film_viewer.one_video_frame(), true);
}
- void forward_frame ()
+ void forward_frame()
{
_film_viewer.seek_by(_film_viewer.one_video_frame(), true);
}
- void analytics_message (string title, string html)
+ void analytics_message(string title, string html)
{
HTMLDialog dialog(this, std_to_wx(title), std_to_wx(html));
dialog.ShowModal();
}
- void set_title ()
+ void set_title()
{
auto s = variant::dcpomatic();
if (_film) {
@@ -1592,7 +1599,7 @@ private:
}
}
- SetTitle (std_to_wx(s));
+ SetTitle(std_to_wx(s));
}
FilmEditor* _film_editor;
@@ -1629,7 +1636,7 @@ static const wxCmdLineEntryDesc command_line_description[] = {
{ wxCMD_LINE_SWITCH, "v", "version", "show version", wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
{ wxCMD_LINE_OPTION, "", "config", "directory containing config.xml and cinemas.xml", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
{ wxCMD_LINE_PARAM, 0, 0, "film to load or create", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
- { wxCMD_LINE_NONE, "", "", "", wxCmdLineParamType (0), 0 }
+ { wxCMD_LINE_NONE, "", "", "", wxCmdLineParamType(0), 0 }
};
@@ -1639,18 +1646,18 @@ static const wxCmdLineEntryDesc command_line_description[] = {
class App : public wxApp
{
public:
- App ()
- : wxApp ()
+ App()
+ : wxApp()
{
- dcpomatic_setup_path_encoding ();
+ dcpomatic_setup_path_encoding();
#ifdef DCPOMATIC_LINUX
- XInitThreads ();
+ XInitThreads();
#endif
}
private:
- bool OnInit () override
+ bool OnInit() override
{
try {
@@ -1673,12 +1680,12 @@ private:
cout << variant::insert_dcpomatic("{} is starting.") << "\n";
}
#endif
- wxInitAllImageHandlers ();
+ wxInitAllImageHandlers();
Config::FailedToLoad.connect(boost::bind(&App::config_failed_to_load, this, _1));
- Config::Warning.connect (boost::bind (&App::config_warning, this, _1));
+ Config::Warning.connect(boost::bind(&App::config_warning, this, _1));
- _splash = maybe_show_splash ();
+ _splash = maybe_show_splash();
SetAppName(variant::wx::dcpomatic());
@@ -1687,12 +1694,12 @@ private:
}
#ifdef DCPOMATIC_LINUX
- unsetenv ("UBUNTU_MENUPROXY");
+ unsetenv("UBUNTU_MENUPROXY");
#endif
#ifdef DCPOMATIC_OSX
- dcpomatic_sleep_seconds (1);
- make_foreground_application ();
+ dcpomatic_sleep_seconds(1);
+ make_foreground_application();
#endif
/* Enable i18n; this will create a Config object
@@ -1706,28 +1713,28 @@ private:
/* Set things up, including filters etc.
which will now be internationalised correctly.
*/
- dcpomatic_setup ();
+ dcpomatic_setup();
/* Force the configuration to be re-loaded correctly next
time it is needed.
*/
- Config::drop ();
+ Config::drop();
/* We only look out for bad configuration from here on, as before
dcpomatic_setup() we haven't got OpenSSL ready so there will be
incorrect certificate chain validity errors.
*/
- Config::Bad.connect (boost::bind(&App::config_bad, this, _1));
+ Config::Bad.connect(boost::bind(&App::config_bad, this, _1));
- signal_manager = new wxSignalManager (this);
+ signal_manager = new wxSignalManager(this);
_frame = new DOMFrame(variant::wx::dcpomatic());
- SetTopWindow (_frame);
- _frame->Maximize ();
- close_splash ();
+ SetTopWindow(_frame);
+ _frame->Maximize();
+ close_splash();
- if (running_32_on_64 ()) {
- NagDialog::maybe_nag (
+ if (running_32_on_64()) {
+ NagDialog::maybe_nag(
_frame, Config::NAG_32_ON_64,
wxString::Format(
_("You are running the 32-bit version of %s on a 64-bit version of Windows. "
@@ -1740,34 +1747,34 @@ private:
false);
}
- _frame->Show ();
+ _frame->Show();
- Bind (wxEVT_IDLE, boost::bind (&App::idle, this, _1));
+ Bind(wxEVT_IDLE, boost::bind(&App::idle, this, _1));
if (!_film_to_load.empty() && dcp::filesystem::is_directory(_film_to_load)) {
try {
- _frame->load_film (_film_to_load);
+ _frame->load_film(_film_to_load);
} catch (exception& e) {
- error_dialog (nullptr, std_to_wx(fmt::format(wx_to_std(_("Could not load film {} ({})")), _film_to_load)), std_to_wx(e.what()));
+ error_dialog(nullptr, std_to_wx(fmt::format(wx_to_std(_("Could not load film {} ({})")), _film_to_load)), std_to_wx(e.what()));
}
}
- if (!_film_to_create.empty ()) {
- _frame->new_film (_film_to_create, optional<string>());
+ if (!_film_to_create.empty()) {
+ _frame->new_film(_film_to_create, optional<string>());
if (!_content_to_add.empty()) {
_frame->film()->examine_and_add_content(content_factory(_content_to_add));
}
- if (!_dcp_to_add.empty ()) {
+ if (!_dcp_to_add.empty()) {
_frame->film()->examine_and_add_content({make_shared<DCPContent>(_dcp_to_add)});
}
}
- Bind (wxEVT_TIMER, boost::bind (&App::check, this));
- _timer.reset (new wxTimer (this));
- _timer->Start (1000);
+ Bind(wxEVT_TIMER, boost::bind(&App::check, this));
+ _timer.reset(new wxTimer(this));
+ _timer->Start(1000);
- if (Config::instance()->check_for_updates ()) {
- UpdateChecker::instance()->run ();
+ if (Config::instance()->check_for_updates()) {
+ UpdateChecker::instance()->run();
}
if (auto release_notes = find_release_notes(gui_is_dark())) {
@@ -1790,51 +1797,51 @@ private:
return true;
}
- void OnInitCmdLine (wxCmdLineParser& parser) override
+ void OnInitCmdLine(wxCmdLineParser& parser) override
{
- parser.SetDesc (command_line_description);
+ parser.SetDesc(command_line_description);
parser.SetSwitchChars(char_to_wx("-"));
}
- bool OnCmdLineParsed (wxCmdLineParser& parser) override
+ bool OnCmdLineParsed(wxCmdLineParser& parser) override
{
if (parser.Found(char_to_wx("version"))) {
cout << "dcpomatic version " << dcpomatic_version << " " << dcpomatic_git_commit << "\n";
- exit (EXIT_SUCCESS);
+ exit(EXIT_SUCCESS);
}
if (parser.GetParamCount() > 0) {
if (parser.Found(char_to_wx("new"))) {
- _film_to_create = wx_to_std (parser.GetParam (0));
+ _film_to_create = wx_to_std(parser.GetParam(0));
} else {
- _film_to_load = wx_to_std (parser.GetParam (0));
+ _film_to_load = wx_to_std(parser.GetParam(0));
}
}
wxString content;
if (parser.Found(char_to_wx("content"), &content)) {
- _content_to_add = wx_to_std (content);
+ _content_to_add = wx_to_std(content);
}
wxString dcp;
if (parser.Found(char_to_wx("dcp"), &dcp)) {
- _dcp_to_add = wx_to_std (dcp);
+ _dcp_to_add = wx_to_std(dcp);
}
wxString config;
if (parser.Found(char_to_wx("config"), &config)) {
- State::override_path = wx_to_std (config);
+ State::override_path = wx_to_std(config);
}
return true;
}
- void report_exception ()
+ void report_exception()
{
try {
throw;
} catch (FileError& e) {
- error_dialog (
+ error_dialog(
nullptr,
wxString::Format(
_("An exception occurred: %s (%s)\n\n%s"),
@@ -1844,7 +1851,7 @@ private:
)
);
} catch (boost::filesystem::filesystem_error& e) {
- error_dialog (
+ error_dialog(
nullptr,
wxString::Format(
_("An exception occurred: %s (%s) (%s)\n\n%s"),
@@ -1855,7 +1862,7 @@ private:
)
);
} catch (exception& e) {
- error_dialog (
+ error_dialog(
nullptr,
wxString::Format(
_("An exception occurred: %s.\n\n%s"),
@@ -1869,34 +1876,34 @@ private:
}
/* An unhandled exception has occurred inside the main event loop */
- bool OnExceptionInMainLoop () override
+ bool OnExceptionInMainLoop() override
{
- report_exception ();
+ report_exception();
/* This will terminate the program */
return false;
}
- void OnUnhandledException () override
+ void OnUnhandledException() override
{
- report_exception ();
+ report_exception();
}
- void idle (wxIdleEvent& ev)
+ void idle(wxIdleEvent& ev)
{
- signal_manager->ui_idle ();
- ev.Skip ();
+ signal_manager->ui_idle();
+ ev.Skip();
}
- void check ()
+ void check()
{
try {
- EncodeServerFinder::instance()->rethrow ();
+ EncodeServerFinder::instance()->rethrow();
} catch (exception& e) {
- error_dialog (0, std_to_wx (e.what ()));
+ error_dialog(0, std_to_wx(e.what()));
}
}
- void close_splash ()
+ void close_splash()
{
if (_splash) {
_splash->Destroy();
@@ -1904,17 +1911,17 @@ private:
}
}
- void config_failed_to_load (Config::LoadFailure what)
+ void config_failed_to_load(Config::LoadFailure what)
{
report_config_load_failure(_frame, what);
}
- void config_warning (string m)
+ void config_warning(string m)
{
- message_dialog (_frame, std_to_wx(m));
+ message_dialog(_frame, std_to_wx(m));
}
- bool config_bad (Config::BadReason reason)
+ bool config_bad(Config::BadReason reason)
{
/* Destroy the splash screen here, as otherwise bad things seem to happen (for reasons unknown)
when we open our recreate dialog, close it, *then* try to Destroy the splash (the Destroy fails).
@@ -1971,7 +1978,7 @@ private:
variant::wx::insert_dcpomatic(_("Close %s"))
);
if (dialog.ShowModal() != wxID_OK) {
- exit (EXIT_FAILURE);
+ exit(EXIT_FAILURE);
}
return true;
}
@@ -1990,7 +1997,7 @@ private:
variant::wx::insert_dcpomatic(_("Close %s"))
);
if (dialog.ShowModal() != wxID_OK) {
- exit (EXIT_FAILURE);
+ exit(EXIT_FAILURE);
}
return true;
}
@@ -2012,7 +2019,7 @@ private:
return dialog.ShowModal() == wxID_OK;
}
default:
- DCPOMATIC_ASSERT (false);
+ DCPOMATIC_ASSERT(false);
}
}
@@ -2026,4 +2033,4 @@ private:
};
-IMPLEMENT_APP (App)
+IMPLEMENT_APP(App)
diff --git a/src/tools/po/zh_CN.po b/src/tools/po/zh_CN.po
index b515feb78..591841030 100644
--- a/src/tools/po/zh_CN.po
+++ b/src/tools/po/zh_CN.po
@@ -13,15 +13,15 @@ msgstr ""
"Project-Id-Version: DCPOMATIC\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-04-12 11:50+0200\n"
-"PO-Revision-Date: 2025-10-05 13:41+0800\n"
+"PO-Revision-Date: 2026-05-17 10:46+0800\n"
"Last-Translator: Dian Li <xslidian@gmail.com>\n"
-"Language-Team: Chinese Simplified (Rov8 branch)\n"
+"Language-Team: Chinese Simplified (Hanyuan branch)\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Poedit 3.7\n"
+"X-Generator: Poedit 3.9\n"
"X-Poedit-SourceCharset: UTF-8\n"
#: src/tools/dcpomatic_kdm.cc:491
@@ -37,7 +37,7 @@ msgstr "%d 导出KDMs 到 %s"
#: src/tools/dcpomatic_combiner.cc:177
#, c-format
msgid "%s already exists as a file, so you cannot use it for a DCP."
-msgstr "%s文件已存在,您不可以将它用于DCP。"
+msgstr "%s是一个文件且已经存在,因此您不可以将它用于DCP。"
#: src/tools/dcpomatic_disk.cc:518 src/tools/dcpomatic_kdm.cc:944
#: src/tools/dcpomatic_player.cc:1426
@@ -157,11 +157,11 @@ msgstr "查看(&V)"
#: src/tools/dcpomatic_verifier.cc:107
msgid "(encrypted, have KDM)"
-msgstr ""
+msgstr "(已加密,有KDM)"
#: src/tools/dcpomatic_verifier.cc:109
msgid "(encrypted, no KDM)"
-msgstr ""
+msgstr "(已加密,无KDM)"
#: src/tools/dcpomatic_playlist.cc:324
msgid "<b>Playlist:</b>"
@@ -194,9 +194,8 @@ msgid "Add &KDM..."
msgstr "添加 &KDM..."
#: src/tools/dcpomatic_verifier.cc:187
-#, fuzzy
msgid "Add KDM..."
-msgstr "添加 &KDM..."
+msgstr "添加 KDM..."
#: src/tools/dcpomatic_playlist.cc:80
msgid "Add content"
@@ -294,11 +293,11 @@ msgstr "注释文本"
msgid ""
"Are you sure you want to restore preferences to their defaults? This cannot "
"be undone."
-msgstr "确定要恢复默认设置? 该操作不能撤销。"
+msgstr "确定恢复默认偏好设置? 该操作不能撤销。"
#: src/tools/dcpomatic_player.cc:709
msgid "Audio graph..."
-msgstr ""
+msgstr "音频图..."
#: src/tools/dcpomatic.cc:878
#, c-format
@@ -329,7 +328,7 @@ msgstr "检查更新"
#: src/tools/dcpomatic_verifier.cc:375
msgid "Checking KDM"
-msgstr ""
+msgstr "检查KDM"
#: src/tools/dcpomatic_combiner.cc:68 src/tools/dcpomatic_disk.cc:84
msgid "Choose a DCP folder"
@@ -376,7 +375,7 @@ msgstr "无法创建目录来存储影片。"
msgid ""
"Could not decrypt the DKDM. Perhaps it was not created with the correct "
"certificate."
-msgstr "不能解开DKDM。 也许它不是用选定的证书所加密的。"
+msgstr "无法解密DKDM。 也许它不是用选定证书所加密的。"
#: src/tools/dcpomatic.cc:661 src/tools/dcpomatic.cc:678
msgid "Could not duplicate project."
@@ -506,11 +505,11 @@ msgstr "无法启动播放器,你可能需要从dcpomatic.com下载。"
#, c-format
msgid ""
"Could not write to config file at %s. Your changes have not been saved."
-msgstr "不能保存设置%s。设置没有被保存。"
+msgstr "不能保存设置到文件%s。你的修改没有被保存。"
#: src/tools/dcpomatic_player.cc:1136
msgid "Could not write to config file. Your changes have not been saved."
-msgstr "不能保存设置到文件。更改没有被保存。"
+msgstr "不能保存设置到文件。你的修改没有被保存。"
#: src/tools/dcpomatic_kdm.cc:239
msgid "Create KDMs"
@@ -655,18 +654,16 @@ msgid "Entry point"
msgstr "入口点"
#: src/tools/dcpomatic_verifier.cc:152
-#, fuzzy
msgid "Examining DCPs"
-msgstr "正在组合DCP"
+msgstr "正在检查DCPs"
#: src/tools/dcpomatic.cc:1446
msgid "Export preferences..."
msgstr "导出首选项设置..."
#: src/tools/dcpomatic.cc:1418
-#, fuzzy
msgid "Export subtitles...\tShift-Ctrl-E"
-msgstr "导出字幕..."
+msgstr "导出字幕...\tShift-Ctrl-E"
#: src/tools/dcpomatic.cc:1417
msgid "Export video file...\tCtrl-E"
@@ -683,7 +680,7 @@ msgstr "眼"
#: src/tools/dcpomatic.cc:1041 src/tools/dcpomatic_kdm.cc:362
#, c-format
msgid "File %s already exists. Do you want to overwrite it?"
-msgstr "已存在文件 %s ,是否覆盖?"
+msgstr "已存在文件 %s ,你是否想要覆盖?"
#. TRANSLATORS: this is the heading for a dialog box, which tells the user that the current
#. project (Film) has been changed since it was last saved.
@@ -698,7 +695,7 @@ msgstr "查找磁盘"
#: src/tools/dcpomatic_kdm.cc:357
#, c-format
msgid "Folder %s already exists. Do you want to overwrite it?"
-msgstr "已存在文件 %s 。是否覆盖?"
+msgstr "已存在文件夹 %s 。你是否想要覆盖?"
#: src/tools/dcpomatic_server.cc:169
msgid "Frames per second"
@@ -958,9 +955,8 @@ msgid "Select DCP to open as OV"
msgstr "选择DCP作为OV打开"
#: src/tools/dcpomatic_verifier.cc:165 src/tools/dcpomatic_verifier.cc:167
-#, fuzzy
msgid "Select DCP(s)"
-msgstr "选择KDM"
+msgstr "选择DCP(s)"
#: src/tools/dcpomatic_kdm.cc:821
msgid "Select DKDM File"
@@ -1228,7 +1224,7 @@ msgstr "向上"
#: src/tools/dcpomatic.cc:1455
msgid "User manual..."
-msgstr ""
+msgstr "用户手册..."
#: src/tools/dcpomatic_verifier.cc:208
msgid "Verify"
diff --git a/src/wx/film_name_location_dialog.cc b/src/wx/film_name_location_dialog.cc
index 893b789f9..0ac7cc98a 100644
--- a/src/wx/film_name_location_dialog.cc
+++ b/src/wx/film_name_location_dialog.cc
@@ -27,6 +27,7 @@
#include "dir_picker_ctrl.h"
#endif
#include "lib/config.h"
+#include <dcp/filesystem.h>
#include <dcp/warnings.h>
LIBDCP_DISABLE_WARNINGS
#include <wx/stdpaths.h>
@@ -139,7 +140,7 @@ FilmNameLocationDialog::template_name () const
bool
FilmNameLocationDialog::check_path ()
{
- if (boost::filesystem::is_directory(path()) && !boost::filesystem::is_empty(path())) {
+ if (dcp::filesystem::is_directory(path()) && !dcp::filesystem::is_empty(path())) {
if (!confirm_dialog (
this,
wxString::Format(
@@ -149,7 +150,7 @@ FilmNameLocationDialog::check_path ()
)) {
return false;
}
- } else if (boost::filesystem::is_regular_file(path())) {
+ } else if (dcp::filesystem::is_regular_file(path())) {
error_dialog (
this,
wxString::Format(_("%s already exists as a file, so you cannot use it for a film."), std_to_wx(path().string()))
diff --git a/src/wx/po/zh_CN.po b/src/wx/po/zh_CN.po
index d8ad12371..87833885b 100644
--- a/src/wx/po/zh_CN.po
+++ b/src/wx/po/zh_CN.po
@@ -13,16 +13,16 @@ msgstr ""
"Project-Id-Version: libdcpomatic-wx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-04-21 17:39+0200\n"
-"PO-Revision-Date: 2025-10-05 14:09+0800\n"
+"PO-Revision-Date: 2026-05-17 10:50+0800\n"
"Last-Translator: Dian Li <xslidian@gmail.com>\n"
-"Language-Team: Chinese Simplified (Rov8 branch)\n"
+"Language-Team: Chinese Simplified (Hanyuan branch)\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2);\n"
-"X-Generator: Poedit 3.7\n"
+"X-Generator: Poedit 3.9\n"
"X-Poedit-SourceCharset: UTF-8\n"
#: src/wx/player_information.cc:111
@@ -109,9 +109,9 @@ msgid "%s already exists as a file, so you cannot use it for a film."
msgstr "%s 文件已经存在,所以不能用它创建工程。"
#: src/wx/audio_dialog.cc:175
-#, fuzzy, c-format
+#, c-format
msgid "%s audio"
-msgstr "%s 音频 - %s"
+msgstr "%s 音频"
#: src/wx/audio_dialog.cc:171 src/wx/audio_dialog.cc:173
#, c-format
@@ -124,12 +124,11 @@ msgid "%s test email"
msgstr "%s发送测试邮件"
#: src/wx/about_dialog.cc:95
-#, fuzzy
msgid ""
"(C) 2012-2026 Carl Hetherington, Terrence Meiczinger\n"
"Aaron Boxer"
msgstr ""
-"(C) 2012-2025 Carl Hetherington, Terrence Meiczinger\n"
+"(C) 2012-2026 Carl Hetherington, Terrence Meiczinger\n"
"Aaron Boxer"
#: src/wx/full_config_dialog.cc:1227 src/wx/player_config_dialog.cc:131
@@ -559,9 +558,8 @@ msgid "Allow mapping to all audio channels"
msgstr "允许映射到所有音频通道"
#: src/wx/full_config_dialog.cc:1079
-#, fuzzy
msgid "Allow use of MPEG2 Interop"
-msgstr "允许使用SMPTE Bv2.0"
+msgstr "允许使用MPEG2 Interop"
#: src/wx/full_config_dialog.cc:1077
msgid "Allow use of SMPTE Bv2.0"
@@ -826,9 +824,8 @@ msgid "Check for updates on startup"
msgstr "启动时检查软件更新"
#: src/wx/content_menu.cc:116
-#, fuzzy
msgid "Choose CPL"
-msgstr "选择CPL…"
+msgstr "选择CPL"
#: src/wx/content_panel.cc:677
msgid "Choose a DCP folder"
@@ -1038,9 +1035,8 @@ msgid "Could not read certificate file."
msgstr "无法读取证书文件。"
#: src/wx/certificate_chain_editor.cc:195
-#, fuzzy
msgid "Could not read certificate file. Make sure it is in PEM format."
-msgstr "无法读取证书文件。"
+msgstr "无法读取证书文件。确保它是 PEM 格式。"
#: src/wx/qube_certificate_panel.cc:55
msgid "Could not read certificates from Qube server."
@@ -1140,9 +1136,8 @@ msgid "Debug: audio analysis"
msgstr "调试: 音频分析"
#: src/wx/full_config_dialog.cc:1322
-#, fuzzy
msgid "Debug: butler"
-msgstr "调试: 播放器"
+msgstr "调试: 管家(butler)"
#: src/wx/full_config_dialog.cc:1314 src/wx/kdm_config_dialog.cc:142
msgid "Debug: email sending"
@@ -1361,33 +1356,28 @@ msgid "Encoding Servers"
msgstr "编码服务器"
#: src/wx/encryption_settings_dialog.cc:33
-#, fuzzy
msgid "Encrypt picture"
-msgstr "加密"
+msgstr "加密图像"
#: src/wx/encryption_settings_dialog.cc:34
-#, fuzzy
msgid "Encrypt sound"
-msgstr "加密"
+msgstr "加密声音"
#: src/wx/encryption_settings_dialog.cc:35
-#, fuzzy
msgid "Encrypt text"
-msgstr "加密"
+msgstr "加密文本"
#: src/wx/dcp_panel.cc:106 src/wx/spl_entry_dialog.cc:51
msgid "Encrypted"
msgstr "加密"
#: src/wx/encryption_settings_dialog.cc:31
-#, fuzzy
msgid "Encryption settings"
-msgstr "导出所有KDM加密设置…"
+msgstr "加密设置"
#: src/wx/dcp_panel.cc:107
-#, fuzzy
msgid "Encryption settings..."
-msgstr "导出所有KDM加密设置…"
+msgstr "加密设置..."
#: src/wx/text_view.cc:68
msgid "End"
@@ -1508,29 +1498,24 @@ msgid "Finding the colours in these subtitles..."
msgstr "查找这些字幕中的颜色..."
#: src/wx/markers.cc:39
-#, fuzzy
msgid "First frame of end credits (FFEC)"
-msgstr "片尾的第一帧"
+msgstr "片尾字幕的第一帧(FFEC)"
#: src/wx/markers.cc:37
-#, fuzzy
msgid "First frame of intermission (FFOI)"
-msgstr "幕间休息第一帧"
+msgstr "幕间休息的第一帧 (FFOI)"
#: src/wx/markers.cc:41
-#, fuzzy
msgid "First frame of moving credits (FFMC)"
-msgstr "动态字幕的第一帧"
+msgstr "滚动字幕的第一帧(FFMC)"
#: src/wx/markers.cc:33
-#, fuzzy
msgid "First frame of ratings band (FFOB)"
-msgstr "评级等级的第一帧"
+msgstr "评级的第一帧(FFOB)"
#: src/wx/markers.cc:35
-#, fuzzy
msgid "First frame of title credits (FFTC)"
-msgstr "标题字幕第一帧"
+msgstr "标题字幕第一帧(FFTC)"
#: src/wx/short_kdm_output_panel.cc:115 src/wx/tall_kdm_output_panel.cc:84
msgid "Folder / ZIP name format"
@@ -1953,29 +1938,24 @@ msgid "Language used for any sign language video track"
msgstr "用于手语视频轨道的语言"
#: src/wx/markers.cc:40
-#, fuzzy
msgid "Last frame of end credits (LFEC)"
-msgstr "片尾字幕的最后一帧"
+msgstr "片尾字幕的最后一帧(LFEC)"
#: src/wx/markers.cc:38
-#, fuzzy
msgid "Last frame of intermission (LFOI)"
-msgstr "幕间休息的最后一帧"
+msgstr "幕间休息的最后一帧(LFOI)"
#: src/wx/markers.cc:42
-#, fuzzy
msgid "Last frame of moving credits (LFMC)"
-msgstr "动态字幕的最后一帧"
+msgstr "动态字幕的最后一帧(LFMC)"
#: src/wx/markers.cc:34
-#, fuzzy
msgid "Last frame of ratings band (LFOB)"
-msgstr "评级等级的最后一帧"
+msgstr "评级等级的最后一帧(LFOB)"
#: src/wx/markers.cc:36
-#, fuzzy
msgid "Last frame of title credits (LFTC)"
-msgstr "标题字幕的最后一帧"
+msgstr "标题字幕的最后一帧(LFTC)"
#: src/wx/content_panel.cc:292
msgid "Later"
@@ -2090,9 +2070,8 @@ msgid "MPEG2 Interop"
msgstr "MPEG2 Interop"
#: src/wx/export_subtitles_dialog.cc:48
-#, fuzzy
msgid "MXF (SMPTE)"
-msgstr "SMPTE"
+msgstr "MXF (SMPTE)"
#. TRANSLATORS: Main and Additional here are a choice for whether a set of subtitles is in the "main" language of the
#. film or an "additional" language.
@@ -3719,9 +3698,9 @@ msgstr ""
"(%duration) 不同。"
#: src/wx/verify_dcp_result_panel.cc:423
-#, fuzzy, c-format
+#, c-format
msgid "The sound asset %f has an invalid bit depth of %bit_depth."
-msgstr "声音资产 %f 的位深度 %bit_depth 无效。"
+msgstr "音频资产 %f 的位深 %bit_depth 无效。"
#: src/wx/verify_dcp_result_panel.cc:420
#, c-format
@@ -3786,9 +3765,8 @@ msgid "The video asset %f uses the invalid image size %size_in_pixels."
msgstr "视频资产 %f 使用了无效的图像大小 %size_in_pixels。"
#: src/wx/verify_dcp_result_panel.cc:369
-#, fuzzy
msgid "The video asset is 4K which is not allowed for 3D video."
-msgstr "视频资产 %f 使用的帧速率 %frame_rate 对于3D视频无效。"
+msgstr "该视频素材为4K,不允许用于3D视频。"
#: src/wx/verify_dcp_result_panel.cc:414
msgid "There are more than 3 closed caption lines in at least one place."
@@ -3846,13 +3824,13 @@ msgid "This CPL contains no encrypted assets."
msgstr "该CPL没有包含加密内容。"
#: src/wx/verify_dcp_result_panel.cc:348
-#, fuzzy, c-format
+#, c-format
msgid ""
"This DCP refers to the asset %asset_id in another DCP (and perhaps others), "
"so it is a \"version file\" (VF)"
msgstr ""
-"此DCP引用了另一个DCP(可能还有其他DCP)中的资产 %asset_id,因此它是一个“版本"
-"文件”(VF)"
+"这个DCP引用了另一个DCP中的资产%asset_id(也可能是其他DCP中的资产),因此它是"
+"一个“版本文件”(VF)"
#: src/wx/verify_dcp_result_panel.cc:354
msgid "This DCP uses the Interop standard, but it should be made with SMPTE."
@@ -4257,18 +4235,16 @@ msgid "Verify"
msgstr "验证"
#: src/wx/content_menu.cc:425
-#, fuzzy
msgid "Verify DCP"
-msgstr "验证"
+msgstr "验证DCP"
#: src/wx/verify_dcp_dialog.cc:94
msgid "Verify picture asset details"
msgstr "验证图像资产详细信息"
#: src/wx/content_menu.cc:107
-#, fuzzy
msgid "Verify..."
-msgstr "验证"
+msgstr "验证..."
#: src/wx/smpte_metadata_dialog.cc:109 src/wx/system_information_dialog.cc:67
msgid "Version"
@@ -4385,9 +4361,8 @@ msgid "X"
msgstr "X"
#: src/wx/export_subtitles_dialog.cc:47
-#, fuzzy
msgid "XML (Interop)"
-msgstr "Interop"
+msgstr "XML (Interop)"
#: src/wx/text_panel.cc:93
msgid "Y"
diff --git a/src/wx/supporters.cc b/src/wx/supporters.cc
index 602bc91b1..cd331bba7 100644
--- a/src/wx/supporters.cc
+++ b/src/wx/supporters.cc
@@ -599,6 +599,7 @@ supported_by.Add (wxT ("Jessica Han"));
supported_by.Add (wxT ("Mark Hanrahan"));
supported_by.Add (wxT ("Niels-Erik Constantin Hansen"));
supported_by.Add (wxT ("Richard Hansen"));
+supported_by.Add (wxT ("Paul Hara"));
supported_by.Add (wxT ("Jozef Hardos"));
supported_by.Add (wxT ("Filmschuur Harlem"));
supported_by.Add (wxT ("Jens Harms"));
@@ -1200,6 +1201,7 @@ supported_by.Add (wxT ("A Tractor Productions"));
supported_by.Add (wxT ("Second Wind Productions"));
supported_by.Add (wxT ("Locomotive Productions"));
supported_by.Add (wxT ("Stoneman Productions"));
+supported_by.Add (wxT ("Zombie Zoo Productions"));
supported_by.Add (wxT ("Oley Sassone Productions"));
supported_by.Add (wxT ("RIOT Productions"));
supported_by.Add (wxT ("Undercrank Productions"));
@@ -1545,6 +1547,7 @@ supported_by.Add (wxT ("Mike Wendt"));
supported_by.Add (wxT ("Frank Wenz"));
supported_by.Add (wxT ("Anja Wenz"));
supported_by.Add (wxT ("Olav Werner"));
+supported_by.Add (wxT ("Georg Werner"));
supported_by.Add (wxT ("Maik Wieczorek"));
supported_by.Add (wxT ("Ralph Wiegandt"));
supported_by.Add (wxT ("Johannes Wilbrand"));
diff --git a/test/audio_mapping_test.cc b/test/audio_mapping_test.cc
index dfde022a0..9bc5bcf5f 100644
--- a/test/audio_mapping_test.cc
+++ b/test/audio_mapping_test.cc
@@ -36,71 +36,71 @@ using std::string;
using boost::optional;
-BOOST_AUTO_TEST_CASE (audio_mapping_test)
+BOOST_AUTO_TEST_CASE(audio_mapping_test)
{
AudioMapping none;
- BOOST_CHECK_EQUAL (none.input_channels(), 0);
+ BOOST_CHECK_EQUAL(none.input_channels(), 0);
- AudioMapping four (4, MAX_DCP_AUDIO_CHANNELS);
- BOOST_CHECK_EQUAL (four.input_channels(), 4);
+ AudioMapping four(4, MAX_DCP_AUDIO_CHANNELS);
+ BOOST_CHECK_EQUAL(four.input_channels(), 4);
- four.set (0, 1, 1);
+ four.set(0, 1, 1);
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < MAX_DCP_AUDIO_CHANNELS; ++j) {
- BOOST_CHECK_EQUAL (four.get(i, j), (i == 0 && j == 1) ? 1 : 0);
+ BOOST_CHECK_EQUAL(four.get(i, j), (i == 0 && j == 1) ? 1 : 0);
}
}
- auto mapped = four.mapped_output_channels ();
- BOOST_CHECK_EQUAL (mapped.size(), 1U);
- BOOST_CHECK_EQUAL (mapped.front(), 1);
+ auto mapped = four.mapped_output_channels();
+ BOOST_CHECK_EQUAL(mapped.size(), 1U);
+ BOOST_CHECK_EQUAL(mapped.front(), 1);
- four.make_zero ();
+ four.make_zero();
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < MAX_DCP_AUDIO_CHANNELS; ++j) {
- BOOST_CHECK_EQUAL (four.get (i, j), 0);
+ BOOST_CHECK_EQUAL(four.get(i, j), 0);
}
}
}
static void
-guess_check (boost::filesystem::path filename, int output_channel)
+guess_check(boost::filesystem::path filename, dcp::Channel output_channel)
{
- AudioMapping m (1, 8);
- m.make_default (0, filename);
- for (int i = 0; i < 8; ++i) {
+ AudioMapping m(1, 12);
+ m.make_default(0, filename);
+ for (int i = 0; i < 12; ++i) {
BOOST_TEST_INFO(fmt::format("{} channel {}", filename.string(), i));
- BOOST_CHECK_CLOSE (m.get(0, i), i == output_channel ? 1 : 0, 0.01);
+ BOOST_CHECK_CLOSE(m.get(0, i), i == static_cast<int>(output_channel) ? 1 : 0, 0.01);
}
}
-BOOST_AUTO_TEST_CASE (audio_mapping_guess_test)
+BOOST_AUTO_TEST_CASE(audio_mapping_guess_test)
{
- guess_check ("stuff_L_nonsense.wav", 0);
- guess_check ("stuff_nonsense.wav", 2);
- guess_check ("fred_R.wav", 1);
- guess_check ("jim_C_sheila.aiff", 2);
- guess_check ("things_Lfe_and.wav", 3);
- guess_check ("weeee_Ls.aiff", 4);
- guess_check ("try_Rs-it.wav", 5);
+ guess_check("stuff_L_nonsense.wav", dcp::Channel::LEFT);
+ guess_check("stuff_nonsense.wav", dcp::Channel::CENTRE);
+ guess_check("fred_R.wav", dcp::Channel::RIGHT);
+ guess_check("jim_C_sheila.aiff", dcp::Channel::CENTRE);
+ guess_check("things_Lfe_and.wav", dcp::Channel::LFE);
+ guess_check("weeee_Ls.aiff", dcp::Channel::LS);
+ guess_check("try_Rs-it.wav", dcp::Channel::RS);
/* PT-style */
- guess_check ("things_LFE.wav", 3);
- guess_check ("ptish_Lsr_abc.wav", 6);
- guess_check ("ptish_Rsr_abc.wav", 7);
- guess_check ("more_Lss_s.wav", 4);
- guess_check ("other_Rss.aiff", 5);
+ guess_check("things_LFE.wav", dcp::Channel::LFE);
+ guess_check("ptish_Lsr_abc.wav", dcp::Channel::BSL);
+ guess_check("ptish_Rsr_abc.wav", dcp::Channel::BSR);
+ guess_check("more_Lss_s.wav", dcp::Channel::LS);
+ guess_check("other_Rss.aiff", dcp::Channel::RS);
/* Only the filename should be taken into account */
- guess_check ("-Lfe-/foo_L.wav", 0);
+ guess_check("-Lfe-/foo_L.wav", dcp::Channel::LEFT);
/* Dolby-style */
- guess_check ("jake-Lrs-good.wav", 6);
- guess_check ("elwood-Rrs-good.wav", 7);
+ guess_check("jake-Lrs-good.wav", dcp::Channel::BSL);
+ guess_check("elwood-Rrs-good.wav", dcp::Channel::BSR);
}
diff --git a/test/film_test.cc b/test/film_test.cc
index 5ce195637..9949fd7d6 100644
--- a/test/film_test.cc
+++ b/test/film_test.cc
@@ -86,3 +86,24 @@ BOOST_AUTO_TEST_CASE(film_possible_reel_types_test2)
BOOST_CHECK_EQUAL(film->possible_reel_types().size(), 2U);
}
+
+BOOST_AUTO_TEST_CASE(film_copy_remembered_assets_test)
+{
+ dcp::filesystem::remove_all("build/test/film_copy_remembered_assets_test2");
+
+ auto content = content_factory("test/data/flat_red.png")[0];
+ auto film = new_test_film("film_copy_remembered_assets_test", { content });
+ make_and_verify_dcp(film);
+
+ auto copy = make_shared<Film>(boost::filesystem::path("build/test/film_copy_remembered_assets_test2"));
+ copy->copy_from(film, [](float) {});
+
+ auto remembered = copy->read_remembered_assets();
+ BOOST_REQUIRE_EQUAL(remembered.size(), 1U);
+ auto path = find_asset(remembered, *copy->directory(), dcpomatic::DCPTimePeriod({}, dcpomatic::DCPTime::from_seconds(10)), film->video_identifier());
+ BOOST_CHECK(path.has_value());
+
+ for (auto path: dcp::filesystem::directory_iterator(film->dir("info"))) {
+ check_file(path.path(), copy->dir("info") / path.path().filename());
+ }
+}
diff --git a/test/memory_util_test.cc b/test/memory_util_test.cc
new file mode 100644
index 000000000..43dedb5ce
--- /dev/null
+++ b/test/memory_util_test.cc
@@ -0,0 +1,72 @@
+/*
+ Copyright (C) 2026 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic 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.
+
+ DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "lib/memory_util.h"
+#include <boost/test/unit_test.hpp>
+
+
+void check(void* p, int size, uint64_t value)
+{
+ uint8_t* up = reinterpret_cast<uint8_t*>(p);
+ for (int i = 0; i < size; ++i) {
+ BOOST_CHECK_EQUAL(*up++, (value >> (i * 8)) & 0xff);
+ }
+}
+
+
+/** Aligned, multiple of 64 size */
+BOOST_AUTO_TEST_CASE(fill_memory_test1)
+{
+ int constexpr size = 256;
+ auto memory = wrapped_av_malloc(size);
+ BOOST_REQUIRE_EQUAL(reinterpret_cast<uintptr_t>(memory) % 8, 0);
+
+ fill_memory(memory, size, 0x1928374654abdfea);
+ check(memory, size, 0x1928374654abdfea);
+}
+
+
+/** Aligned, extra bytes at the end */
+BOOST_AUTO_TEST_CASE(fill_memory_test2)
+{
+ int constexpr size = 259;
+
+ auto memory = wrapped_av_malloc(size);
+ BOOST_REQUIRE_EQUAL(reinterpret_cast<uintptr_t>(memory) % 8, 0);
+
+ fill_memory(memory, size, 0x1928374654abdfea);
+ check(memory, size, 0x1928374654abdfea);
+}
+
+
+/** Non-aligned, extra bytes at start and end */
+BOOST_AUTO_TEST_CASE(fill_memory_test3)
+{
+ int constexpr size = 265;
+
+ auto memory = wrapped_av_malloc(size + 512);
+ BOOST_REQUIRE_EQUAL(reinterpret_cast<uintptr_t>(memory) % 8, 0);
+ memory = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(memory) + 3);
+
+ fill_memory(memory, size, 0x1928374654abdfea);
+ check(memory, size, 0x1928374654abdfea);
+}
+
diff --git a/test/vf_test.cc b/test/vf_test.cc
index 9c7ff65be..29b9913fd 100644
--- a/test/vf_test.cc
+++ b/test/vf_test.cc
@@ -592,3 +592,99 @@ BOOST_AUTO_TEST_CASE(vf_subs_get_font_from_ov)
auto vf_font = find_file(*font_dir, "font");
check_file("test/data/Inconsolata-VF.ttf", vf_font);
}
+
+
+/** CCAPs in OVs would not correctly be referred to as we'd incorrectly create an
+ * empty filler CCAP asset.
+ */
+BOOST_AUTO_TEST_CASE(vf_referring_to_ov_ccap_test)
+{
+ auto picture = content_factory("test/data/flat_red.png")[0];
+ auto ccap = content_factory("test/data/short.srt")[0];
+ auto ov = new_test_film("vf_referring_to_ov_ccap_test_ov", { picture, ccap });
+ ccap->only_text()->set_use(true);
+ ccap->only_text()->set_type(TextType::CLOSED_CAPTION);
+ ccap->only_text()->set_dcp_track(DCPTextTrack("First track", dcp::LanguageTag("fr")));
+ make_and_verify_dcp(ov, { dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME });
+
+ auto ov_dcp = make_shared<DCPContent>(ov->dir(ov->dcp_name()));
+ auto subs = content_factory("test/data/short.srt")[0];
+ auto vf = new_test_film("vf_referring_to_ov_ccap_test_vf", { ov_dcp, subs });
+ vf->set_reel_type(ReelType::BY_VIDEO_CONTENT);
+ ov_dcp->set_reference_video(true);
+ ov_dcp->set_reference_audio(true);
+ ov_dcp->set_reference_text(TextType::CLOSED_CAPTION, true);
+ subs->only_text()->set_use(true);
+ subs->only_text()->set_type(TextType::OPEN_SUBTITLE);
+ subs->set_position(vf, dcpomatic::DCPTime());
+ vf->write_metadata();
+ make_dcp(vf, TranscodeJob::ChangedBehaviour::IGNORE);
+ BOOST_REQUIRE(!wait_for_jobs());
+
+ dcp::DCP ov_check(ov->dir(ov->dcp_name()));
+ ov_check.read();
+ dcp::DCP vf_check(vf->dir(vf->dcp_name()));
+ vf_check.read();
+
+ BOOST_REQUIRE_EQUAL(ov_check.cpls().size(), 1U);
+ BOOST_REQUIRE_EQUAL(vf_check.cpls().size(), 1U);
+ BOOST_REQUIRE_EQUAL(ov_check.cpls()[0]->reels().size(), 1U);
+ BOOST_REQUIRE_EQUAL(vf_check.cpls()[0]->reels().size(), 1U);
+ BOOST_REQUIRE_EQUAL(ov_check.cpls()[0]->reels()[0]->closed_captions().size(), 1U);
+ BOOST_REQUIRE_EQUAL(vf_check.cpls()[0]->reels()[0]->closed_captions().size(), 1U);
+
+ BOOST_CHECK_EQUAL(
+ ov_check.cpls()[0]->reels()[0]->closed_captions()[0]->id(),
+ vf_check.cpls()[0]->reels()[0]->closed_captions()[0]->id()
+ );
+}
+
+
+/** Check that in a VF we can have a CCAP reel which refers to the OV and another
+ * which is an auto-created filler.
+ */
+BOOST_AUTO_TEST_CASE(ccaps_can_be_referred_and_filled_test)
+{
+ auto picture = content_factory("test/data/flat_red.png")[0];
+ auto ccap = content_factory("test/data/short.srt")[0];
+ auto ov = new_test_film("ccaps_can_be_referred_and_filled_test_ov", { picture, ccap });
+ ccap->only_text()->set_use(true);
+ ccap->only_text()->set_type(TextType::CLOSED_CAPTION);
+ ccap->only_text()->set_dcp_track(DCPTextTrack("First track", dcp::LanguageTag("fr")));
+ make_and_verify_dcp(ov, { dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME });
+
+ auto ov_dcp = make_shared<DCPContent>(ov->dir(ov->dcp_name()));
+ auto subs = content_factory("test/data/short.srt")[0];
+ auto vf = new_test_film("ccaps_can_be_referred_and_filled_test_vf", { ov_dcp, subs, picture });
+ vf->set_reel_type(ReelType::BY_VIDEO_CONTENT);
+ ov_dcp->set_reference_video(true);
+ ov_dcp->set_reference_audio(true);
+ ov_dcp->set_reference_text(TextType::CLOSED_CAPTION, true);
+ subs->only_text()->set_use(true);
+ subs->only_text()->set_type(TextType::OPEN_SUBTITLE);
+ subs->set_position(vf, dcpomatic::DCPTime());
+ vf->write_metadata();
+ make_dcp(vf, TranscodeJob::ChangedBehaviour::IGNORE);
+ BOOST_REQUIRE(!wait_for_jobs());
+
+ dcp::DCP ov_check(ov->dir(ov->dcp_name()));
+ ov_check.read();
+ dcp::DCP vf_check(vf->dir(vf->dcp_name()));
+ vf_check.read();
+
+ BOOST_REQUIRE_EQUAL(ov_check.cpls().size(), 1U);
+ BOOST_REQUIRE_EQUAL(vf_check.cpls().size(), 1U);
+ BOOST_REQUIRE_EQUAL(ov_check.cpls()[0]->reels().size(), 1U);
+ BOOST_REQUIRE_EQUAL(vf_check.cpls()[0]->reels().size(), 2U);
+
+ BOOST_REQUIRE_EQUAL(ov_check.cpls()[0]->reels()[0]->closed_captions().size(), 1U);
+ BOOST_REQUIRE_EQUAL(vf_check.cpls()[0]->reels()[0]->closed_captions().size(), 1U);
+
+ BOOST_CHECK_EQUAL(
+ ov_check.cpls()[0]->reels()[0]->closed_captions()[0]->id(),
+ vf_check.cpls()[0]->reels()[0]->closed_captions()[0]->id()
+ );
+
+ BOOST_REQUIRE_EQUAL(vf_check.cpls()[0]->reels()[1]->closed_captions().size(), 1U);
+}
+
diff --git a/test/wscript b/test/wscript
index 341c407e7..3c8e2229a 100644
--- a/test/wscript
+++ b/test/wscript
@@ -136,6 +136,7 @@ def build(bld):
markers_test.cc
map_cli_test.cc
mca_subdescriptors_test.cc
+ memory_util_test.cc
mpeg2_dcp_test.cc
no_use_video_test.cc
open_caption_test.cc
diff --git a/wscript b/wscript
index c2c795a7c..ce7168953 100644
--- a/wscript
+++ b/wscript
@@ -766,6 +766,7 @@ def build(bld):
bld.recurse('src')
bld.recurse('graphics')
bld.recurse('web')
+ bld.recurse('benchmark')
if not bld.env.DISABLE_TESTS:
bld.recurse('test')