From 3339d3bce70afe9ae2ca10e9fcfc4b54b748fbf4 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 8 Apr 2021 21:32:44 +0200 Subject: [PATCH] Assorted C++11/formatting cleanups. --- src/lib/audio_analysis.cc | 62 +++++++++------- src/lib/audio_analysis.h | 14 ++-- src/lib/audio_decoder.cc | 11 ++- src/lib/audio_decoder.h | 8 ++- src/lib/cross_windows.cc | 88 ++++++++++++++--------- src/lib/dcp.cc | 17 ++--- src/lib/dcp.h | 15 +++- src/lib/dcpomatic_time.h | 44 +++++++----- src/lib/dcpomatic_time_coalesce.h | 10 ++- src/lib/ffmpeg_examiner.cc | 48 ++++++++----- src/lib/ffmpeg_examiner.h | 16 +++-- src/lib/j2k_encoder.cc | 18 ++++- src/lib/j2k_encoder.h | 11 ++- src/lib/json_server.cc | 35 +++++---- src/lib/kdm_with_metadata.cc | 45 ++++++------ src/lib/kdm_with_metadata.h | 14 ++-- src/lib/player_text.h | 2 +- src/lib/rect.h | 12 +++- src/lib/render_text.cc | 106 +++++++++++++++------------- src/lib/send_kdm_email_job.cc | 12 +++- src/lib/send_kdm_email_job.h | 10 ++- src/lib/subtitle_analysis.cc | 13 ++-- src/lib/subtitle_analysis.h | 10 +-- src/lib/timer.cc | 33 ++++++--- src/lib/timer.h | 6 +- src/lib/video_content.h | 3 +- src/lib/zipper.cc | 6 +- src/lib/zipper.h | 6 +- src/tools/dcpomatic_player.cc | 1 + src/tools/dcpomatic_playlist.cc | 110 +++++++++++++++-------------- src/wx/film_viewer.cc | 113 +++++++++++++++++++----------- src/wx/film_viewer.h | 28 ++++---- src/wx/timeline_reels_view.cc | 20 ++++-- src/wx/timeline_reels_view.h | 6 +- test/audio_merger_test.cc | 28 +++++--- test/dcp_decoder_test.cc | 1 + 36 files changed, 606 insertions(+), 376 deletions(-) diff --git a/src/lib/audio_analysis.cc b/src/lib/audio_analysis.cc index 22c14c764..b16fa708a 100644 --- a/src/lib/audio_analysis.cc +++ b/src/lib/audio_analysis.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2018 Carl Hetherington + Copyright (C) 2012-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,6 +18,7 @@ */ + #include "audio_analysis.h" #include "cross.h" #include "util.h" @@ -35,28 +36,33 @@ DCPOMATIC_ENABLE_WARNINGS #include #include -using std::ostream; -using std::istream; -using std::string; -using std::vector; + using std::cout; +using std::dynamic_pointer_cast; +using std::istream; +using std::list; +using std::make_pair; +using std::make_shared; using std::max; +using std::ostream; using std::pair; -using std::make_pair; -using std::list; using std::shared_ptr; +using std::string; +using std::vector; using boost::optional; -using std::dynamic_pointer_cast; using dcp::raw_convert; using namespace dcpomatic; + int const AudioAnalysis::_current_state_version = 3; + AudioAnalysis::AudioAnalysis (int channels) { _data.resize (channels); } + AudioAnalysis::AudioAnalysis (boost::filesystem::path filename) { cxml::Document f ("AudioAnalysis"); @@ -79,26 +85,27 @@ AudioAnalysis::AudioAnalysis (boost::filesystem::path filename) for (auto i: f.node_children ("SamplePeak")) { _sample_peak.push_back ( - PeakTime ( + PeakTime( dcp::raw_convert(i->content()), DCPTime(i->number_attribute("Time")) ) ); } - for (auto i: f.node_children ("TruePeak")) { - _true_peak.push_back (dcp::raw_convert (i->content ())); + for (auto i: f.node_children("TruePeak")) { + _true_peak.push_back (dcp::raw_convert(i->content())); } - _integrated_loudness = f.optional_number_child ("IntegratedLoudness"); - _loudness_range = f.optional_number_child ("LoudnessRange"); + _integrated_loudness = f.optional_number_child("IntegratedLoudness"); + _loudness_range = f.optional_number_child("LoudnessRange"); - _analysis_gain = f.optional_number_child ("AnalysisGain"); - _samples_per_point = f.number_child ("SamplesPerPoint"); - _sample_rate = f.number_child ("SampleRate"); + _analysis_gain = f.optional_number_child("AnalysisGain"); + _samples_per_point = f.number_child("SamplesPerPoint"); + _sample_rate = f.number_child("SampleRate"); _leqm = f.optional_number_child("Leqm"); } + void AudioAnalysis::add_point (int c, AudioPoint const & p) { @@ -106,43 +113,47 @@ AudioAnalysis::add_point (int c, AudioPoint const & p) _data[c].push_back (p); } + AudioPoint AudioAnalysis::get_point (int c, int p) const { - DCPOMATIC_ASSERT (p < points (c)); + DCPOMATIC_ASSERT (p < points(c)); return _data[c][p]; } + int AudioAnalysis::channels () const { return _data.size (); } + int AudioAnalysis::points (int c) const { - DCPOMATIC_ASSERT (c < channels ()); + DCPOMATIC_ASSERT (c < channels()); return _data[c].size (); } + void AudioAnalysis::write (boost::filesystem::path filename) { - shared_ptr doc (new xmlpp::Document); + auto doc = make_shared(); xmlpp::Element* root = doc->create_root_node ("AudioAnalysis"); - root->add_child("Version")->add_child_text (raw_convert (_current_state_version)); + root->add_child("Version")->add_child_text(raw_convert(_current_state_version)); for (auto& i: _data) { - xmlpp::Element* channel = root->add_child ("Channel"); + auto channel = root->add_child ("Channel"); for (auto& j: i) { j.as_xml (channel->add_child ("Point")); } } for (size_t i = 0; i < _sample_peak.size(); ++i) { - xmlpp::Element* n = root->add_child("SamplePeak"); + auto n = root->add_child("SamplePeak"); n->add_child_text (raw_convert (_sample_peak[i].peak)); n->set_attribute ("Time", raw_convert (_sample_peak[i].time.get())); } @@ -173,6 +184,7 @@ AudioAnalysis::write (boost::filesystem::path filename) doc->write_to_file_formatted (filename.string ()); } + float AudioAnalysis::gain_correction (shared_ptr playlist) { @@ -182,17 +194,18 @@ AudioAnalysis::gain_correction (shared_ptr playlist) what correction is now needed to make it look `right'. */ DCPOMATIC_ASSERT (playlist->content().front()->audio); - return playlist->content().front()->audio->gain() - analysis_gain().get (); + return playlist->content().front()->audio->gain() - analysis_gain().get(); } return 0.0f; } + /** @return Peak across all channels, and the channel number it is on */ pair AudioAnalysis::overall_sample_peak () const { - DCPOMATIC_ASSERT (!_sample_peak.empty ()); + DCPOMATIC_ASSERT (!_sample_peak.empty()); optional pt; int c = 0; @@ -207,6 +220,7 @@ AudioAnalysis::overall_sample_peak () const return make_pair (pt.get(), c); } + optional AudioAnalysis::overall_true_peak () const { diff --git a/src/lib/audio_analysis.h b/src/lib/audio_analysis.h index c3aec6e29..263e8a8a0 100644 --- a/src/lib/audio_analysis.h +++ b/src/lib/audio_analysis.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2018 Carl Hetherington + Copyright (C) 2012-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,9 +18,11 @@ */ + #ifndef DCPOMATIC_AUDIO_ANALYSIS_H #define DCPOMATIC_AUDIO_ANALYSIS_H + #include "dcpomatic_time.h" #include "audio_point.h" #include @@ -28,12 +30,15 @@ #include #include + namespace xmlpp { class Element; } + class Playlist; + class AudioAnalysis : public boost::noncopyable { public: @@ -129,7 +134,7 @@ public: float gain_correction (std::shared_ptr playlist); private: - std::vector > _data; + std::vector> _data; std::vector _sample_peak; std::vector _true_peak; boost::optional _integrated_loudness; @@ -140,10 +145,11 @@ private: * happened. */ boost::optional _analysis_gain; - int64_t _samples_per_point; - int _sample_rate; + int64_t _samples_per_point = 0; + int _sample_rate = 0; static int const _current_state_version; }; + #endif diff --git a/src/lib/audio_decoder.cc b/src/lib/audio_decoder.cc index f7f147bd9..77c9b0695 100644 --- a/src/lib/audio_decoder.cc +++ b/src/lib/audio_decoder.cc @@ -18,6 +18,7 @@ */ + #include "audio_decoder.h" #include "audio_buffers.h" #include "audio_content.h" @@ -29,6 +30,7 @@ #include "i18n.h" + using std::cout; using std::map; using std::pair; @@ -37,6 +39,7 @@ using std::make_shared; using boost::optional; using namespace dcpomatic; + AudioDecoder::AudioDecoder (Decoder* parent, shared_ptr content, bool fast) : DecoderPart (parent) , _content (content) @@ -48,6 +51,7 @@ AudioDecoder::AudioDecoder (Decoder* parent, shared_ptr cont } } + /** @param time_already_delayed true if the delay should not be added to time */ void AudioDecoder::emit (shared_ptr film, AudioStreamPtr stream, shared_ptr data, ContentTime time, bool time_already_delayed) @@ -97,7 +101,7 @@ AudioDecoder::emit (shared_ptr film, AudioStreamPtr stream, shared_p shared_ptr resampler; auto i = _resamplers.find(stream); - if (i != _resamplers.end ()) { + if (i != _resamplers.end()) { resampler = i->second; } else { if (stream->frame_rate() != resampled_rate) { @@ -128,6 +132,7 @@ AudioDecoder::emit (shared_ptr film, AudioStreamPtr stream, shared_p _positions[stream] += data->frames(); } + /** @return Time just after the last thing that was emitted from a given stream */ ContentTime AudioDecoder::stream_position (shared_ptr film, AudioStreamPtr stream) const @@ -137,6 +142,7 @@ AudioDecoder::stream_position (shared_ptr film, AudioStreamPtr strea return ContentTime::from_frames (i->second, _content->resampled_frame_rate(film)); } + boost::optional AudioDecoder::position (shared_ptr film) const { @@ -151,6 +157,7 @@ AudioDecoder::position (shared_ptr film) const return p; } + void AudioDecoder::seek () { @@ -164,6 +171,7 @@ AudioDecoder::seek () } } + void AudioDecoder::flush () { @@ -181,6 +189,7 @@ AudioDecoder::flush () } } + void AudioDecoder::silence (int milliseconds) { diff --git a/src/lib/audio_decoder.h b/src/lib/audio_decoder.h index 2b6e3f758..754321880 100644 --- a/src/lib/audio_decoder.h +++ b/src/lib/audio_decoder.h @@ -18,19 +18,23 @@ */ + /** @file src/lib/audio_decoder.h * @brief Parent class for audio decoders. */ + #ifndef DCPOMATIC_AUDIO_DECODER_H #define DCPOMATIC_AUDIO_DECODER_H + #include "decoder.h" #include "content_audio.h" #include "audio_stream.h" #include "decoder_part.h" #include + class AudioBuffers; class AudioContent; class AudioDecoderStream; @@ -38,6 +42,7 @@ class Log; class Film; class Resampler; + /** @class AudioDecoder. * @brief Parent class for audio decoders. */ @@ -64,10 +69,11 @@ private: */ typedef std::map PositionMap; PositionMap _positions; - typedef std::map > ResamplerMap; + typedef std::map> ResamplerMap; ResamplerMap _resamplers; bool _fast; }; + #endif diff --git a/src/lib/cross_windows.cc b/src/lib/cross_windows.cc index 0ab56bb6b..04ee26271 100644 --- a/src/lib/cross_windows.cc +++ b/src/lib/cross_windows.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2020 Carl Hetherington + Copyright (C) 2012-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,6 +18,7 @@ */ + #include "cross.h" #include "compose.hpp" #include "log.h" @@ -47,21 +48,24 @@ extern "C" { #include "i18n.h" + using std::pair; -using std::list; -using std::ifstream; -using std::string; -using std::wstring; -using std::make_pair; -using std::vector; using std::cerr; using std::cout; -using std::runtime_error; +using std::ifstream; +using std::list; +using std::make_pair; using std::map; +using std::runtime_error; using std::shared_ptr; +using std::string; +using std::vector; +using std::wstring; using boost::optional; -static std::vector > locked_volumes; + +static std::vector> locked_volumes; + /** @param s Number of seconds to sleep for */ void @@ -70,12 +74,14 @@ dcpomatic_sleep_seconds (int s) Sleep (s * 1000); } + void dcpomatic_sleep_milliseconds (int ms) { Sleep (ms); } + /** @return A string of CPU information (model name etc.) */ string cpu_info () @@ -110,6 +116,7 @@ cpu_info () return info; } + void run_ffprobe (boost::filesystem::path content, boost::filesystem::path out) { @@ -150,7 +157,7 @@ run_ffprobe (boost::filesystem::path content, boost::filesystem::path out) return; } - FILE* o = fopen_boost (out, "w"); + auto o = fopen_boost (out, "w"); if (!o) { LOG_ERROR_NC (N_("ffprobe call failed (could not create output file)")); return; @@ -175,11 +182,11 @@ run_ffprobe (boost::filesystem::path content, boost::filesystem::path out) CloseHandle (child_stderr_read); } -list > + +list> mount_info () { - list > m; - return m; + return {}; } @@ -239,12 +246,14 @@ fopen_boost (boost::filesystem::path p, string t) return _wfopen (p.c_str(), w.c_str ()); } + int dcpomatic_fseek (FILE* stream, int64_t offset, int whence) { return _fseeki64 (stream, offset, whence); } + void Waker::nudge () { @@ -252,11 +261,13 @@ Waker::nudge () SetThreadExecutionState (ES_SYSTEM_REQUIRED); } + Waker::Waker () { } + Waker::~Waker () { @@ -266,7 +277,7 @@ Waker::~Waker () void start_tool (string executable) { - boost::filesystem::path batch = directory_containing_executable() / executable; + auto batch = directory_containing_executable() / executable; STARTUPINFO startup_info; ZeroMemory (&startup_info, sizeof (startup_info)); @@ -301,6 +312,7 @@ thread_id () return (uint64_t) GetCurrentThreadId (); } + static string wchar_to_utf8 (wchar_t const * s) { @@ -312,38 +324,42 @@ wchar_to_utf8 (wchar_t const * s) return u; } + int avio_open_boost (AVIOContext** s, boost::filesystem::path file, int flags) { return avio_open (s, wchar_to_utf8(file.c_str()).c_str(), flags); } + void maybe_open_console () { if (Config::instance()->win32_console ()) { AllocConsole(); - HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE); + auto handle_out = GetStdHandle(STD_OUTPUT_HANDLE); int hCrt = _open_osfhandle((intptr_t) handle_out, _O_TEXT); - FILE* hf_out = _fdopen(hCrt, "w"); + auto hf_out = _fdopen(hCrt, "w"); setvbuf(hf_out, NULL, _IONBF, 1); *stdout = *hf_out; - HANDLE handle_in = GetStdHandle(STD_INPUT_HANDLE); + auto handle_in = GetStdHandle(STD_INPUT_HANDLE); hCrt = _open_osfhandle((intptr_t) handle_in, _O_TEXT); - FILE* hf_in = _fdopen(hCrt, "r"); + auto hf_in = _fdopen(hCrt, "r"); setvbuf(hf_in, NULL, _IONBF, 128); *stdin = *hf_in; } } + boost::filesystem::path home_directory () { return boost::filesystem::path(getenv("HOMEDRIVE")) / boost::filesystem::path(getenv("HOMEPATH")); } + /** @return true if this process is a 32-bit one running on a 64-bit-capable OS */ bool running_32_on_64 () @@ -353,6 +369,7 @@ running_32_on_64 () return p; } + static optional get_friendly_name (HDEVINFO device_info, SP_DEVINFO_DATA* device_info_data) { @@ -367,10 +384,12 @@ get_friendly_name (HDEVINFO device_info, SP_DEVINFO_DATA* device_info_data) return wchar_to_utf8 (buffer); } + static const GUID GUID_DEVICE_INTERFACE_DISK = { 0x53F56307L, 0xB6BF, 0x11D0, { 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B } }; + static optional get_device_number (HDEVINFO device_info, SP_DEVINFO_DATA* device_info_data) { @@ -379,7 +398,7 @@ get_device_number (HDEVINFO device_info, SP_DEVINFO_DATA* device_info_data) SP_DEVICE_INTERFACE_DATA device_interface_data; device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - BOOL r = SetupDiEnumDeviceInterfaces (device_info, device_info_data, &GUID_DEVICE_INTERFACE_DISK, 0, &device_interface_data); + auto r = SetupDiEnumDeviceInterfaces (device_info, device_info_data, &GUID_DEVICE_INTERFACE_DISK, 0, &device_interface_data); if (!r) { LOG_DISK("SetupDiEnumDeviceInterfaces failed (%1)", GetLastError()); return optional(); @@ -407,7 +426,7 @@ get_device_number (HDEVINFO device_info, SP_DEVINFO_DATA* device_info_data) /* Open it. We would not be allowed GENERIC_READ access here but specifying 0 for dwDesiredAccess allows us to query some metadata. */ - HANDLE device = CreateFileW ( + auto device = CreateFileW ( device_detail_data->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0 @@ -430,13 +449,15 @@ get_device_number (HDEVINFO device_info, SP_DEVINFO_DATA* device_info_data) CloseHandle (device); if (!r) { - return optional(); + return {}; } return device_number.DeviceNumber; } -typedef map > MountPoints; + +typedef map> MountPoints; + /** Take a volume path (with a trailing \) and add any disk numbers related to that volume * to @ref disks. @@ -463,7 +484,7 @@ add_volume_mount_points (wchar_t* volume, MountPoints& mount_points) DCPOMATIC_ASSERT (len > 0); volume[len - 1] = L'\0'; - HANDLE handle = CreateFileW ( + auto handle = CreateFileW ( volume, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0 @@ -483,13 +504,14 @@ add_volume_mount_points (wchar_t* volume, MountPoints& mount_points) mount_points[extents.Extents[0].DiskNumber] = mp; } + MountPoints find_mount_points () { MountPoints mount_points; wchar_t volume_name[512]; - HANDLE volume = FindFirstVolumeW (volume_name, sizeof(volume_name) / sizeof(wchar_t)); + auto volume = FindFirstVolumeW (volume_name, sizeof(volume_name) / sizeof(wchar_t)); if (volume == INVALID_HANDLE_VALUE) { return MountPoints(); } @@ -506,15 +528,16 @@ find_mount_points () return mount_points; } + vector Drive::get () { vector drives; - MountPoints mount_points = find_mount_points (); + auto mount_points = find_mount_points (); /* Get a `device information set' containing information about all disks */ - HDEVINFO device_info = SetupDiGetClassDevsA (&GUID_DEVICE_INTERFACE_DISK, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + auto device_info = SetupDiGetClassDevsA (&GUID_DEVICE_INTERFACE_DISK, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (device_info == INVALID_HANDLE_VALUE) { LOG_DISK_NC ("SetupDiClassDevsA failed"); return drives; @@ -534,8 +557,8 @@ Drive::get () } ++i; - optional const friendly_name = get_friendly_name (device_info, &device_info_data); - optional device_number = get_device_number (device_info, &device_info_data); + auto const friendly_name = get_friendly_name (device_info, &device_info_data); + auto device_number = get_device_number (device_info, &device_info_data); if (!device_number) { continue; } @@ -562,8 +585,8 @@ Drive::get () LOG_DISK("Having a look through %1 locked volumes", locked_volumes.size()); bool locked = false; - for (vector >::const_iterator i = locked_volumes.begin(); i != locked_volumes.end(); ++i) { - if (i->second == physical_drive) { + for (auto const& i: locked_volumes) { + if (i.second == physical_drive) { locked = true; } } @@ -619,11 +642,12 @@ config_path () return p; } + void disk_write_finished () { - for (vector >::const_iterator i = locked_volumes.begin(); i != locked_volumes.end(); ++i) { - CloseHandle (i->first); + for (auto const& i: locked_volumes) { + CloseHandle (i.first); } } diff --git a/src/lib/dcp.cc b/src/lib/dcp.cc index 06e3e15d5..d99c32bf3 100644 --- a/src/lib/dcp.cc +++ b/src/lib/dcp.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2018 Carl Hetherington + Copyright (C) 2014-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,19 +18,20 @@ */ -#include "dcp.h" -#include "config.h" -#include "film.h" -#include "log.h" -#include "dcpomatic_log.h" + #include "compose.hpp" +#include "dcp.h" #include "dcp_content.h" +#include "dcpomatic_log.h" +#include "log.h" +#include "util.h" #include #include #include #include "i18n.h" + using std::list; using std::string; using std::shared_ptr; @@ -40,7 +41,7 @@ using std::vector; /** Find all the CPLs in our directories, cross-add assets and return the CPLs */ -list > +list> DCP::cpls () const { list> dcps; @@ -77,7 +78,7 @@ DCP::cpls () const } if (_dcp_content->kdm ()) { - dcp::DecryptedKDM k = decrypt_kdm_with_helpful_error (_dcp_content->kdm().get()); + auto k = decrypt_kdm_with_helpful_error (_dcp_content->kdm().get()); for (auto i: dcps) { i->add (k); } diff --git a/src/lib/dcp.h b/src/lib/dcp.h index d72ce6833..d8e0aec27 100644 --- a/src/lib/dcp.h +++ b/src/lib/dcp.h @@ -18,19 +18,27 @@ */ + #ifndef DCPOMATIC_DCP_H #define DCPOMATIC_DCP_H -#include + #include -#include +#include + + +namespace dcp { + class CPL; +} + class DCPContent; + class DCP { public: - std::list > cpls () const; + std::list> cpls () const; protected: explicit DCP (std::shared_ptr content, bool tolerant) @@ -44,4 +52,5 @@ private: bool _tolerant; }; + #endif diff --git a/src/lib/dcpomatic_time.h b/src/lib/dcpomatic_time.h index 00a31a7a7..9e7191b1e 100644 --- a/src/lib/dcpomatic_time.h +++ b/src/lib/dcpomatic_time.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2018 Carl Hetherington + Copyright (C) 2014-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,13 +18,16 @@ */ + /** @file src/lib/dcpomatic_time.h * @brief Types to describe time. */ + #ifndef DCPOMATIC_TIME_H #define DCPOMATIC_TIME_H + #include "frame_rate_change.h" #include "dcpomatic_assert.h" #include @@ -34,9 +37,11 @@ #include #include + struct dcpomatic_time_ceil_test; struct dcpomatic_time_floor_test; + namespace dcpomatic { @@ -156,15 +161,15 @@ public: * @param r Sampling rate. */ Time ceil (double r) const { - return Time (llrint (HZ * frames_ceil(r) / r)); + return Time (llrint(HZ * frames_ceil(r) / r)); } Time floor (double r) const { - return Time (llrint (HZ * frames_floor(r) / r)); + return Time (llrint(HZ * frames_floor(r) / r)); } Time round (double r) const { - return Time (llrint (HZ * frames_round(r) / r)); + return Time (llrint(HZ * frames_round(r) / r)); } double seconds () const { @@ -172,7 +177,7 @@ public: } Time abs () const { - return Time (std::abs (_t)); + return Time (std::abs(_t)); } template @@ -231,7 +236,6 @@ public: return buffer; } - static Time from_seconds (double s) { return Time (llrint (s * HZ)); } @@ -263,9 +267,11 @@ private: Type _t; }; + class ContentTimeDifferentiator {}; class DCPTimeDifferentiator {}; + /* Specializations for the two allowed explicit conversions */ template<> @@ -274,6 +280,7 @@ Time::Time (Time Time::Time (Time d, FrameRateChange f); + /** Time relative to the start or position of a piece of content in its native frame rate */ typedef Time ContentTime; /** Time relative to the start of the output DCP in its frame rate */ @@ -303,12 +310,12 @@ public: return TimePeriod (from + o, to + o); } - boost::optional > overlap (TimePeriod const & other) const { + boost::optional> overlap (TimePeriod const & other) const { T const max_from = std::max (from, other.from); T const min_to = std::min (to, other.to); if (max_from >= min_to) { - return boost::optional > (); + return {}; } return TimePeriod (max_from, min_to); @@ -334,36 +341,37 @@ public: } }; + /** @param A Period which is subtracted from. * @param B Periods to subtract from `A', must be in ascending order of start time and must not overlap. */ template -std::list > subtract (TimePeriod A, std::list > const & B) +std::list> subtract (TimePeriod A, std::list> const & B) { - std::list > result; + std::list> result; result.push_back (A); for (auto i: B) { - std::list > new_result; + std::list> new_result; for (auto j: result) { - boost::optional > ov = i.overlap (j); + auto ov = i.overlap (j); if (ov) { if (*ov == i) { /* A contains all of B */ if (i.from != j.from) { - new_result.push_back (TimePeriod (j.from, i.from)); + new_result.push_back (TimePeriod(j.from, i.from)); } if (i.to != j.to) { - new_result.push_back (TimePeriod (i.to, j.to)); + new_result.push_back (TimePeriod(i.to, j.to)); } } else if (*ov == j) { /* B contains all of A */ } else if (i.from < j.from) { /* B overlaps start of A */ - new_result.push_back (TimePeriod (i.to, j.to)); + new_result.push_back (TimePeriod(i.to, j.to)); } else if (i.to > j.to) { /* B overlaps end of A */ - new_result.push_back (TimePeriod (j.from, i.from)); + new_result.push_back (TimePeriod(j.from, i.from)); } } else { new_result.push_back (j); @@ -375,9 +383,11 @@ std::list > subtract (TimePeriod A, std::list > c return result; } + typedef TimePeriod ContentTimePeriod; typedef TimePeriod DCPTimePeriod; + DCPTime min (DCPTime a, DCPTime b); DCPTime max (DCPTime a, DCPTime b); ContentTime min (ContentTime a, ContentTime b); @@ -386,6 +396,8 @@ std::string to_string (ContentTime t); std::string to_string (DCPTime t); std::string to_string (DCPTimePeriod p); + } + #endif diff --git a/src/lib/dcpomatic_time_coalesce.h b/src/lib/dcpomatic_time_coalesce.h index 56f82bcb6..015326bdd 100644 --- a/src/lib/dcpomatic_time_coalesce.h +++ b/src/lib/dcpomatic_time_coalesce.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2017 Carl Hetherington + Copyright (C) 2017-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,17 +18,20 @@ */ + #include "dcpomatic_time.h" #include + namespace dcpomatic { + /** @param periods Set of periods in ascending order of from time */ template -std::list > coalesce (std::list > periods) +std::list> coalesce (std::list> periods) { bool did_something; - std::list > coalesced; + std::list> coalesced; do { coalesced.clear (); did_something = false; @@ -49,4 +52,5 @@ std::list > coalesce (std::list > periods) return periods; } + } diff --git a/src/lib/ffmpeg_examiner.cc b/src/lib/ffmpeg_examiner.cc index ed867b475..39951d139 100644 --- a/src/lib/ffmpeg_examiner.cc +++ b/src/lib/ffmpeg_examiner.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2015 Carl Hetherington + Copyright (C) 2013-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,6 +18,7 @@ */ + #include "dcpomatic_log.h" #include "ffmpeg_examiner.h" #include "ffmpeg_content.h" @@ -40,11 +41,13 @@ DCPOMATIC_ENABLE_WARNINGS #include "i18n.h" -using std::string; + using std::cout; +using std::make_shared; using std::max; -using std::vector; using std::shared_ptr; +using std::string; +using std::vector; using boost::optional; using namespace dcpomatic; @@ -65,7 +68,7 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr c, shared_ptrnb_streams; ++i) { - AVStream* s = _format_context->streams[i]; + auto s = _format_context->streams[i]; DCPOMATIC_DISABLE_WARNINGS if (s->codec->codec_type == AVMEDIA_TYPE_AUDIO) { @@ -82,15 +85,13 @@ DCPOMATIC_DISABLE_WARNINGS DCPOMATIC_ASSERT (s->codec->codec->name); _audio_streams.push_back ( - shared_ptr ( - new FFmpegAudioStream ( - stream_name (s), - s->codec->codec->name, - s->id, - s->codec->sample_rate, - llrint ((double (_format_context->duration) / AV_TIME_BASE) * s->codec->sample_rate), - s->codec->channels - ) + make_shared( + stream_name (s), + s->codec->codec->name, + s->id, + s->codec->sample_rate, + llrint ((double(_format_context->duration) / AV_TIME_BASE) * s->codec->sample_rate), + s->codec->channels ) ); @@ -295,12 +296,14 @@ FFmpegExaminer::video_frame_rate () const return av_q2d(av_guess_frame_rate(_format_context, _format_context->streams[_video_stream.get()], 0)); } + dcp::Size FFmpegExaminer::video_size () const { return dcp::Size (video_codec_context()->width, video_codec_context()->height); } + /** @return Length according to our content's header */ Frame FFmpegExaminer::video_length () const @@ -308,11 +311,12 @@ FFmpegExaminer::video_length () const return max (Frame (1), _video_length); } + optional FFmpegExaminer::sample_aspect_ratio () const { DCPOMATIC_ASSERT (_video_stream); - AVRational sar = av_guess_sample_aspect_ratio (_format_context, _format_context->streams[_video_stream.get()], 0); + auto sar = av_guess_sample_aspect_ratio (_format_context, _format_context->streams[_video_stream.get()], 0); if (sar.num == 0) { /* I assume this means that we don't know */ return {}; @@ -320,6 +324,7 @@ FFmpegExaminer::sample_aspect_ratio () const return double (sar.num) / sar.den; } + string FFmpegExaminer::subtitle_stream_name (AVStream* s) const { @@ -332,18 +337,19 @@ FFmpegExaminer::subtitle_stream_name (AVStream* s) const return n; } + string FFmpegExaminer::stream_name (AVStream* s) const { string n; if (s->metadata) { - AVDictionaryEntry const * lang = av_dict_get (s->metadata, "language", 0, 0); + auto const lang = av_dict_get (s->metadata, "language", 0, 0); if (lang) { n = lang->value; } - AVDictionaryEntry const * title = av_dict_get (s->metadata, "title", 0, 0); + auto const title = av_dict_get (s->metadata, "title", 0, 0); if (title) { if (!n.empty()) { n += " "; @@ -355,18 +361,20 @@ FFmpegExaminer::stream_name (AVStream* s) const return n; } + optional FFmpegExaminer::bits_per_pixel () const { if (video_codec_context()->pix_fmt == -1) { - return optional(); + return {}; } - AVPixFmtDescriptor const * d = av_pix_fmt_desc_get (video_codec_context()->pix_fmt); + auto const d = av_pix_fmt_desc_get (video_codec_context()->pix_fmt); DCPOMATIC_ASSERT (d); return av_get_bits_per_pixel (d); } + bool FFmpegExaminer::yuv () const { @@ -448,12 +456,14 @@ FFmpegExaminer::yuv () const } } + bool FFmpegExaminer::has_video () const { - return static_cast (_video_stream); + return static_cast(_video_stream); } + VideoRange FFmpegExaminer::range () const { diff --git a/src/lib/ffmpeg_examiner.h b/src/lib/ffmpeg_examiner.h index 0884a6fb8..793460f9b 100644 --- a/src/lib/ffmpeg_examiner.h +++ b/src/lib/ffmpeg_examiner.h @@ -18,20 +18,22 @@ */ + #include "ffmpeg.h" #include "video_examiner.h" #include -struct AVStream; +struct AVStream; class FFmpegAudioStream; class FFmpegSubtitleStream; class Job; + class FFmpegExaminer : public FFmpeg, public VideoExaminer { public: - FFmpegExaminer (std::shared_ptr, std::shared_ptr job = std::shared_ptr ()); + FFmpegExaminer (std::shared_ptr, std::shared_ptr job = std::shared_ptr()); bool has_video () const; @@ -41,11 +43,11 @@ public: boost::optional sample_aspect_ratio () const; bool yuv () const; - std::vector > subtitle_streams () const { + std::vector> subtitle_streams () const { return _subtitle_streams; } - std::vector > audio_streams () const { + std::vector> audio_streams () const { return _audio_streams; } @@ -89,8 +91,8 @@ private: std::string subtitle_stream_name (AVStream* s) const; boost::optional frame_time (AVStream* s) const; - std::vector > _subtitle_streams; - std::vector > _audio_streams; + std::vector> _subtitle_streams; + std::vector> _audio_streams; boost::optional _first_video; /** Video length, either obtained from the header or derived by running * through the whole file. @@ -115,6 +117,6 @@ private: dcpomatic::ContentTime time; }; - typedef std::map, boost::optional > LastSubtitleMap; + typedef std::map, boost::optional> LastSubtitleMap; LastSubtitleMap _last_subtitle_start; }; diff --git a/src/lib/j2k_encoder.cc b/src/lib/j2k_encoder.cc index a7fa657f8..c2553854b 100644 --- a/src/lib/j2k_encoder.cc +++ b/src/lib/j2k_encoder.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2019 Carl Hetherington + Copyright (C) 2012-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,10 +18,12 @@ */ + /** @file src/j2k_encoder.cc * @brief J2K encoder class. */ + #include "j2k_encoder.h" #include "util.h" #include "film.h" @@ -41,6 +43,7 @@ #include "i18n.h" + using std::list; using std::cout; using std::exception; @@ -51,6 +54,7 @@ using boost::optional; using dcp::Data; using namespace dcpomatic; + /** @param film Film that we are encoding. * @param writer Writer that we are using. */ @@ -62,21 +66,24 @@ J2KEncoder::J2KEncoder (shared_ptr film, shared_ptr writer) servers_list_changed (); } + J2KEncoder::~J2KEncoder () { boost::mutex::scoped_lock lm (_threads_mutex); terminate_threads (); } + void J2KEncoder::begin () { - weak_ptr wp = shared_from_this (); + auto wp = shared_from_this (); _server_found_connection = EncodeServerFinder::instance()->ServersListChanged.connect ( boost::bind (&J2KEncoder::call_servers_list_changed, wp) ); } + /* We don't want the servers-list-changed callback trying to do things during destruction of J2KEncoder, and I think this is the neatest way to achieve that. @@ -90,6 +97,7 @@ J2KEncoder::call_servers_list_changed (weak_ptr encoder) } } + void J2KEncoder::end () { @@ -142,6 +150,7 @@ J2KEncoder::end () } } + /** @return an estimate of the current number of frames we are encoding per second, * if known. */ @@ -151,6 +160,7 @@ J2KEncoder::current_encoding_rate () const return _history.rate (); } + /** @return Number of video frames that have been queued for encoding */ int J2KEncoder::video_frames_enqueued () const @@ -162,6 +172,7 @@ J2KEncoder::video_frames_enqueued () const return _last_player_video_time->frames_floor (_film->video_frame_rate ()); } + /** Should be called when a frame has been encoded successfully */ void J2KEncoder::frame_done () @@ -169,6 +180,7 @@ J2KEncoder::frame_done () _history.event (); } + /** Called to request encoding of the next video frame in the DCP. This is called in order, * so each time the supplied frame is the one after the previous one. * pv represents one video frame, and could be empty if there is nothing to encode @@ -266,6 +278,7 @@ J2KEncoder::terminate_threads () _threads.reset (); } + void J2KEncoder::encoder_thread (optional server) try @@ -373,6 +386,7 @@ catch (...) _full_condition.notify_all (); } + void J2KEncoder::servers_list_changed () { diff --git a/src/lib/j2k_encoder.h b/src/lib/j2k_encoder.h index 98cca6ba2..06b4d429c 100644 --- a/src/lib/j2k_encoder.h +++ b/src/lib/j2k_encoder.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2016 Carl Hetherington + Copyright (C) 2012-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,13 +18,16 @@ */ + #ifndef DCPOMATIC_J2K_ENCODER_H #define DCPOMATIC_J2K_ENCODER_H + /** @file src/j2k_encoder.h * @brief J2KEncoder class. */ + #include "util.h" #include "cross.h" #include "event_history.h" @@ -37,6 +40,7 @@ #include #include + class Film; class EncodeServerDescription; class DCPVideo; @@ -44,13 +48,13 @@ class Writer; class Job; class PlayerVideo; + /** @class J2KEncoder * @brief Class to manage encoding to J2K. * * This class keeps a queue of frames to be encoded and distributes * the work around threads and encoding servers. */ - class J2KEncoder : public boost::noncopyable, public ExceptionStore, public std::enable_shared_from_this { public: @@ -89,7 +93,7 @@ private: std::shared_ptr _threads; mutable boost::mutex _queue_mutex; - std::list > _queue; + std::list> _queue; /** condition to manage thread wakeups when we have nothing to do */ boost::condition _empty_condition; /** condition to manage thread wakeups when we have too much to do */ @@ -104,4 +108,5 @@ private: boost::signals2::scoped_connection _server_found_connection; }; + #endif diff --git a/src/lib/json_server.cc b/src/lib/json_server.cc index 9c1034a68..dd56b3124 100644 --- a/src/lib/json_server.cc +++ b/src/lib/json_server.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2015 Carl Hetherington + Copyright (C) 2014-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,6 +18,7 @@ */ + #include "json_server.h" #include "job_manager.h" #include "job.h" @@ -30,6 +31,7 @@ #include #include + using std::string; using std::cout; using std::map; @@ -40,8 +42,10 @@ using std::dynamic_pointer_cast; using boost::asio::ip::tcp; using dcp::raw_convert; + #define MAX_LENGTH 512 + enum State { AWAITING_G, AWAITING_E, @@ -50,16 +54,18 @@ enum State { READING_URL, }; + JSONServer::JSONServer (int port) { #ifdef DCPOMATIC_LINUX - thread* t = new thread (boost::bind (&JSONServer::run, this, port)); + auto t = new thread (boost::bind (&JSONServer::run, this, port)); pthread_setname_np (t->native_handle(), "json-server"); #else new thread (boost::bind (&JSONServer::run, this, port)); #endif } + void JSONServer::run (int port) try @@ -82,6 +88,7 @@ catch (...) } + void JSONServer::handle (shared_ptr socket) { @@ -97,11 +104,11 @@ JSONServer::handle (shared_ptr socket) break; } - char* p = data; - char* e = data + len; + auto p = data; + auto e = data + len; while (p != e) { - State old_state = state; + auto old_state = state; switch (state) { case AWAITING_G: if (*p == 'G') { @@ -143,14 +150,15 @@ JSONServer::handle (shared_ptr socket) } } + void JSONServer::request (string url, shared_ptr socket) { cout << "request: " << url << "\n"; - map r = split_get_request (url); - for (map::iterator i = r.begin(); i != r.end(); ++i) { - cout << i->first << " => " << i->second << "\n"; + auto r = split_get_request (url); + for (auto const& i: r) { + cout << i.first << " => " << i.second << "\n"; } string action; @@ -161,11 +169,10 @@ JSONServer::request (string url, shared_ptr socket) string json; if (action == "status") { - list > jobs = JobManager::instance()->get (); + auto jobs = JobManager::instance()->get(); json += "{ \"jobs\": ["; - for (list >::iterator i = jobs.begin(); i != jobs.end(); ++i) { - + for (auto i = jobs.cbegin(); i != jobs.cend(); ++i) { json += "{ "; if ((*i)->film()) { @@ -173,7 +180,7 @@ JSONServer::request (string url, shared_ptr socket) } json += "\"name\": \"" + (*i)->json_name() + "\", "; - if ((*i)->progress ()) { + if ((*i)->progress()) { json += "\"progress\": " + raw_convert((*i)->progress().get()) + ", "; } else { json += "\"progress\": unknown, "; @@ -181,7 +188,7 @@ JSONServer::request (string url, shared_ptr socket) json += "\"status\": \"" + (*i)->json_status() + "\""; json += " }"; - list >::iterator j = i; + auto j = i; ++j; if (j != jobs.end ()) { json += ", "; @@ -196,5 +203,5 @@ JSONServer::request (string url, shared_ptr socket) "\r\n" + json + "\r\n"; cout << "reply: " << json << "\n"; - boost::asio::write (*socket, boost::asio::buffer (reply.c_str(), reply.length())); + boost::asio::write (*socket, boost::asio::buffer(reply.c_str(), reply.length())); } diff --git a/src/lib/kdm_with_metadata.cc b/src/lib/kdm_with_metadata.cc index 92c95a401..fbd2e4bd4 100644 --- a/src/lib/kdm_with_metadata.cc +++ b/src/lib/kdm_with_metadata.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2016 Carl Hetherington + Copyright (C) 2013-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,6 +18,7 @@ */ + #include "kdm_with_metadata.h" #include "cinema.h" #include "screen.h" @@ -31,6 +32,7 @@ #include "i18n.h" + using std::string; using std::cout; using std::list; @@ -38,6 +40,7 @@ using std::shared_ptr; using boost::optional; using boost::function; + int write_files ( list kdms, @@ -64,7 +67,7 @@ write_files ( /* Write KDMs to the specified directory */ for (auto i: kdms) { - boost::filesystem::path out = directory / careful_string_filter(name_format.get(i->name_values(), ".xml")); + auto out = directory / careful_string_filter(name_format.get(i->name_values(), ".xml")); if (!boost::filesystem::exists (out) || confirm_overwrite (out)) { i->kdm_as_xml (out); ++written; @@ -78,9 +81,9 @@ write_files ( optional KDMWithMetadata::get (char k) const { - dcp::NameFormat::Map::const_iterator i = _name_values.find (k); + auto i = _name_values.find (k); if (i == _name_values.end()) { - return optional(); + return {}; } return i->second; @@ -93,7 +96,7 @@ make_zip_file (list kdms, boost::filesystem::path zip_file, Zipper zipper (zip_file); for (auto i: kdms) { - string const name = careful_string_filter(name_format.get(i->name_values(), ".xml")); + auto const name = careful_string_filter(name_format.get(i->name_values(), ".xml")); zipper.add (name, i->kdm_as_xml()); } @@ -104,14 +107,14 @@ make_zip_file (list kdms, boost::filesystem::path zip_file, /** Collect a list of KDMWithMetadatas into a list of lists so that * each list contains the KDMs for one list. */ -list > +list> collect (list kdms) { - list > grouped; + list> grouped; for (auto i: kdms) { - list >::iterator j = grouped.begin (); + auto j = grouped.begin (); while (j != grouped.end()) { if (j->front()->group() == i->group()) { @@ -134,7 +137,7 @@ collect (list kdms) /** Write one directory per list into another directory */ int write_directories ( - list > kdms, + list> kdms, boost::filesystem::path directory, dcp::NameFormat container_name_format, dcp::NameFormat filename_format, @@ -160,7 +163,7 @@ write_directories ( /** Write one ZIP file per cinema into a directory */ int write_zip_files ( - list > kdms, + list> kdms, boost::filesystem::path directory, dcp::NameFormat container_name_format, dcp::NameFormat filename_format, @@ -170,7 +173,7 @@ write_zip_files ( int written = 0; for (auto const& i: kdms) { - boost::filesystem::path path = directory; + auto path = directory; path /= container_name_format.get(i.front()->name_values(), ".zip", "s"); if (!boost::filesystem::exists (path) || confirm_overwrite (path)) { if (boost::filesystem::exists (path)) { @@ -195,13 +198,13 @@ write_zip_files ( */ void email ( - list > kdms, + list> kdms, dcp::NameFormat container_name_format, dcp::NameFormat filename_format, string cpl_name ) { - Config* config = Config::instance (); + auto config = Config::instance (); if (config->mail_server().empty()) { throw NetworkError (_("No mail server configured in preferences")); @@ -213,18 +216,18 @@ email ( continue; } - boost::filesystem::path zip_file = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + auto zip_file = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); boost::filesystem::create_directories (zip_file); zip_file /= container_name_format.get(i.front()->name_values(), ".zip"); make_zip_file (i, zip_file, filename_format); - string subject = config->kdm_subject(); + auto subject = config->kdm_subject(); boost::algorithm::replace_all (subject, "$CPL_NAME", cpl_name); boost::algorithm::replace_all (subject, "$START_TIME", i.front()->get('b').get_value_or("")); boost::algorithm::replace_all (subject, "$END_TIME", i.front()->get('e').get_value_or("")); boost::algorithm::replace_all (subject, "$CINEMA_NAME", i.front()->get('c').get_value_or("")); - string body = config->kdm_email().c_str(); + auto body = config->kdm_email(); boost::algorithm::replace_all (body, "$CPL_NAME", cpl_name); boost::algorithm::replace_all (body, "$START_TIME", i.front()->get('b').get_value_or("")); boost::algorithm::replace_all (body, "$END_TIME", i.front()->get('e').get_value_or("")); @@ -232,7 +235,7 @@ email ( string screens; for (auto j: i) { - optional screen_name = j->get('n'); + auto screen_name = j->get('n'); if (screen_name) { screens += *screen_name + ", "; } @@ -244,16 +247,14 @@ email ( for (auto i: config->kdm_cc()) { email.add_cc (i); } - if (!config->kdm_bcc().empty ()) { - email.add_bcc (config->kdm_bcc ()); + if (!config->kdm_bcc().empty()) { + email.add_bcc (config->kdm_bcc()); } email.add_attachment (zip_file, container_name_format.get(i.front()->name_values(), ".zip"), "application/zip"); - Config* c = Config::instance (); - try { - email.send (c->mail_server(), c->mail_port(), c->mail_protocol(), c->mail_user(), c->mail_password()); + email.send (config->mail_server(), config->mail_port(), config->mail_protocol(), config->mail_user(), config->mail_password()); } catch (...) { boost::filesystem::remove (zip_file); dcpomatic_log->log ("Email content follows", LogEntry::TYPE_DEBUG_EMAIL); diff --git a/src/lib/kdm_with_metadata.h b/src/lib/kdm_with_metadata.h index fc80a8743..99c2ef8dc 100644 --- a/src/lib/kdm_with_metadata.h +++ b/src/lib/kdm_with_metadata.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2019 Carl Hetherington + Copyright (C) 2013-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,14 +18,18 @@ */ + #ifndef DCPOMATIC_KDM_WITH_METADATA_H #define DCPOMATIC_KDM_WITH_METADATA_H + #include #include + class Cinema; + class KDMWithMetadata { public: @@ -78,11 +82,11 @@ int write_files ( void make_zip_file (std::list kdms, boost::filesystem::path zip_file, dcp::NameFormat name_format); -std::list > collect (std::list kdms); +std::list> collect (std::list kdms); int write_directories ( - std::list > kdms, + std::list> kdms, boost::filesystem::path directory, dcp::NameFormat container_name_format, dcp::NameFormat filename_format, @@ -91,7 +95,7 @@ int write_directories ( int write_zip_files ( - std::list > kdms, + std::list> kdms, boost::filesystem::path directory, dcp::NameFormat container_name_format, dcp::NameFormat filename_format, @@ -100,7 +104,7 @@ int write_zip_files ( void email ( - std::list > kdms, + std::list> kdms, dcp::NameFormat container_name_format, dcp::NameFormat filename_format, std::string cpl_name diff --git a/src/lib/player_text.h b/src/lib/player_text.h index cd4be984c..45c8bf589 100644 --- a/src/lib/player_text.h +++ b/src/lib/player_text.h @@ -38,7 +38,7 @@ class PlayerText { public: void add_fonts (std::list> fonts_); - std::list > fonts; + std::list> fonts; /** BitmapTexts, with their rectangles transformed as specified by their content */ std::list bitmap; diff --git a/src/lib/rect.h b/src/lib/rect.h index 4851ad007..5f807f499 100644 --- a/src/lib/rect.h +++ b/src/lib/rect.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Carl Hetherington + Copyright (C) 2013-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,18 +18,22 @@ */ + #ifndef DCPOMATIC_RECT_H #define DCPOMATIC_RECT_H + #include "position.h" #include #include + /* Put this inside a namespace as Apple put a Rect in the global namespace */ namespace dcpomatic { + /** @struct Rect * @brief A rectangle. */ @@ -69,7 +73,7 @@ public: return Position (x, y); } - boost::optional > intersection (Rect const & other) const + boost::optional> intersection (Rect const & other) const { /* This isn't exactly the paragon of mathematical precision */ @@ -83,7 +87,7 @@ public: ); if (r.width < 0 || r.height < 0) { - return boost::optional > (); + return {}; } return r; @@ -114,6 +118,8 @@ public: } }; + } + #endif diff --git a/src/lib/render_text.cc b/src/lib/render_text.cc index 2272d3506..d4d827a6b 100644 --- a/src/lib/render_text.cc +++ b/src/lib/render_text.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2016 Carl Hetherington + Copyright (C) 2014-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,14 +18,15 @@ */ -#include "render_text.h" -#include "types.h" -#include "image.h" + #include "cross.h" -#include "font.h" #include "dcpomatic_assert.h" -#include "warnings.h" +#include "font.h" +#include "image.h" +#include "render_text.h" +#include "types.h" #include "util.h" +#include "warnings.h" #include #include #include @@ -39,21 +40,25 @@ DCPOMATIC_ENABLE_WARNINGS #include #include -using std::list; + +using std::cerr; using std::cout; -using std::string; -using std::min; +using std::list; +using std::make_pair; +using std::make_shared; using std::max; +using std::min; using std::pair; -using std::cerr; -using std::make_pair; using std::shared_ptr; +using std::string; using boost::optional; using boost::algorithm::replace_all; using namespace dcpomatic; -static FcConfig* fc_config = 0; -static list > fc_config_fonts; + +static FcConfig* fc_config = nullptr; +static list> fc_config_fonts; + string marked_up (list subtitles, int target_height, float fade_factor) @@ -86,6 +91,7 @@ marked_up (list subtitles, int target_height, float fade_factor) return out; } + static void set_source_rgba (Cairo::RefPtr context, dcp::Colour colour, float fade_factor) { @@ -97,7 +103,7 @@ static shared_ptr create_image (dcp::Size size) { /* FFmpeg BGRA means first byte blue, second byte green, third byte red, fourth byte alpha */ - shared_ptr image (new Image(AV_PIX_FMT_BGRA, size, false)); + auto image = make_shared(AV_PIX_FMT_BGRA, size, false); image->make_black (); return image; } @@ -107,7 +113,7 @@ static Cairo::RefPtr create_surface (shared_ptr image) { #ifdef DCPOMATIC_HAVE_FORMAT_STRIDE_FOR_WIDTH - Cairo::RefPtr surface = Cairo::ImageSurface::create ( + auto surface = Cairo::ImageSurface::create ( image->data()[0], Cairo::FORMAT_ARGB32, image->size().width, @@ -119,7 +125,7 @@ create_surface (shared_ptr image) /* Centos 5 does not have Cairo::ImageSurface::format_stride_for_width, so just use width * 4 which I hope is safe (if slow) */ - Cairo::RefPtr surface = Cairo::ImageSurface::create ( + auto surface = Cairo::ImageSurface::create ( image->data()[0], Cairo::FORMAT_ARGB32, image->size().width, @@ -133,22 +139,22 @@ create_surface (shared_ptr image) static string -setup_font (StringText const& subtitle, list > const& fonts) +setup_font (StringText const& subtitle, list> const& fonts) { if (!fc_config) { fc_config = FcInitLoadConfig (); } - optional font_file = default_font_file (); + auto font_file = default_font_file (); for (auto i: fonts) { if (i->id() == subtitle.font() && i->file()) { - font_file = i->file (); + font_file = i->file().get(); } } - list >::const_iterator existing = fc_config_fonts.begin (); - while (existing != fc_config_fonts.end() && existing->first != *font_file) { + auto existing = fc_config_fonts.cbegin (); + while (existing != fc_config_fonts.end() && existing->first != font_file) { ++existing; } @@ -157,12 +163,12 @@ setup_font (StringText const& subtitle, list > const& fonts) font_name = existing->second; } else { /* Make this font available to DCP-o-matic */ - FcConfigAppFontAddFile (fc_config, reinterpret_cast(font_file->string().c_str())); - FcPattern* pattern = FcPatternBuild ( - 0, FC_FILE, FcTypeString, font_file->string().c_str(), static_cast (0) + FcConfigAppFontAddFile (fc_config, reinterpret_cast(font_file.string().c_str())); + auto pattern = FcPatternBuild ( + 0, FC_FILE, FcTypeString, font_file.string().c_str(), static_cast(0) ); - FcObjectSet* object_set = FcObjectSetBuild (FC_FAMILY, FC_STYLE, FC_LANG, FC_FILE, static_cast (0)); - FcFontSet* font_set = FcFontList (fc_config, pattern, object_set); + auto object_set = FcObjectSetBuild (FC_FAMILY, FC_STYLE, FC_LANG, FC_FILE, static_cast (0)); + auto font_set = FcFontList (fc_config, pattern, object_set); if (font_set) { for (int i = 0; i < font_set->nfont; ++i) { FcPattern* font = font_set->fonts[i]; @@ -184,7 +190,7 @@ setup_font (StringText const& subtitle, list > const& fonts) FcObjectSetDestroy (object_set); FcPatternDestroy (pattern); - fc_config_fonts.push_back (make_pair(*font_file, font_name)); + fc_config_fonts.push_back (make_pair(font_file, font_name)); } FcConfigSetCurrent (fc_config); @@ -200,10 +206,10 @@ calculate_fade_factor (StringText const& first, DCPTime time, int frame_rate) /* Round the fade start/end to the nearest frame start. Otherwise if a subtitle starts just after the start of a frame it will be faded out. */ - DCPTime const fade_in_start = DCPTime::from_seconds(first.in().as_seconds()).round(frame_rate); - DCPTime const fade_in_end = fade_in_start + DCPTime::from_seconds (first.fade_up_time().as_seconds ()); - DCPTime const fade_out_end = DCPTime::from_seconds (first.out().as_seconds()).round(frame_rate); - DCPTime const fade_out_start = fade_out_end - DCPTime::from_seconds (first.fade_down_time().as_seconds ()); + auto const fade_in_start = DCPTime::from_seconds(first.in().as_seconds()).round(frame_rate); + auto const fade_in_end = fade_in_start + DCPTime::from_seconds (first.fade_up_time().as_seconds ()); + auto const fade_out_end = DCPTime::from_seconds (first.out().as_seconds()).round(frame_rate); + auto const fade_out_start = fade_out_end - DCPTime::from_seconds (first.fade_down_time().as_seconds ()); if (fade_in_start <= time && time <= fade_in_end && fade_in_start != fade_in_end) { fade_factor *= DCPTime(time - fade_in_start).seconds() / DCPTime(fade_in_end - fade_in_start).seconds(); @@ -223,7 +229,7 @@ static int x_position (StringText const& first, int target_width, int layout_width) { int x = 0; - switch (first.h_align ()) { + switch (first.h_align()) { case dcp::HAlign::LEFT: /* h_position is distance between left of frame and left of subtitle */ x = first.h_position() * target_width; @@ -242,12 +248,11 @@ x_position (StringText const& first, int target_width, int layout_width) } - static int y_position (StringText const& first, int target_height, int layout_height) { int y = 0; - switch (first.v_align ()) { + switch (first.v_align()) { case dcp::VAlign::TOP: /* SMPTE says that v_position is the distance between top of frame and top of subtitle, but this doesn't always seem to be @@ -280,6 +285,7 @@ setup_layout (Glib::RefPtr layout, string font_name, string marku layout->set_markup (markup); } + /** Create a Pango layout using a dummy context which we can use to calculate the size * of the text we will render. Then we can transfer the layout over to the real context * for the actual render. @@ -287,12 +293,12 @@ setup_layout (Glib::RefPtr layout, string font_name, string marku static Glib::RefPtr create_layout() { - PangoFontMap* c_font_map = pango_cairo_font_map_new (); + auto c_font_map = pango_cairo_font_map_new (); DCPOMATIC_ASSERT (c_font_map); - Glib::RefPtr font_map = Glib::wrap (c_font_map); - PangoContext* c_context = pango_font_map_create_context (c_font_map); + auto font_map = Glib::wrap (c_font_map); + auto c_context = pango_font_map_create_context (c_font_map); DCPOMATIC_ASSERT (c_context); - Glib::RefPtr context = Glib::wrap (c_context); + auto context = Glib::wrap (c_context); return Pango::Layout::create (context); } @@ -301,19 +307,19 @@ create_layout() * at the same time and with the same fade in/out. */ static PositionImage -render_line (list subtitles, list > fonts, dcp::Size target, DCPTime time, int frame_rate) +render_line (list subtitles, list> fonts, dcp::Size target, DCPTime time, int frame_rate) { /* XXX: this method can only handle italic / bold changes mid-line, nothing else yet. */ DCPOMATIC_ASSERT (!subtitles.empty ()); - StringText const& first = subtitles.front (); + auto const& first = subtitles.front (); - string const font_name = setup_font (first, fonts); - float const fade_factor = calculate_fade_factor (first, time, frame_rate); - string const markup = marked_up (subtitles, target.height, fade_factor); - Glib::RefPtr layout = create_layout (); + auto const font_name = setup_font (first, fonts); + auto const fade_factor = calculate_fade_factor (first, time, frame_rate); + auto const markup = marked_up (subtitles, target.height, fade_factor); + auto layout = create_layout (); setup_layout (layout, font_name, markup); dcp::Size size; layout->get_pixel_size (size.width, size.height); @@ -333,7 +339,7 @@ render_line (list subtitles, list > fonts, dcp::Siz } } - float const border_width = first.effect() == dcp::Effect::BORDER ? (first.outline_width * target.width / 2048.0) : 0; + auto const border_width = first.effect() == dcp::Effect::BORDER ? (first.outline_width * target.width / 2048.0) : 0; size.width += 2 * ceil (border_width); size.height += 2 * ceil (border_width); @@ -348,9 +354,9 @@ render_line (list subtitles, list > fonts, dcp::Siz size.width += x_offset; size.height += y_offset; - shared_ptr image = create_image (size); - Cairo::RefPtr surface = create_surface (image); - Cairo::RefPtr context = Cairo::Context::create (surface); + auto image = create_image (size); + auto surface = create_surface (image); + auto context = Cairo::Context::create (surface); context->set_line_width (1); context->scale (x_scale, y_scale); @@ -398,7 +404,7 @@ render_line (list subtitles, list > fonts, dcp::Siz * @param frame_rate DCP frame rate. */ list -render_text (list subtitles, list > fonts, dcp::Size target, DCPTime time, int frame_rate) +render_text (list subtitles, list> fonts, dcp::Size target, DCPTime time, int frame_rate) { list pending; list images; @@ -411,7 +417,7 @@ render_text (list subtitles, list > fonts, dcp::Siz pending.push_back (i); } - if (!pending.empty ()) { + if (!pending.empty()) { images.push_back (render_line (pending, fonts, target, time, frame_rate)); } diff --git a/src/lib/send_kdm_email_job.cc b/src/lib/send_kdm_email_job.cc index 8ed08f2a3..67ddd0eef 100644 --- a/src/lib/send_kdm_email_job.cc +++ b/src/lib/send_kdm_email_job.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2020 Carl Hetherington + Copyright (C) 2013-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,6 +18,7 @@ */ + #include "send_kdm_email_job.h" #include "compose.hpp" #include "kdm_with_metadata.h" @@ -26,11 +27,13 @@ #include "i18n.h" + using std::string; using std::list; using std::shared_ptr; using boost::optional; + SendKDMEmailJob::SendKDMEmailJob ( list kdms, dcp::NameFormat container_name_format, @@ -49,6 +52,7 @@ SendKDMEmailJob::SendKDMEmailJob ( } } + /** @param kdms KDMs to email. * @param container_name_format Format to ues for folders / ZIP files. * @param filename_format Format to use for filenames. @@ -70,15 +74,17 @@ SendKDMEmailJob::SendKDMEmailJob ( } + SendKDMEmailJob::~SendKDMEmailJob () { stop_thread (); } + string SendKDMEmailJob::name () const { - optional f = _kdms.front().front()->get('f'); + auto f = _kdms.front().front()->get('f'); if (!f || f->empty()) { return _("Email KDMs"); } @@ -86,12 +92,14 @@ SendKDMEmailJob::name () const return String::compose (_("Email KDMs for %2"), *f); } + string SendKDMEmailJob::json_name () const { return N_("send_kdm_email"); } + void SendKDMEmailJob::run () { diff --git a/src/lib/send_kdm_email_job.h b/src/lib/send_kdm_email_job.h index fa409edaa..2b010665c 100644 --- a/src/lib/send_kdm_email_job.h +++ b/src/lib/send_kdm_email_job.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2019 Carl Hetherington + Copyright (C) 2013-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,18 +18,22 @@ */ + #include "job.h" #include "kdm_with_metadata.h" #include #include #include + namespace dcpomatic { class Screen; } + class Log; + class SendKDMEmailJob : public Job { public: @@ -41,7 +45,7 @@ public: ); SendKDMEmailJob ( - std::list > kdms, + std::list> kdms, dcp::NameFormat container_name_format, dcp::NameFormat filename_format, std::string cpl_name @@ -57,5 +61,5 @@ private: dcp::NameFormat _container_name_format; dcp::NameFormat _filename_format; std::string _cpl_name; - std::list > _kdms; + std::list> _kdms; }; diff --git a/src/lib/subtitle_analysis.cc b/src/lib/subtitle_analysis.cc index 49041151f..0838816b0 100644 --- a/src/lib/subtitle_analysis.cc +++ b/src/lib/subtitle_analysis.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Carl Hetherington + Copyright (C) 2020-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,6 +18,7 @@ */ + #include "subtitle_analysis.h" #include "exceptions.h" #include "warnings.h" @@ -27,9 +28,12 @@ DCPOMATIC_DISABLE_WARNINGS #include DCPOMATIC_ENABLE_WARNINGS + +using std::make_shared; +using std::shared_ptr; using std::string; using dcp::raw_convert; -using std::shared_ptr; + int const SubtitleAnalysis::_current_state_version = 1; @@ -62,13 +66,13 @@ SubtitleAnalysis::SubtitleAnalysis (boost::filesystem::path path) void SubtitleAnalysis::write (boost::filesystem::path path) const { - shared_ptr doc (new xmlpp::Document); + auto doc = make_shared(); xmlpp::Element* root = doc->create_root_node ("SubtitleAnalysis"); root->add_child("Version")->add_child_text (raw_convert(_current_state_version)); if (_bounding_box) { - xmlpp::Element* bounding_box = root->add_child("BoundingBox"); + auto bounding_box = root->add_child("BoundingBox"); bounding_box->add_child("X")->add_child_text(raw_convert(_bounding_box->x)); bounding_box->add_child("Y")->add_child_text(raw_convert(_bounding_box->y)); bounding_box->add_child("Width")->add_child_text(raw_convert(_bounding_box->width)); @@ -81,4 +85,3 @@ SubtitleAnalysis::write (boost::filesystem::path path) const doc->write_to_file_formatted (path.string()); } - diff --git a/src/lib/subtitle_analysis.h b/src/lib/subtitle_analysis.h index 6a7049a29..0a9dc6dca 100644 --- a/src/lib/subtitle_analysis.h +++ b/src/lib/subtitle_analysis.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Carl Hetherington + Copyright (C) 2020-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,6 +18,7 @@ */ + #include "rect.h" #include #include @@ -26,14 +27,13 @@ /** @class SubtitleAnalysis * @brief Class to store the results of a SubtitleAnalysisJob. */ - class SubtitleAnalysis : public boost::noncopyable { public: explicit SubtitleAnalysis (boost::filesystem::path path); SubtitleAnalysis ( - boost::optional > bounding_box, + boost::optional> bounding_box, double analysis_x_offset_, double analysis_y_offset_ ) @@ -44,7 +44,7 @@ public: void write (boost::filesystem::path path) const; - boost::optional > bounding_box () const { + boost::optional> bounding_box () const { return _bounding_box; } @@ -61,7 +61,7 @@ private: * expressed as a proportion of screen size (i.e. 0 is left hand side/top, * 1 is right hand side/bottom), or empty if no subtitles were found. */ - boost::optional > _bounding_box; + boost::optional> _bounding_box; double _analysis_x_offset; double _analysis_y_offset; diff --git a/src/lib/timer.cc b/src/lib/timer.cc index 84329a5d5..caef89e0e 100644 --- a/src/lib/timer.cc +++ b/src/lib/timer.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2019 Carl Hetherington + Copyright (C) 2012-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,21 +18,29 @@ */ + /** @file src/timer.cc * @brief Some timing classes for debugging and profiling. */ + +#include "compose.hpp" #include "timer.h" #include "util.h" -#include "compose.hpp" -#include #include +#include #include "i18n.h" -using namespace std; + +using std::cout; +using std::list; +using std::max; +using std::pair; +using std::string; using boost::optional; + /** @param n Name to use when giving output */ PeriodTimer::PeriodTimer (string n) : _name (n) @@ -40,6 +48,7 @@ PeriodTimer::PeriodTimer (string n) gettimeofday (&_start, 0); } + /** Destroy PeriodTimer and output the time elapsed since its construction */ PeriodTimer::~PeriodTimer () { @@ -48,6 +57,7 @@ PeriodTimer::~PeriodTimer () cout << N_("T: ") << _name << N_(": ") << (seconds (stop) - seconds (_start)) << N_("\n"); } + StateTimer::StateTimer (string n, string s) : _name (n) { @@ -57,18 +67,21 @@ StateTimer::StateTimer (string n, string s) _state = s; } + StateTimer::StateTimer (string n) : _name (n) { } + void StateTimer::set (string s) { set_internal (s); } + void StateTimer::set_internal (optional s) { @@ -88,16 +101,13 @@ StateTimer::set_internal (optional s) _state = s; } + void StateTimer::unset () { set_internal (optional()); } -bool compare (pair a, pair b) -{ - return a.first > b.first; -} /** Destroy StateTimer and generate a summary of the state timings on cout */ StateTimer::~StateTimer () @@ -113,7 +123,7 @@ StateTimer::~StateTimer () longest = max (longest, int(i.first.length())); } - list > sorted; + list> sorted; for (auto const& i: _counts) { string name = i.first + string(longest + 1 - i.first.size(), ' '); @@ -123,7 +133,10 @@ StateTimer::~StateTimer () sorted.push_back (make_pair(i.second.total_time, String::compose("\t%1%2 %3 %4", name, total_time, i.second.number, (i.second.total_time / i.second.number)))); } - sorted.sort (compare); + sorted.sort ([](pair const& a, pair const& b) { + return a.first > b.first; + }); + cout << _name << N_(":\n"); for (auto const& i: sorted) { diff --git a/src/lib/timer.h b/src/lib/timer.h index e18b799d9..6435155c6 100644 --- a/src/lib/timer.h +++ b/src/lib/timer.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2019 Carl Hetherington + Copyright (C) 2012-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,18 +18,22 @@ */ + /** @file src/timer.h * @brief Some timing classes for debugging and profiling. */ + #ifndef DCPOMATIC_TIMER_H #define DCPOMATIC_TIMER_H + #include #include #include #include + /** @class PeriodTimer * @brief A class to allow timing of a period within the caller. * diff --git a/src/lib/video_content.h b/src/lib/video_content.h index 4e9e5815f..c1e1dbeec 100644 --- a/src/lib/video_content.h +++ b/src/lib/video_content.h @@ -61,7 +61,7 @@ class VideoContent : public ContentPart, public std::enable_shared_from_this >); + VideoContent (Content* parent, std::vector>); void as_xml (xmlpp::Node *) const; std::string technical_summary () const; @@ -249,4 +249,5 @@ private: boost::optional _burnt_subtitle_language; }; + #endif diff --git a/src/lib/zipper.cc b/src/lib/zipper.cc index 005e15248..2c334dc94 100644 --- a/src/lib/zipper.cc +++ b/src/lib/zipper.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Carl Hetherington + Copyright (C) 2020-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,6 +18,7 @@ */ + #include "zipper.h" #include "exceptions.h" #include "dcpomatic_assert.h" @@ -25,6 +26,7 @@ #include #include + using std::string; using std::runtime_error; using std::shared_ptr; @@ -49,7 +51,7 @@ Zipper::add (string name, string content) shared_ptr copy(new string(content)); _store.push_back (copy); - struct zip_source* source = zip_source_buffer (_zip, copy->c_str(), copy->length(), 0); + auto source = zip_source_buffer (_zip, copy->c_str(), copy->length(), 0); if (!source) { throw runtime_error ("could not create ZIP source"); } diff --git a/src/lib/zipper.h b/src/lib/zipper.h index c2b40556c..62a6af5b9 100644 --- a/src/lib/zipper.h +++ b/src/lib/zipper.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Carl Hetherington + Copyright (C) 2020-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,10 +18,12 @@ */ + #include #include #include + class Zipper : public boost::noncopyable { public: @@ -33,6 +35,6 @@ public: private: struct zip* _zip; - std::vector > _store; + std::vector> _store; }; diff --git a/src/tools/dcpomatic_player.cc b/src/tools/dcpomatic_player.cc index 77e48ce0c..506ba052e 100644 --- a/src/tools/dcpomatic_player.cc +++ b/src/tools/dcpomatic_player.cc @@ -56,6 +56,7 @@ #include "lib/ffmpeg_content.h" #include "lib/dcpomatic_log.h" #include "lib/file_log.h" +#include #include #include #include diff --git a/src/tools/dcpomatic_playlist.cc b/src/tools/dcpomatic_playlist.cc index 1dca8c182..6f06c0624 100644 --- a/src/tools/dcpomatic_playlist.cc +++ b/src/tools/dcpomatic_playlist.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2018-2020 Carl Hetherington + Copyright (C) 2018-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,40 +18,44 @@ */ -#include "../wx/wx_util.h" -#include "../wx/wx_signal_manager.h" -#include "../wx/content_view.h" -#include "../wx/dcpomatic_button.h" -#include "../wx/about_dialog.h" -#include "../wx/playlist_editor_config_dialog.h" -#include "../lib/util.h" -#include "../lib/config.h" -#include "../lib/cross.h" -#include "../lib/film.h" -#include "../lib/dcp_content.h" -#include "../lib/spl_entry.h" -#include "../lib/spl.h" + +#include "wx/wx_util.h" +#include "wx/wx_signal_manager.h" +#include "wx/content_view.h" +#include "wx/dcpomatic_button.h" +#include "wx/about_dialog.h" +#include "wx/playlist_editor_config_dialog.h" +#include "lib/config.h" +#include "lib/cross.h" +#include "lib/dcp_content.h" +#include "lib/film.h" +#include "lib/spl.h" +#include "lib/spl_entry.h" +#include "lib/util.h" #include #include #include #include #include -using std::exception; + using std::cout; -using std::string; -using std::map; +using std::exception; using std::make_pair; -using std::vector; -using boost::optional; +using std::make_shared; +using std::map; using std::shared_ptr; +using std::string; +using std::vector; using std::weak_ptr; using boost::bind; +using boost::optional; using std::dynamic_pointer_cast; #if BOOST_VERSION >= 106100 using namespace boost::placeholders; #endif + class ContentDialog : public wxDialog, public ContentStore { public: @@ -61,12 +65,12 @@ public: { _content_view->update (); - wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL); + auto overall_sizer = new wxBoxSizer (wxVERTICAL); SetSizer (overall_sizer); overall_sizer->Add (_content_view, 1, wxEXPAND | wxALL, DCPOMATIC_DIALOG_BORDER); - wxSizer* buttons = CreateSeparatedButtonSizer (wxOK | wxCANCEL); + auto buttons = CreateSeparatedButtonSizer (wxOK | wxCANCEL); if (buttons) { overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder()); } @@ -100,7 +104,7 @@ public: : _sizer (new wxBoxSizer(wxVERTICAL)) , _content_store (content_store) { - wxStaticText* label = new wxStaticText (parent, wxID_ANY, wxEmptyString); + auto label = new wxStaticText (parent, wxID_ANY, wxEmptyString); label->SetLabelMarkup (_("Playlists")); _sizer->Add (label, 0, wxTOP | wxLEFT, DCPOMATIC_SIZER_GAP * 2); @@ -111,13 +115,13 @@ public: _list->AppendColumn (_("Name"), wxLIST_FORMAT_LEFT, 840); _list->AppendColumn (_("Length"), wxLIST_FORMAT_LEFT, 100); - wxBoxSizer* button_sizer = new wxBoxSizer (wxVERTICAL); + auto button_sizer = new wxBoxSizer (wxVERTICAL); _new = new Button (parent, _("New")); button_sizer->Add (_new, 0, wxEXPAND | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP); _delete = new Button (parent, _("Delete")); button_sizer->Add (_delete, 0, wxEXPAND | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP); - wxSizer* list = new wxBoxSizer (wxHORIZONTAL); + auto list = new wxBoxSizer (wxHORIZONTAL); list->Add (_list, 1, wxEXPAND | wxALL, DCPOMATIC_SIZER_GAP); list->Add (button_sizer, 0, wxALL, DCPOMATIC_SIZER_GAP); @@ -139,7 +143,7 @@ public: shared_ptr first_playlist () const { if (_playlists.empty()) { - return shared_ptr(); + return {}; } return _playlists.front (); @@ -164,7 +168,7 @@ private: void name_changed (weak_ptr wp) { - shared_ptr playlist = wp.lock (); + auto playlist = wp.lock (); if (!playlist) { return; } @@ -180,17 +184,17 @@ private: void load_playlists () { - optional path = Config::instance()->player_playlist_directory(); + auto path = Config::instance()->player_playlist_directory(); if (!path) { return; } _list->DeleteAllItems (); _playlists.clear (); - for (boost::filesystem::directory_iterator i(*path); i != boost::filesystem::directory_iterator(); ++i) { - shared_ptr spl(new SignalSPL); + for (auto i: boost::filesystem::directory_iterator(*path)) { + auto spl = make_shared(); try { - spl->read (*i, _content_store); + spl->read (i, _content_store); add_playlist_to_model (spl); } catch (...) {} } @@ -215,7 +219,7 @@ private: return; } - optional dir = Config::instance()->player_playlist_directory(); + auto dir = Config::instance()->player_playlist_directory(); if (!dir) { return; } @@ -241,7 +245,7 @@ private: wxListCtrl* _list; wxButton* _new; wxButton* _delete; - vector > _playlists; + vector> _playlists; ContentStore* _content_store; }; @@ -253,15 +257,15 @@ public: : _content_dialog (content_dialog) , _sizer (new wxBoxSizer(wxVERTICAL)) { - wxBoxSizer* title = new wxBoxSizer (wxHORIZONTAL); - wxStaticText* label = new wxStaticText (parent, wxID_ANY, wxEmptyString); + auto title = new wxBoxSizer (wxHORIZONTAL); + auto label = new wxStaticText (parent, wxID_ANY, wxEmptyString); label->SetLabelMarkup (_("Playlist:")); title->Add (label, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, DCPOMATIC_SIZER_GAP); _name = new wxTextCtrl (parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(400, -1)); title->Add (_name, 0, wxRIGHT, DCPOMATIC_SIZER_GAP); _sizer->Add (title, 0, wxTOP | wxLEFT, DCPOMATIC_SIZER_GAP * 2); - wxBoxSizer* list = new wxBoxSizer (wxHORIZONTAL); + auto list = new wxBoxSizer (wxHORIZONTAL); _list = new wxListCtrl ( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_SINGLE_SEL @@ -272,7 +276,7 @@ public: _list->AppendColumn (_("Type"), wxLIST_FORMAT_LEFT, 100); _list->AppendColumn (_("Encrypted"), wxLIST_FORMAT_CENTRE, 90); - wxImageList* images = new wxImageList (16, 16); + auto images = new wxImageList (16, 16); wxIcon tick_icon; wxIcon no_tick_icon; tick_icon.LoadFile (bitmap_path("tick"), wxBITMAP_TYPE_PNG); @@ -284,7 +288,7 @@ public: list->Add (_list, 1, wxEXPAND | wxALL, DCPOMATIC_SIZER_GAP); - wxBoxSizer* button_sizer = new wxBoxSizer (wxVERTICAL); + auto button_sizer = new wxBoxSizer (wxVERTICAL); _up = new Button (parent, _("Up")); _down = new Button (parent, _("Down")); _add = new Button (parent, _("Add")); @@ -374,7 +378,7 @@ private: { int const r = _content_dialog->ShowModal (); if (r == wxID_OK) { - shared_ptr content = _content_dialog->selected (); + auto content = _content_dialog->selected (); if (content) { SPLEntry e (content); add (e); @@ -393,7 +397,7 @@ private: DCPOMATIC_ASSERT (_playlist); - SPLEntry tmp = (*_playlist)[s]; + auto tmp = (*_playlist)[s]; (*_playlist)[s] = (*_playlist)[s-1]; (*_playlist)[s-1] = tmp; @@ -410,7 +414,7 @@ private: DCPOMATIC_ASSERT (_playlist); - SPLEntry tmp = (*_playlist)[s]; + auto tmp = (*_playlist)[s]; (*_playlist)[s] = (*_playlist)[s+1]; (*_playlist)[s+1] = tmp; @@ -446,19 +450,19 @@ class DOMFrame : public wxFrame { public: explicit DOMFrame (wxString const & title) - : wxFrame (0, -1, title) + : wxFrame (nullptr, wxID_ANY, title) , _content_dialog (new ContentDialog(this)) - , _config_dialog (0) + , _config_dialog (nullptr) { - wxMenuBar* bar = new wxMenuBar; + auto bar = new wxMenuBar; setup_menu (bar); SetMenuBar (bar); /* Use a panel as the only child of the Frame so that we avoid the dark-grey background on Windows. */ - wxPanel* overall_panel = new wxPanel (this, wxID_ANY); - wxBoxSizer* sizer = new wxBoxSizer (wxVERTICAL); + auto overall_panel = new wxPanel (this, wxID_ANY); + auto sizer = new wxBoxSizer (wxVERTICAL); _playlist_list = new PlaylistList (overall_panel, _content_dialog); _playlist_content = new PlaylistContent (overall_panel, _content_dialog); @@ -489,7 +493,7 @@ private: void help_about () { - AboutDialog* d = new AboutDialog (this); + auto d = new AboutDialog (this); d->ShowModal (); d->Destroy (); } @@ -504,7 +508,7 @@ private: void change_playlist (shared_ptr playlist) { - shared_ptr old = _playlist_content->playlist (); + auto old = _playlist_content->playlist (); if (old) { save_playlist (old); } @@ -513,7 +517,7 @@ private: void save_playlist (shared_ptr playlist) { - optional dir = Config::instance()->player_playlist_directory(); + auto dir = Config::instance()->player_playlist_directory(); if (!dir) { error_dialog (this, _("No playlist folder is specified in preferences. Please set one and then try again.")); return; @@ -523,7 +527,7 @@ private: void setup_menu (wxMenuBar* m) { - wxMenu* file = new wxMenu; + auto file = new wxMenu; #ifdef __WXOSX__ file->Append (wxID_EXIT, _("&Exit")); #else @@ -531,11 +535,11 @@ private: #endif #ifndef __WXOSX__ - wxMenu* edit = new wxMenu; + auto edit = new wxMenu; edit->Append (wxID_PREFERENCES, _("&Preferences...\tCtrl-P")); #endif - wxMenu* help = new wxMenu; + auto help = new wxMenu; #ifdef __WXOSX__ help->Append (wxID_ABOUT, _("About DCP-o-matic")); #else @@ -565,7 +569,6 @@ private: } } - ContentDialog* _content_dialog; PlaylistList* _playlist_list; PlaylistContent* _playlist_content; @@ -573,6 +576,7 @@ private: boost::signals2::scoped_connection _config_changed_connection; }; + /** @class App * @brief The magic App class for wxWidgets. */ @@ -581,7 +585,7 @@ class App : public wxApp public: App () : wxApp () - , _frame (0) + , _frame (nullptr) {} private: diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index cc18d634d..8805d1311 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -59,17 +59,19 @@ extern "C" { #include #include -using std::string; -using std::pair; -using std::min; -using std::max; + +using std::bad_alloc; using std::cout; +using std::dynamic_pointer_cast; +using std::exception; using std::list; -using std::bad_alloc; using std::make_pair; -using std::exception; +using std::make_shared; +using std::max; +using std::min; +using std::pair; using std::shared_ptr; -using std::dynamic_pointer_cast; +using std::string; using std::vector; using std::weak_ptr; using boost::optional; @@ -79,6 +81,7 @@ using namespace boost::placeholders; using dcp::Size; using namespace dcpomatic; + static int rtaudio_callback (void* out, void *, unsigned int frames, double, RtAudioStreamStatus, void* data) @@ -86,18 +89,10 @@ rtaudio_callback (void* out, void *, unsigned int frames, double, RtAudioStreamS return reinterpret_cast(data)->audio_callback (out, frames); } + FilmViewer::FilmViewer (wxWindow* p) - : _coalesce_player_changes (false) - , _audio (DCPOMATIC_RTAUDIO_API) - , _audio_channels (0) - , _audio_block_size (1024) - , _playing (false) - , _suspended (0) - , _latency_history_count (0) + : _audio (DCPOMATIC_RTAUDIO_API) , _closed_captions_dialog (new ClosedCaptionsDialog(p, this)) - , _outline_content (false) - , _pad_black (false) - , _idle_get (false) { switch (Config::instance()->video_view_type()) { case Config::VIDEO_VIEW_OPENGL: @@ -111,17 +106,19 @@ FilmViewer::FilmViewer (wxWindow* p) _video_view->Sized.connect (boost::bind(&FilmViewer::video_view_sized, this)); _video_view->TooManyDropped.connect (boost::bind(&FilmViewer::too_many_frames_dropped, this)); - set_film (shared_ptr ()); + set_film (shared_ptr()); - _config_changed_connection = Config::instance()->Changed.connect (bind (&FilmViewer::config_changed, this, _1)); + _config_changed_connection = Config::instance()->Changed.connect(bind(&FilmViewer::config_changed, this, _1)); config_changed (Config::SOUND_OUTPUT); } + FilmViewer::~FilmViewer () { stop (); } + /** Ask for ::get() to be called next time we are idle */ void FilmViewer::request_idle_display_next_frame () @@ -135,6 +132,7 @@ FilmViewer::request_idle_display_next_frame () signal_manager->when_idle (boost::bind(&FilmViewer::idle_handler, this)); } + void FilmViewer::idle_handler () { @@ -150,6 +148,7 @@ FilmViewer::idle_handler () } } + void FilmViewer::set_film (shared_ptr film) { @@ -170,7 +169,7 @@ FilmViewer::set_film (shared_ptr film) } try { - _player.reset (new Player(_film)); + _player = make_shared(_film); _player->set_fast (); if (_dcp_decode_reduction) { _player->set_dcp_decode_reduction (_dcp_decode_reduction); @@ -203,6 +202,7 @@ FilmViewer::set_film (shared_ptr film) slow_refresh (); } + void FilmViewer::recreate_butler () { @@ -214,17 +214,15 @@ FilmViewer::recreate_butler () return; } - _butler.reset( - new Butler( - _film, - _player, - Config::instance()->audio_mapping(_audio_channels), - _audio_channels, - bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), - VideoRange::FULL, - false, - true - ) + _butler = std::make_shared( + _film, + _player, + Config::instance()->audio_mapping(_audio_channels), + _audio_channels, + bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), + VideoRange::FULL, + false, + true ); if (!Config::instance()->sound() && !_audio.isStreamOpen()) { @@ -236,6 +234,7 @@ FilmViewer::recreate_butler () resume (); } + void FilmViewer::set_outline_content (bool o) { @@ -245,7 +244,7 @@ FilmViewer::set_outline_content (bool o) void -FilmViewer::set_outline_subtitles (optional > rect) +FilmViewer::set_outline_subtitles (optional> rect) { _outline_subtitles = rect; _video_view->update (); @@ -259,6 +258,7 @@ FilmViewer::set_eyes (Eyes e) slow_refresh (); } + void FilmViewer::video_view_sized () { @@ -268,6 +268,7 @@ FilmViewer::video_view_sized () } } + void FilmViewer::calculate_sizes () { @@ -275,10 +276,10 @@ FilmViewer::calculate_sizes () return; } - Ratio const * container = _film->container (); + auto const container = _film->container (); - float const view_ratio = float(_video_view->get()->GetSize().x) / _video_view->get()->GetSize().y; - float const film_ratio = container ? container->ratio () : 1.78; + auto const view_ratio = float(_video_view->get()->GetSize().x) / _video_view->get()->GetSize().y; + auto const film_ratio = container ? container->ratio () : 1.78; if (view_ratio < film_ratio) { /* panel is less widscreen than the film; clamp width */ @@ -297,6 +298,7 @@ FilmViewer::calculate_sizes () _player->set_video_container_size (_out_size); } + void FilmViewer::suspend () { @@ -306,6 +308,7 @@ FilmViewer::suspend () } } + void FilmViewer::resume () { @@ -320,6 +323,7 @@ FilmViewer::resume () } } + void FilmViewer::start () { @@ -327,7 +331,7 @@ FilmViewer::start () return; } - optional v = PlaybackPermitted (); + auto v = PlaybackPermitted (); if (v && !*v) { /* Computer says no */ return; @@ -357,6 +361,7 @@ FilmViewer::start () _video_view->start (); } + bool FilmViewer::stop () { @@ -377,6 +382,7 @@ FilmViewer::stop () return true; } + void FilmViewer::player_change (ChangeType type, int property, bool frequent) { @@ -392,6 +398,7 @@ FilmViewer::player_change (ChangeType type, int property, bool frequent) player_change ({property}); } + void FilmViewer::player_change (vector properties) { @@ -427,6 +434,7 @@ FilmViewer::player_change (vector properties) } } + void FilmViewer::film_change (ChangeType type, Film::Property p) { @@ -445,12 +453,14 @@ FilmViewer::film_change (ChangeType type, Film::Property p) } } + void FilmViewer::film_length_change () { _video_view->set_length (_film->length()); } + /** Re-get the current frame slowly by seeking */ void FilmViewer::slow_refresh () @@ -458,6 +468,7 @@ FilmViewer::slow_refresh () seek (_video_view->position(), true); } + /** Try to re-get the current frame quickly by resetting the metadata * in the PlayerVideo that we used last time. * @return true if this was possible, false if not. @@ -471,15 +482,17 @@ FilmViewer::quick_refresh () return _video_view->reset_metadata (_film, _player->video_container_size()); } + void FilmViewer::seek (shared_ptr content, ContentTime t, bool accurate) { - optional dt = _player->content_time_to_dcp (content, t); + auto dt = _player->content_time_to_dcp (content, t); if (dt) { seek (*dt, accurate); } } + void FilmViewer::set_coalesce_player_changes (bool c) { @@ -491,6 +504,7 @@ FilmViewer::set_coalesce_player_changes (bool c) } } + void FilmViewer::seek (DCPTime t, bool accurate) { @@ -498,11 +512,11 @@ FilmViewer::seek (DCPTime t, bool accurate) return; } - if (t < DCPTime ()) { + if (t < DCPTime()) { t = DCPTime (); } - if (t >= _film->length ()) { + if (t >= _film->length()) { t = _film->length() - one_video_frame(); } @@ -526,6 +540,7 @@ FilmViewer::seek (DCPTime t, bool accurate) resume (); } + void FilmViewer::config_changed (Config::Property p) { @@ -584,38 +599,42 @@ FilmViewer::config_changed (Config::Property p) } } + DCPTime FilmViewer::uncorrected_time () const { - if (_audio.isStreamRunning ()) { + if (_audio.isStreamRunning()) { return DCPTime::from_seconds (const_cast(&_audio)->getStreamTime()); } return _video_view->position(); } + optional FilmViewer::audio_time () const { if (!_audio.isStreamRunning()) { - return optional(); + return {}; } return DCPTime::from_seconds (const_cast(&_audio)->getStreamTime ()) - DCPTime::from_frames (average_latency(), _film->audio_frame_rate()); } + DCPTime FilmViewer::time () const { return audio_time().get_value_or(_video_view->position()); } + int FilmViewer::audio_callback (void* out_p, unsigned int frames) { while (true) { - optional t = _butler->get_audio (reinterpret_cast (out_p), frames); + auto t = _butler->get_audio (reinterpret_cast (out_p), frames); if (!t || DCPTime(uncorrected_time() - *t) < one_video_frame()) { /* There was an underrun or this audio is on time; carry on */ break; @@ -634,6 +653,7 @@ FilmViewer::audio_callback (void* out_p, unsigned int frames) return 0; } + Frame FilmViewer::average_latency () const { @@ -650,6 +670,7 @@ FilmViewer::average_latency () const return total / _latency_history.size(); } + void FilmViewer::set_dcp_decode_reduction (optional reduction) { @@ -659,18 +680,21 @@ FilmViewer::set_dcp_decode_reduction (optional reduction) } } + optional FilmViewer::dcp_decode_reduction () const { return _dcp_decode_reduction; } + DCPTime FilmViewer::one_video_frame () const { return DCPTime::from_frames (1, _film ? _film->video_frame_rate() : 24); } + /** Open a dialog box showing our film's closed captions */ void FilmViewer::show_closed_captions () @@ -678,18 +702,21 @@ FilmViewer::show_closed_captions () _closed_captions_dialog->Show(); } + void FilmViewer::seek_by (DCPTime by, bool accurate) { seek (_video_view->position() + by, accurate); } + void FilmViewer::set_pad_black (bool p) { _pad_black = p; } + /** Called when a player has finished the current film. * May be called from a non-UI thread. */ @@ -699,6 +726,7 @@ FilmViewer::finished () emit (boost::bind(&FilmViewer::ui_finished, this)); } + /** Called by finished() in the UI thread */ void FilmViewer::ui_finished () @@ -707,6 +735,7 @@ FilmViewer::ui_finished () Finished (); } + int FilmViewer::dropped () const { diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h index 52b97f0f6..0f9967519 100644 --- a/src/wx/film_viewer.h +++ b/src/wx/film_viewer.h @@ -95,7 +95,7 @@ public: void set_dcp_decode_reduction (boost::optional reduction); boost::optional dcp_decode_reduction () const; void set_outline_content (bool o); - void set_outline_subtitles (boost::optional >); + void set_outline_subtitles (boost::optional>); void set_eyes (Eyes e); void set_pad_black (bool p); @@ -121,7 +121,7 @@ public: bool outline_content () const { return _outline_content; } - boost::optional > outline_subtitles () const { + boost::optional> outline_subtitles () const { return _outline_subtitles; } bool pad_black () const { @@ -171,38 +171,38 @@ private: std::shared_ptr _film; std::shared_ptr _player; - VideoView* _video_view; - bool _coalesce_player_changes; + VideoView* _video_view = nullptr; + bool _coalesce_player_changes = false; std::vector _pending_player_changes; /** Size of our output (including padding if we have any) */ dcp::Size _out_size; RtAudio _audio; - int _audio_channels; - unsigned int _audio_block_size; - bool _playing; - int _suspended; + int _audio_channels = 0; + unsigned int _audio_block_size = 1024; + bool _playing = false; + int _suspended = 0; std::shared_ptr _butler; std::list _latency_history; /** Mutex to protect _latency_history */ mutable boost::mutex _latency_history_mutex; - int _latency_history_count; + int _latency_history_count = 0; boost::optional _dcp_decode_reduction; - ClosedCaptionsDialog* _closed_captions_dialog; + ClosedCaptionsDialog* _closed_captions_dialog = nullptr; - bool _outline_content; - boost::optional > _outline_subtitles; + bool _outline_content = false; + boost::optional> _outline_subtitles; /** true to pad the viewer panel with black, false to use the normal window background colour. */ - bool _pad_black; + bool _pad_black = false; /** true if an get() is required next time we are idle */ - bool _idle_get; + bool _idle_get = false; boost::signals2::scoped_connection _config_changed_connection; }; diff --git a/src/wx/timeline_reels_view.cc b/src/wx/timeline_reels_view.cc index 962451ac3..cf1abb34f 100644 --- a/src/wx/timeline_reels_view.cc +++ b/src/wx/timeline_reels_view.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2015-2016 Carl Hetherington + Copyright (C) 2015-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,15 +18,18 @@ */ + #include "timeline_reels_view.h" #include "timeline.h" #include #include + using std::min; using std::list; using namespace dcpomatic; + TimelineReelsView::TimelineReelsView (Timeline& tl, int y) : TimelineView (tl) , _y (y) @@ -34,12 +37,14 @@ TimelineReelsView::TimelineReelsView (Timeline& tl, int y) } + dcpomatic::Rect TimelineReelsView::bbox () const { return dcpomatic::Rect (0, _y - 4, _timeline.width(), 24); } + void TimelineReelsView::set_y (int y) { @@ -47,8 +52,9 @@ TimelineReelsView::set_y (int y) force_redraw (); } + void -TimelineReelsView::do_paint (wxGraphicsContext* gc, list >) +TimelineReelsView::do_paint (wxGraphicsContext* gc, list>) { if (!_timeline.pixels_per_second()) { return; @@ -58,7 +64,7 @@ TimelineReelsView::do_paint (wxGraphicsContext* gc, list >) gc->SetPen (*wxThePenList->FindOrCreatePen (wxColour (0, 0, 255), 1, wxPENSTYLE_SOLID)); - wxGraphicsPath path = gc->CreatePath (); + auto path = gc->CreatePath (); path.MoveToPoint (time_x (DCPTime (0)), _y); path.AddLineToPoint (time_x (_timeline.film()->length()), _y); gc->StrokePath (path); @@ -69,7 +75,7 @@ TimelineReelsView::do_paint (wxGraphicsContext* gc, list >) for (auto i: _timeline.film()->reels()) { int const size = min (8.0, i.duration().seconds() * pps / 2); - wxGraphicsPath path = gc->CreatePath (); + auto path = gc->CreatePath (); path.MoveToPoint (time_x (i.from) + size, _y + size / 2); path.AddLineToPoint (time_x (i.from), _y); path.AddLineToPoint (time_x (i.from) + size, _y - size / 2); @@ -81,17 +87,17 @@ TimelineReelsView::do_paint (wxGraphicsContext* gc, list >) path.AddLineToPoint (time_x (i.to) - size, _y - size / 2); gc->StrokePath (path); - wxString str = wxString::Format (_("Reel %d"), reel++); + auto str = wxString::Format (_("Reel %d"), reel++); wxDouble str_width; wxDouble str_height; wxDouble str_descent; wxDouble str_leading; gc->GetTextExtent (str, &str_width, &str_height, &str_descent, &str_leading); - int const available_width = time_x (DCPTime (i.to.get())) - time_x (DCPTime (i.from.get())); + int const available_width = time_x(DCPTime(i.to.get())) - time_x(DCPTime(i.from.get())); if (available_width > str_width) { - gc->DrawText (str, time_x (DCPTime (i.from.get())) + (available_width - str_width) / 2, _y + 4); + gc->DrawText (str, time_x(DCPTime(i.from.get())) + (available_width - str_width) / 2, _y + 4); } } } diff --git a/src/wx/timeline_reels_view.h b/src/wx/timeline_reels_view.h index c31045651..a6c73100f 100644 --- a/src/wx/timeline_reels_view.h +++ b/src/wx/timeline_reels_view.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2015-2016 Carl Hetherington + Copyright (C) 2015-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,8 +18,10 @@ */ + #include "timeline_view.h" + class TimelineReelsView : public TimelineView { public: @@ -29,7 +31,7 @@ public: void set_y (int y); private: - void do_paint (wxGraphicsContext* gc, std::list > overlaps); + void do_paint (wxGraphicsContext* gc, std::list> overlaps); int _y; }; diff --git a/test/audio_merger_test.cc b/test/audio_merger_test.cc index d8e5b0e26..4472f02c1 100644 --- a/test/audio_merger_test.cc +++ b/test/audio_merger_test.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2020 Carl Hetherington + Copyright (C) 2013-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,11 +18,13 @@ */ + /** @file test/audio_merger_test.cc * @brief Test AudioMerger class. * @ingroup selfcontained */ + #include "lib/cross.h" #include "lib/audio_merger.h" #include "lib/audio_buffers.h" @@ -35,7 +37,9 @@ #include #include + using std::pair; +using std::make_shared; using std::list; using std::cout; using std::string; @@ -43,20 +47,24 @@ using std::shared_ptr; using boost::bind; using namespace dcpomatic; + static shared_ptr last_audio; + int const sampling_rate = 48000; + static void push (AudioMerger& merger, int from, int to, int at) { - shared_ptr buffers (new AudioBuffers (1, to - from)); + auto buffers = make_shared(1, to - from); for (int i = 0; i < (to - from); ++i) { buffers->data()[0][i] = from + i; } merger.push (buffers, DCPTime(at, sampling_rate)); } + /* Basic mixing, 2 overlapping pushes */ BOOST_AUTO_TEST_CASE (audio_merger_test1) { @@ -65,7 +73,7 @@ BOOST_AUTO_TEST_CASE (audio_merger_test1) push (merger, 0, 64, 0); push (merger, 0, 64, 22); - list, DCPTime> > tb = merger.pull (DCPTime::from_frames (22, sampling_rate)); + auto tb = merger.pull (DCPTime::from_frames (22, sampling_rate)); BOOST_REQUIRE (tb.size() == 1U); BOOST_CHECK (tb.front().first != shared_ptr ()); BOOST_CHECK_EQUAL (tb.front().first->frames(), 22); @@ -91,6 +99,7 @@ BOOST_AUTO_TEST_CASE (audio_merger_test1) } } + /* Push at non-zero time */ BOOST_AUTO_TEST_CASE (audio_merger_test2) { @@ -99,7 +108,7 @@ BOOST_AUTO_TEST_CASE (audio_merger_test2) push (merger, 0, 64, 9); /* There's nothing from 0 to 9 */ - list, DCPTime> > tb = merger.pull (DCPTime::from_frames (9, sampling_rate)); + auto tb = merger.pull (DCPTime::from_frames (9, sampling_rate)); BOOST_CHECK_EQUAL (tb.size(), 0U); /* Then there's our data at 9 */ @@ -114,6 +123,7 @@ BOOST_AUTO_TEST_CASE (audio_merger_test2) } } + /* Push two non contiguous blocks */ BOOST_AUTO_TEST_CASE (audio_merger_test3) { @@ -124,7 +134,7 @@ BOOST_AUTO_TEST_CASE (audio_merger_test3) /* Get them back */ - list, DCPTime> > tb = merger.pull (DCPTime::from_frames (100, sampling_rate)); + auto tb = merger.pull (DCPTime::from_frames (100, sampling_rate)); BOOST_REQUIRE (tb.size() == 1U); BOOST_CHECK_EQUAL (tb.front().first->frames(), 64); BOOST_CHECK_EQUAL (tb.front().second.get(), DCPTime::from_frames(17, sampling_rate).get()); @@ -141,10 +151,11 @@ BOOST_AUTO_TEST_CASE (audio_merger_test3) } } + /* Reply a sequence of calls to AudioMerger that resulted in a crash */ BOOST_AUTO_TEST_CASE (audio_merger_test4) { - FILE* f = fopen_boost("test/data/audio_merger_bug1.log", "r"); + auto f = fopen_boost("test/data/audio_merger_bug1.log", "r"); BOOST_REQUIRE (f); list tokens; char buf[64]; @@ -153,7 +164,7 @@ BOOST_AUTO_TEST_CASE (audio_merger_test4) } shared_ptr merger; - list::const_iterator i = tokens.begin (); + auto i = tokens.begin (); while (i != tokens.end()) { BOOST_CHECK (*i++ == "I/AM"); string const cmd = *i++; @@ -167,7 +178,7 @@ BOOST_AUTO_TEST_CASE (audio_merger_test4) DCPTime time(dcp::raw_convert(*i++)); BOOST_REQUIRE (i != tokens.end()); int const frames = dcp::raw_convert(*i++); - shared_ptr buffers(new AudioBuffers(1, frames)); + auto buffers = make_shared(1, frames); BOOST_REQUIRE (merger); merger->push (buffers, time); } else if (cmd == "pull") { @@ -178,4 +189,3 @@ BOOST_AUTO_TEST_CASE (audio_merger_test4) } } - diff --git a/test/dcp_decoder_test.cc b/test/dcp_decoder_test.cc index 45b715e95..a52a0ccc5 100644 --- a/test/dcp_decoder_test.cc +++ b/test/dcp_decoder_test.cc @@ -34,6 +34,7 @@ #include "lib/job_manager.h" #include "lib/config.h" #include "test.h" +#include #include #include #include -- 2.30.2