/*
- Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
#include <dcp/sound_asset.h>
#include <dcp/subtitle_asset.h>
#include <dcp/atmos_asset.h>
+DCPOMATIC_DISABLE_WARNINGS
extern "C" {
#include <libavfilter/avfilter.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
}
+DCPOMATIC_ENABLE_WARNINGS
#include <curl/curl.h>
#include <glib.h>
#include <pangomm/init.h>
+#include <unicode/utypes.h>
+#include <unicode/unistr.h>
+#include <unicode/translit.h>
#include <boost/algorithm/string.hpp>
#include <boost/range/algorithm/replace_if.hpp>
#include <boost/thread.hpp>
using std::bad_alloc;
using std::set_terminate;
using std::make_pair;
-using boost::shared_ptr;
+using std::shared_ptr;
+using std::make_shared;
using boost::thread;
using boost::optional;
using boost::lexical_cast;
LONG WINAPI
exception_handler(struct _EXCEPTION_POINTERS * info)
{
- FILE* f = fopen_boost (backtrace_file, "w");
+ auto f = fopen_boost (backtrace_file, "w");
fprintf (f, "C-style exception %d\n", info->ExceptionRecord->ExceptionCode);
fclose(f);
/* Add our library directory to the libltdl search path so that
xmlsec can find xmlsec1-openssl.
*/
- boost::filesystem::path lib = directory_containing_executable().parent_path();
+ auto lib = directory_containing_executable().parent_path();
lib /= "Frameworks";
setenv ("LTDL_LIBRARY_PATH", lib.c_str (), 1);
#endif
/* Render something to fontconfig to create its cache */
list<StringText> subs;
dcp::SubtitleString ss(
- optional<string>(), false, false, false, dcp::Colour(), 42, 1, dcp::Time(), dcp::Time(), 0, dcp::HALIGN_CENTER, 0, dcp::VALIGN_CENTER, dcp::DIRECTION_LTR,
- "Hello dolly", dcp::NONE, dcp::Colour(), dcp::Time(), dcp::Time()
+ optional<string>(), false, false, false, dcp::Colour(), 42, 1, dcp::Time(), dcp::Time(), 0, dcp::HAlign::CENTER, 0, dcp::VAlign::CENTER, dcp::Direction::LTR,
+ "Hello dolly", dcp::Effect::NONE, dcp::Colour(), dcp::Time(), dcp::Time()
);
subs.push_back (StringText(ss, 0));
- render_text (subs, list<shared_ptr<Font> >(), dcp::Size(640, 480), DCPTime(), 24);
+ render_text (subs, list<shared_ptr<Font>>(), dcp::Size(640, 480), DCPTime(), 24);
#endif
Ratio::setup_ratios ();
char* p = buffer.get ();
int i = 0;
while (i < int64_t (files.size()) && to_do > 0) {
- FILE* f = fopen_boost (files[i], "rb");
+ auto f = fopen_boost (files[i], "rb");
if (!f) {
throw OpenFileError (files[i].string(), errno, OpenFileError::READ);
}
p = buffer.get ();
i = files.size() - 1;
while (i >= 0 && to_do > 0) {
- FILE* f = fopen_boost (files[i], "rb");
+ auto f = fopen_boost (files[i], "rb");
if (!f) {
throw OpenFileError (files[i].string(), errno, OpenFileError::READ);
}
_("BsR"),
_("DBP"),
_("DBS"),
- "",
+ _("Sign"),
""
};
return false;
}
- string ext = f.extension().string();
+ auto ext = f.extension().string();
transform (ext.begin(), ext.end(), ext.begin(), ::tolower);
return (
ext == ".tif" || ext == ".tiff" || ext == ".jpg" || ext == ".jpeg" ||
ext == ".png" || ext == ".bmp" || ext == ".tga" || ext == ".dpx" ||
ext == ".j2c" || ext == ".j2k" || ext == ".jp2" || ext == ".exr" ||
- ext == ".jpf"
+ ext == ".jpf" || ext == ".psd"
);
}
return false;
}
- string ext = f.extension().string();
+ auto ext = f.extension().string();
transform (ext.begin(), ext.end(), ext.begin(), ::tolower);
return (ext == ".wav" || ext == ".mp3" || ext == ".aif" || ext == ".aiff");
}
bool
valid_j2k_file (boost::filesystem::path f)
{
- string ext = f.extension().string();
+ auto ext = f.extension().string();
transform (ext.begin(), ext.end(), ext.begin(), ::tolower);
return (ext == ".j2k" || ext == ".j2c" || ext == ".jp2");
}
void *
wrapped_av_malloc (size_t s)
{
- void* p = av_malloc (s);
+ auto p = av_malloc (s);
if (!p) {
throw bad_alloc ();
}
Safety first and all that.
*/
- wstring ws = boost::locale::conv::utf_to_utf<wchar_t>(s);
+ /* First transliterate using libicu to try to remove accents in a "nice" way */
+ auto icu_utf16 = icu::UnicodeString::fromUTF8(icu::StringPiece(s));
+ auto status = U_ZERO_ERROR;
+ auto transliterator = icu::Transliterator::createInstance("NFD; [:M:] Remove; NFC", UTRANS_FORWARD, status);
+ transliterator->transliterate(icu_utf16);
+ s.clear ();
+ icu_utf16.toUTF8String(s);
+ /* Then remove anything that's not in a very limited character set */
+ wstring ws = boost::locale::conv::utf_to_utf<wchar_t>(s);
string out;
string const allowed = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_%.+";
for (size_t i = 0; i < ws.size(); ++i) {
-
wchar_t c = ws[i];
-
- /* Remove some accents */
- if (wstring(L"áàâ").find(c) != string::npos) {
- c = 'a';
- }
- if (wstring(L"éèêë").find(c) != string::npos) {
- c = 'e';
- }
- if (wstring(L"ö").find(c) != string::npos) {
- c = 'o';
- }
- if (wstring(L"ü").find(c) != string::npos) {
- c = 'u';
- }
-
if (allowed.find(c) != string::npos) {
out += c;
}
int non_lfe = 0;
int lfe = 0;
- BOOST_FOREACH (int i, mapped) {
+ for (auto i: mapped) {
if (i >= channels) {
/* This channel is mapped but is not included in the DCP */
continue;
}
switch (static_cast<dcp::Channel>(i)) {
- case dcp::LFE:
+ case dcp::Channel::LFE:
++lfe;
break;
- case dcp::LEFT:
- case dcp::RIGHT:
- case dcp::CENTRE:
- case dcp::LS:
- case dcp::RS:
- case dcp::BSL:
- case dcp::BSR:
+ case dcp::Channel::LEFT:
+ case dcp::Channel::RIGHT:
+ case dcp::Channel::CENTRE:
+ case dcp::Channel::LS:
+ case dcp::Channel::RS:
+ case dcp::Channel::BSL:
+ case dcp::Channel::BSR:
++non_lfe;
break;
- case dcp::HI:
- case dcp::VI:
- case dcp::MOTION_DATA:
- case dcp::SYNC_SIGNAL:
- case dcp::SIGN_LANGUAGE:
- case dcp::CHANNEL_COUNT:
+ case dcp::Channel::HI:
+ case dcp::Channel::VI:
+ case dcp::Channel::MOTION_DATA:
+ case dcp::Channel::SYNC_SIGNAL:
+ case dcp::Channel::SIGN_LANGUAGE:
+ case dcp::Channel::CHANNEL_COUNT:
break;
}
}
shared_ptr<AudioBuffers>
remap (shared_ptr<const AudioBuffers> input, int output_channels, AudioMapping map)
{
- shared_ptr<AudioBuffers> mapped (new AudioBuffers (output_channels, input->frames()));
+ auto mapped = make_shared<AudioBuffers>(output_channels, input->frames());
mapped->make_silent ();
int to_do = min (map.input_channels(), input->channels());
for (int i = 0; i < to_do; ++i) {
for (int j = 0; j < mapped->channels(); ++j) {
- if (map.get (i, static_cast<dcp::Channel> (j)) > 0) {
- mapped->accumulate_channel (
+ if (map.get(i, j) > 0) {
+ mapped->accumulate_channel(
input.get(),
i,
- static_cast<dcp::Channel> (j),
- map.get (i, static_cast<dcp::Channel> (j))
+ j,
+ map.get(i, j)
);
}
}
Eyes
increment_eyes (Eyes e)
{
- if (e == EYES_LEFT) {
- return EYES_RIGHT;
+ if (e == Eyes::LEFT) {
+ return Eyes::RIGHT;
}
- return EYES_LEFT;
+ return Eyes::LEFT;
}
void
{
/* XXX: this is rather inefficient; decoding the image just to get its size */
FFmpegImageProxy proxy (sub.png_image());
- shared_ptr<Image> image = proxy.image().image;
+ auto image = proxy.image().image;
/* set up rect with height and width */
dcpomatic::Rect<double> rect(0, 0, image->size().width / double(size.width), image->size().height / double(size.height));
/* add in position */
switch (sub.h_align()) {
- case dcp::HALIGN_LEFT:
+ case dcp::HAlign::LEFT:
rect.x += sub.h_position();
break;
- case dcp::HALIGN_CENTER:
+ case dcp::HAlign::CENTER:
rect.x += 0.5 + sub.h_position() - rect.width / 2;
break;
- case dcp::HALIGN_RIGHT:
+ case dcp::HAlign::RIGHT:
rect.x += 1 - sub.h_position() - rect.width;
break;
}
switch (sub.v_align()) {
- case dcp::VALIGN_TOP:
+ case dcp::VAlign::TOP:
rect.y += sub.v_position();
break;
- case dcp::VALIGN_CENTER:
+ case dcp::VAlign::CENTER:
rect.y += 0.5 + sub.v_position() - rect.height / 2;
break;
- case dcp::VALIGN_BOTTOM:
+ case dcp::VAlign::BOTTOM:
rect.y += 1 - sub.v_position() - rect.height;
break;
}
dcpomatic_sleep_seconds (5);
- list<shared_ptr<Job> > jobs = JobManager::instance()->get();
+ auto jobs = JobManager::instance()->get();
if (!first && progress) {
for (size_t i = 0; i < jobs.size(); ++i) {
first = false;
- BOOST_FOREACH (shared_ptr<Job> i, jobs) {
+ for (auto i: jobs) {
if (progress) {
cout << i->name();
if (!i->sub_name().empty()) {
/** XXX: could use mmap? */
void
-copy_in_bits (boost::filesystem::path from, boost::filesystem::path to, boost::function<void (float)> progress)
+copy_in_bits (boost::filesystem::path from, boost::filesystem::path to, std::function<void (float)> progress)
{
- FILE* f = fopen_boost (from, "rb");
+ auto f = fopen_boost (from, "rb");
if (!f) {
throw OpenFileError (from, errno, OpenFileError::READ);
}
- FILE* t = fopen_boost (to, "wb");
+ auto t = fopen_boost (to, "wb");
if (!t) {
fclose (f);
throw OpenFileError (to, errno, OpenFileError::WRITE);
/* on the order of a second's worth of copying */
boost::uintmax_t const chunk = 20 * 1024 * 1024;
- uint8_t* buffer = static_cast<uint8_t*> (malloc(chunk));
+ auto buffer = static_cast<uint8_t*> (malloc(chunk));
if (!buffer) {
throw std::bad_alloc ();
}
free (buffer);
}
-#ifdef DCPOMATIC_VARIANT_SWAROOP
-
-/* Make up a key from the machine UUID */
-dcp::Data
-key_from_uuid ()
-{
- dcp::Data key (dcpomatic::crypto_key_length());
- memset (key.data().get(), 0, key.size());
- string const magic = command_and_read ("dcpomatic2_uuid");
- strncpy ((char *) key.data().get(), magic.c_str(), dcpomatic::crypto_key_length());
- return key;
-}
-
-/* swaroop chain file format:
- *
- * 0 [int16_t] IV length
- * 2 [int16_t] cert #1 length, or 0 for none
- * 4 [int16_t] cert #2 length, or 0 for none
- * 6 [int16_t] cert #3 length, or 0 for none
- * 8 [int16_t] cert #4 length, or 0 for none
- * 10 [int16_t] cert #5 length, or 0 for none
- * 12 [int16_t] cert #6 length, or 0 for none
- * 14 [int16_t] cert #7 length, or 0 for none
- * 16 [int16_t] cert #8 length, or 0 for none
- * 16 [int16_t] private key length
- * 20 IV
- * cert #1
- * cert #2
- * cert #3
- * cert #4
- * cert #5
- * cert #6
- * cert #7
- * cert #8
- * private key
- */
-
-struct __attribute__ ((packed)) Header_ {
- int16_t iv_length;
- int16_t cert_length[8];
- int16_t private_key_length;
-};
-
-typedef struct Header_ Header;
-
-shared_ptr<dcp::CertificateChain>
-read_swaroop_chain (boost::filesystem::path path)
-{
- dcp::Data data (path);
- Header* header = (Header *) data.data().get();
- uint8_t* p = data.data().get() + sizeof(Header);
-
- dcp::Data iv (p, header->iv_length);
- p += iv.size();
-
- shared_ptr<dcp::CertificateChain> cc (new dcp::CertificateChain());
- for (int i = 0; i < 8; ++i) {
- if (header->cert_length[i] == 0) {
- break;
- }
- dcp::Data c(p, header->cert_length[i]);
- p += c.size();
- cc->add (dcp::Certificate(dcpomatic::decrypt(c, key_from_uuid(), iv)));
- }
-
- dcp::Data k (p, header->private_key_length);
- cc->set_key (dcpomatic::decrypt(k, key_from_uuid(), iv));
- return cc;
-}
-
-void
-write_swaroop_chain (shared_ptr<const dcp::CertificateChain> chain, boost::filesystem::path output)
-{
- scoped_array<uint8_t> buffer (new uint8_t[65536]);
- Header* header = (Header *) buffer.get();
- memset (header, 0, sizeof(Header));
- uint8_t* p = buffer.get() + sizeof(Header);
-
- dcp::Data iv = dcpomatic::random_iv ();
- header->iv_length = iv.size ();
- memcpy (p, iv.data().get(), iv.size());
- p += iv.size();
-
- int N = 0;
- BOOST_FOREACH (dcp::Certificate i, chain->root_to_leaf()) {
- dcp::Data e = dcpomatic::encrypt (i.certificate(true), key_from_uuid(), iv);
- memcpy (p, e.data().get(), e.size());
- p += e.size();
- DCPOMATIC_ASSERT (N < 8);
- header->cert_length[N] = e.size ();
- ++N;
- }
-
- dcp::Data k = dcpomatic::encrypt (chain->key().get(), key_from_uuid(), iv);
- memcpy (p, k.data().get(), k.size());
- p += k.size();
- header->private_key_length = k.size ();
-
- FILE* f = fopen_boost (output, "wb");
- checked_fwrite (buffer.get(), p - buffer.get(), f, output);
- fclose (f);
-}
-
-#endif
-
double
db_to_linear (double db)
{
return dcp::DecryptedKDM (kdm, Config::instance()->decryption_chain()->key().get());
} catch (dcp::KDMDecryptionError& e) {
/* Try to flesh out the error a bit */
- string const kdm_subject_name = kdm.recipient_x509_subject_name();
+ auto const kdm_subject_name = kdm.recipient_x509_subject_name();
bool on_chain = false;
- shared_ptr<const dcp::CertificateChain> dc = Config::instance()->decryption_chain();
- BOOST_FOREACH (dcp::Certificate i, dc->root_to_leaf()) {
+ auto dc = Config::instance()->decryption_chain();
+ for (auto i: dc->root_to_leaf()) {
if (i.subject() == kdm_subject_name) {
on_chain = true;
}
}
if (!on_chain) {
throw KDMError (_("This KDM was not made for DCP-o-matic's decryption certificate."), e.what());
- } else if (on_chain && kdm_subject_name != dc->leaf().subject()) {
+ } else if (kdm_subject_name != dc->leaf().subject()) {
throw KDMError (_("This KDM was made for DCP-o-matic but not for its leaf certificate."), e.what());
} else {
throw;
return liberation_normal;
}
+
+
+string
+to_upper (string s)
+{
+ transform (s.begin(), s.end(), s.begin(), ::toupper);
+ return s;
+}
+
+
+/* Set to 1 to print the IDs of some of our threads to stdout on creation */
+#define DCPOMATIC_DEBUG_THREADS 0
+
+#if DCPOMATIC_DEBUG_THREADS
+void
+start_of_thread (string name)
+{
+ std::cout << "THREAD:" << name << ":" << std::hex << pthread_self() << "\n";
+}
+#else
+void
+start_of_thread (string)
+{
+
+}
+#endif
+