diff options
| author | Carl Hetherington <cth@carlh.net> | 2020-05-10 01:57:20 +0200 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2020-05-11 22:02:49 +0200 |
| commit | 15a83d720780d58f905d40f8493cdcb86596eaee (patch) | |
| tree | 96edb81d905bed4231819efc5bd6292aefaf2c4c /src | |
| parent | dd7c63112eda87f2e491261873075acff114396b (diff) | |
Change video content scaling so that it either:
1. scales the content up to fit the DCP container,
preserving aspect ratio, or
2. stretches the content to a custom aspect ratio, or
3. scales the content to some custom size.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/create_cli.cc | 29 | ||||
| -rw-r--r-- | src/lib/create_cli.h | 1 | ||||
| -rw-r--r-- | src/lib/film.cc | 10 | ||||
| -rw-r--r-- | src/lib/hints.cc | 2 | ||||
| -rw-r--r-- | src/lib/player.cc | 4 | ||||
| -rw-r--r-- | src/lib/player.h | 4 | ||||
| -rw-r--r-- | src/lib/player_video.cc | 2 | ||||
| -rw-r--r-- | src/lib/util.cc | 19 | ||||
| -rw-r--r-- | src/lib/util.h | 1 | ||||
| -rw-r--r-- | src/lib/video_content.cc | 118 | ||||
| -rw-r--r-- | src/lib/video_content.h | 39 | ||||
| -rw-r--r-- | src/lib/video_content_scale.cc | 171 | ||||
| -rw-r--r-- | src/lib/video_content_scale.h | 81 | ||||
| -rw-r--r-- | src/lib/wscript | 1 | ||||
| -rw-r--r-- | src/tools/dcpomatic_cli.cc | 6 | ||||
| -rw-r--r-- | src/tools/dcpomatic_create.cc | 1 | ||||
| -rw-r--r-- | src/wx/custom_scale_dialog.cc | 142 | ||||
| -rw-r--r-- | src/wx/custom_scale_dialog.h | 51 | ||||
| -rw-r--r-- | src/wx/video_panel.cc | 132 | ||||
| -rw-r--r-- | src/wx/video_panel.h | 10 | ||||
| -rw-r--r-- | src/wx/wscript | 3 |
21 files changed, 447 insertions, 380 deletions
diff --git a/src/lib/create_cli.cc b/src/lib/create_cli.cc index 878ee6fdd..b670282b4 100644 --- a/src/lib/create_cli.cc +++ b/src/lib/create_cli.cc @@ -42,7 +42,6 @@ string CreateCLI::_help = " -c, --dcp-content-type <type> FTR, SHR, TLR, TST, XSN, RTG, TSR, POL, PSA or ADV\n" " -f, --dcp-frame-rate <rate> set DCP video frame rate (otherwise guessed from content)\n" " --container-ratio <ratio> 119, 133, 137, 138, 166, 178, 185 or 239\n" - " --content-ratio <ratio> 119, 133, 137, 138, 166, 178, 185 or 239\n" " -s, --still-length <n> number of seconds that still content should last\n" " --standard <standard> SMPTE or interop (default SMPTE)\n" " --no-use-isdcf-name do not use an ISDCF name; use the specified name unmodified\n" @@ -79,7 +78,6 @@ CreateCLI::CreateCLI (int argc, char* argv[]) , threed (false) , dcp_content_type (0) , container_ratio (0) - , content_ratio (0) , still_length (10) , standard (dcp::SMPTE) , no_use_isdcf_name (false) @@ -87,7 +85,6 @@ CreateCLI::CreateCLI (int argc, char* argv[]) , fourk (false) { string dcp_content_type_string = "TST"; - string content_ratio_string; string container_ratio_string; string standard_string = "SMPTE"; int dcp_frame_rate_int = 0; @@ -136,7 +133,6 @@ CreateCLI::CreateCLI (int argc, char* argv[]) argument_option(i, argc, argv, "-c", "--dcp-content-type", &claimed, &error, &dcp_content_type_string); argument_option(i, argc, argv, "-f", "--dcp-frame-rate", &claimed, &error, &dcp_frame_rate_int); argument_option(i, argc, argv, "", "--container-ratio", &claimed, &error, &container_ratio_string); - argument_option(i, argc, argv, "", "--content-ratio", &claimed, &error, &content_ratio_string); argument_option(i, argc, argv, "-s", "--still-length", &claimed, &error, &still_length); argument_option(i, argc, argv, "", "--standard", &claimed, &error, &standard_string); argument_option(i, argc, argv, "", "--config", &claimed, &error, &config_dir_string); @@ -185,25 +181,12 @@ CreateCLI::CreateCLI (int argc, char* argv[]) return; } - if (content_ratio_string.empty()) { - error = String::compose("%1: missing required option --content-ratio", argv[0]); - return; - } - - content_ratio = Ratio::from_id (content_ratio_string); - if (!content_ratio) { - error = String::compose("%1: unrecognised content ratio %2", content_ratio_string); - return; - } - - if (container_ratio_string.empty()) { - container_ratio_string = content_ratio_string; - } - - container_ratio = Ratio::from_id (container_ratio_string); - if (!container_ratio) { - error = String::compose("%1: unrecognised container ratio %2", argv[0], container_ratio_string); - return; + if (!container_ratio_string.empty()) { + container_ratio = Ratio::from_id (container_ratio_string); + if (!container_ratio) { + error = String::compose("%1: unrecognised container ratio %2", argv[0], container_ratio_string); + return; + } } if (standard_string != "SMPTE" && standard_string != "interop") { diff --git a/src/lib/create_cli.h b/src/lib/create_cli.h index a9d9daa22..01e8e6633 100644 --- a/src/lib/create_cli.h +++ b/src/lib/create_cli.h @@ -45,7 +45,6 @@ public: DCPContentType const * dcp_content_type; boost::optional<int> dcp_frame_rate; Ratio const * container_ratio; - Ratio const * content_ratio; int still_length; dcp::Standard standard; bool no_use_isdcf_name; diff --git a/src/lib/film.cc b/src/lib/film.cc index b233e5ee6..b1dcb46d7 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -132,8 +132,10 @@ string const Film::metadata_file = "metadata.xml"; * 36 -> 37 * TextContent can be in a Caption tag, and some of the tag names * have had Subtitle prefixes or suffixes removed. + * 37 -> 38 + * VideoContent scale expressed just as "guess" or "custom" */ -int const Film::current_state_version = 37; +int const Film::current_state_version = 38; /** Construct a Film object in a given directory. * @@ -787,11 +789,7 @@ Film::isdcf_name (bool if_created_now) const BOOST_FOREACH (shared_ptr<Content> i, content ()) { if (i->video) { /* Here's the first piece of video content */ - if (i->video->scale().ratio ()) { - content_ratio = i->video->scale().ratio (); - } else { - content_ratio = Ratio::from_ratio (i->video->size().ratio ()); - } + content_ratio = Ratio::nearest_from_ratio(i->video->scaled_size(frame_size()).ratio()); break; } } diff --git a/src/lib/hints.cc b/src/lib/hints.cc index 581d63972..0f18835ef 100644 --- a/src/lib/hints.cc +++ b/src/lib/hints.cc @@ -123,7 +123,7 @@ Hints::thread () int scope = 0; BOOST_FOREACH (shared_ptr<const Content> i, content) { if (i->video) { - Ratio const * r = i->video->scale().ratio (); + Ratio const * r = Ratio::nearest_from_ratio(i->video->scaled_size(film->frame_size()).ratio()); if (r && r->id() == "239") { ++scope; } else if (r && r->id() != "239" && r->id() != "190") { diff --git a/src/lib/player.cc b/src/lib/player.cc index e41cecf13..059465724 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -864,9 +864,7 @@ Player::video (weak_ptr<Piece> wp, ContentVideo video) video.image, piece->content->video->crop (), piece->content->video->fade (_film, video.frame), - piece->content->video->scale().size ( - piece->content->video, _video_container_size, _film->frame_size () - ), + scale_for_display(piece->content->video->scaled_size(_film->frame_size()), _video_container_size, _film->frame_size()), _video_container_size, video.eyes, video.part, diff --git a/src/lib/player.h b/src/lib/player.h index 51de78982..bb2a0c613 100644 --- a/src/lib/player.h +++ b/src/lib/player.h @@ -159,7 +159,9 @@ private: boost::atomic<int> _suspended; std::list<boost::shared_ptr<Piece> > _pieces; - /** Size of the image in the DCP (e.g. 1990x1080 for flat) */ + /** Size of the image we are rendering to; this may be the DCP frame size, or + * the size of preview in a window. + */ dcp::Size _video_container_size; boost::shared_ptr<Image> _black_image; diff --git a/src/lib/player_video.cc b/src/lib/player_video.cc index cb2a55724..10e798ed5 100644 --- a/src/lib/player_video.cc +++ b/src/lib/player_video.cc @@ -339,7 +339,7 @@ PlayerVideo::reset_metadata (shared_ptr<const Film> film, dcp::Size video_contai _crop = content->video->crop(); _fade = content->video->fade(film, _video_frame.get()); - _inter_size = content->video->scale().size(content->video, video_container_size, film_frame_size); + _inter_size = scale_for_display(content->video->scaled_size(film_frame_size), video_container_size, film_frame_size); _out_size = video_container_size; _colour_conversion = content->video->colour_conversion(); _video_range = content->video->range(); diff --git a/src/lib/util.cc b/src/lib/util.cc index d04bbdf24..c1ef4245f 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -394,7 +394,6 @@ dcpomatic_setup () Ratio::setup_ratios (); PresetColourConversion::setup_colour_conversion_presets (); - VideoContentScale::setup_scales (); DCPContentType::setup_dcp_content_types (); Filter::setup_filters (); CinemaSoundProcessor::setup_cinema_sound_processors (); @@ -1184,3 +1183,21 @@ linear_to_db (double linear) return 20 * log10(linear); } + +dcp::Size +scale_for_display (dcp::Size s, dcp::Size display_container, dcp::Size film_container) +{ + /* Now scale it down if the display container is smaller than the film container */ + if (display_container != film_container) { + float const scale = min ( + float (display_container.width) / film_container.width, + float (display_container.height) / film_container.height + ); + + s.width = lrintf (s.width * scale); + s.height = lrintf (s.height * scale); + } + + return s; +} + diff --git a/src/lib/util.h b/src/lib/util.h index f8e9409f1..f7b4704ac 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -116,6 +116,7 @@ extern void copy_in_bits (boost::filesystem::path from, boost::filesystem::path extern boost::shared_ptr<dcp::CertificateChain> read_swaroop_chain (boost::filesystem::path path); extern void write_swaroop_chain (boost::shared_ptr<const dcp::CertificateChain> chain, boost::filesystem::path output); #endif +extern dcp::Size scale_for_display (dcp::Size s, dcp::Size display_container, dcp::Size film_container); template <class T> std::list<T> diff --git a/src/lib/video_content.cc b/src/lib/video_content.cc index 9e8659b98..b4ad30f70 100644 --- a/src/lib/video_content.cc +++ b/src/lib/video_content.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2019 Carl Hetherington <cth@carlh.net> + Copyright (C) 2013-2020 Carl Hetherington <cth@carlh.net> This file is part of DCP-o-matic. @@ -48,6 +48,8 @@ int const VideoContentProperty::COLOUR_CONVERSION = 5; int const VideoContentProperty::FADE_IN = 6; int const VideoContentProperty::FADE_OUT = 7; int const VideoContentProperty::RANGE = 8; +int const VideoContentProperty::CUSTOM_RATIO = 9; +int const VideoContentProperty::CUSTOM_SIZE = 10; using std::string; using std::setprecision; @@ -70,7 +72,6 @@ VideoContent::VideoContent (Content* parent) , _use (true) , _length (0) , _frame_type (VIDEO_FRAME_TYPE_2D) - , _scale (VideoContentScale (Ratio::from_id ("178"))) , _yuv (true) , _fade_in (0) , _fade_out (0) @@ -139,10 +140,29 @@ VideoContent::VideoContent (Content* parent, cxml::ConstNodePtr node, int versio if (version <= 7) { optional<string> r = node->optional_string_child ("Ratio"); if (r) { - _scale = VideoContentScale (Ratio::from_id (r.get ())); + _legacy_ratio = Ratio::from_id(r.get())->ratio(); } + } else if (version <= 37) { + optional<string> ratio = node->node_child("Scale")->optional_string_child("Ratio"); + if (ratio) { + _legacy_ratio = Ratio::from_id(ratio.get())->ratio(); + } + optional<bool> scale = node->node_child("Scale")->optional_bool_child("Scale"); + if (scale) { + if (*scale) { + /* This is what we used to call "no stretch" */ + _legacy_ratio = _size.ratio(); + } else { + /* This is what we used to call "no scale" */ + _custom_size = _size; + } + } + } else { - _scale = VideoContentScale (node->node_child ("Scale")); + _custom_ratio = node->optional_number_child<float>("CustomRatio"); + if (node->optional_number_child<int>("CustomWidth")) { + _custom_size = dcp::Size (node->number_child<int>("CustomWidth"), node->number_child<int>("CustomHeight")); + } } if (node->optional_node_child ("ColourConversion")) { @@ -190,8 +210,12 @@ VideoContent::VideoContent (Content* parent, vector<shared_ptr<Content> > c) throw JoinError (_("Content to be joined must have the same crop.")); } - if (c[i]->video->scale() != ref->scale()) { - throw JoinError (_("Content to be joined must have the same scale setting.")); + if (c[i]->video->custom_ratio() != ref->custom_ratio()) { + throw JoinError (_("Content to be joined must have the same custom ratio setting.")); + } + + if (c[i]->video->custom_size() != ref->custom_size()) { + throw JoinError (_("Content to be joined must have the same custom size setting.")); } if (c[i]->video->colour_conversion() != ref->colour_conversion()) { @@ -213,7 +237,7 @@ VideoContent::VideoContent (Content* parent, vector<shared_ptr<Content> > c) _size = ref->size (); _frame_type = ref->frame_type (); _crop = ref->crop (); - _scale = ref->scale (); + _custom_ratio = ref->custom_ratio (); _colour_conversion = ref->colour_conversion (); _fade_in = ref->fade_in (); _fade_out = ref->fade_out (); @@ -233,7 +257,13 @@ VideoContent::as_xml (xmlpp::Node* node) const node->add_child("SampleAspectRatio")->add_child_text (raw_convert<string> (_sample_aspect_ratio.get ())); } _crop.as_xml (node); - _scale.as_xml (node->add_child("Scale")); + if (_custom_ratio) { + node->add_child("CustomRatio")->add_child_text(raw_convert<string>(*_custom_ratio)); + } + if (_custom_size) { + node->add_child("CustomWidth")->add_child_text(raw_convert<string>(_custom_size->width)); + node->add_child("CustomHeight")->add_child_text(raw_convert<string>(_custom_size->height)); + } if (_colour_conversion) { _colour_conversion.get().as_xml (node->add_child("ColourConversion")); } @@ -265,15 +295,6 @@ VideoContent::take_from_examiner (shared_ptr<VideoExaminer> d) _sample_aspect_ratio = ar; _yuv = yuv; _range = range; - - if (Config::instance()->default_scale_to ()) { - _scale = VideoContentScale (Config::instance()->default_scale_to ()); - } else { - /* Guess correct scale from size and sample aspect ratio */ - _scale = VideoContentScale ( - Ratio::nearest_from_ratio (double (_size.width) * ar.get_value_or (1) / _size.height) - ); - } } LOG_GENERAL ("Video length obtained from header as %1 frames", _length); @@ -289,13 +310,15 @@ VideoContent::identifier () const { char buffer[256]; snprintf ( - buffer, sizeof(buffer), "%d_%d_%d_%d_%d_%s_%" PRId64 "_%" PRId64 "_%d", + buffer, sizeof(buffer), "%d_%d_%d_%d_%d_%f_%d_%d%" PRId64 "_%" PRId64 "_%d", (_use ? 1 : 0), crop().left, crop().right, crop().top, crop().bottom, - scale().id().c_str(), + _custom_ratio.get_value_or(0), + _custom_size ? _custom_size->width : 0, + _custom_size ? _custom_size->height : 0, _fade_in, _fade_out, _range == VIDEO_RANGE_FULL ? 0 : 1 @@ -379,7 +402,7 @@ VideoContent::fade (shared_ptr<const Film> film, Frame f) const } string -VideoContent::processing_description (shared_ptr<const Film> film) const +VideoContent::processing_description (shared_ptr<const Film> film) { string d; char buffer[256]; @@ -416,7 +439,7 @@ VideoContent::processing_description (shared_ptr<const Film> film) const } dcp::Size const container_size = film->frame_size (); - dcp::Size const scaled = scale().size (shared_from_this(), container_size, container_size); + dcp::Size const scaled = scaled_size (container_size); if (scaled != size_after_crop ()) { d += String::compose ( @@ -489,11 +512,6 @@ VideoContent::set_bottom_crop (int c) maybe_set (_crop.bottom, c, VideoContentProperty::CROP); } -void -VideoContent::set_scale (VideoContentScale s) -{ - maybe_set (_scale, s, VideoContentProperty::SCALE); -} void VideoContent::set_frame_type (VideoFrameType t) @@ -551,7 +569,8 @@ VideoContent::take_settings_from (shared_ptr<const VideoContent> c) set_right_crop (c->_crop.right); set_top_crop (c->_crop.top); set_bottom_crop (c->_crop.bottom); - set_scale (c->_scale); + set_custom_ratio (c->_custom_ratio); + set_custom_size (c->_custom_size); set_fade_in (c->_fade_in); set_fade_out (c->_fade_out); } @@ -569,3 +588,48 @@ VideoContent::modify_trim_start (ContentTime& trim) const trim = trim.round (_parent->video_frame_rate().get()); } } + + +/** @param film_container The size of the container for the DCP that we are working on */ +dcp::Size +VideoContent::scaled_size (dcp::Size film_container) +{ + if (_custom_ratio) { + return fit_ratio_within(*_custom_ratio, film_container); + } + + if (_custom_size) { + return *_custom_size; + } + + dcp::Size size = size_after_crop (); + size.width *= _sample_aspect_ratio.get_value_or(1); + + /* This is what we will return unless there is any legacy stuff to take into account */ + dcp::Size auto_size = fit_ratio_within (size.ratio(), film_container); + + if (_legacy_ratio) { + if (fit_ratio_within(*_legacy_ratio, film_container) != auto_size) { + _custom_ratio = *_legacy_ratio; + _legacy_ratio = optional<float>(); + return fit_ratio_within(*_custom_ratio, film_container); + } + _legacy_ratio = 0; + } + + return auto_size; +} + + +void +VideoContent::set_custom_ratio (optional<float> ratio) +{ + maybe_set (_custom_ratio, ratio, VideoContentProperty::CUSTOM_RATIO); +} + + +void +VideoContent::set_custom_size (optional<dcp::Size> size) +{ + maybe_set (_custom_size, size, VideoContentProperty::CUSTOM_SIZE); +} diff --git a/src/lib/video_content.h b/src/lib/video_content.h index 9a7ad6dda..b478666bb 100644 --- a/src/lib/video_content.h +++ b/src/lib/video_content.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2019 Carl Hetherington <cth@carlh.net> + Copyright (C) 2013-2020 Carl Hetherington <cth@carlh.net> This file is part of DCP-o-matic. @@ -22,7 +22,6 @@ #define DCPOMATIC_VIDEO_CONTENT_H #include "colour_conversion.h" -#include "video_content_scale.h" #include "dcpomatic_time.h" #include "user_property.h" #include "types.h" @@ -48,6 +47,8 @@ public: static int const FADE_IN; static int const FADE_OUT; static int const RANGE; + static int const CUSTOM_RATIO; + static int const CUSTOM_SIZE; }; class VideoContent : public ContentPart, public boost::enable_shared_from_this<VideoContent> @@ -87,7 +88,9 @@ public: void set_top_crop (int); void set_bottom_crop (int); - void set_scale (VideoContentScale); + void set_custom_ratio (boost::optional<float> ratio); + void set_custom_size (boost::optional<dcp::Size> size); + void unset_colour_conversion (); void set_colour_conversion (ColourConversion); @@ -127,12 +130,19 @@ public: return _crop.bottom; } - /** @return Description of how to scale this content (if indeed it should be scaled) */ - VideoContentScale scale () const { + + boost::optional<float> custom_ratio () const { boost::mutex::scoped_lock lm (_mutex); - return _scale; + return _custom_ratio; } + + boost::optional<dcp::Size> custom_size () const { + boost::mutex::scoped_lock lm (_mutex); + return _custom_size; + } + + boost::optional<ColourConversion> colour_conversion () const { boost::mutex::scoped_lock lm (_mutex); return _colour_conversion; @@ -168,12 +178,14 @@ public: return _use; } + /* XXX: names for these? */ dcp::Size size_after_3d_split () const; dcp::Size size_after_crop () const; + dcp::Size scaled_size (dcp::Size container_size); boost::optional<double> fade (boost::shared_ptr<const Film> film, Frame) const; - std::string processing_description (boost::shared_ptr<const Film> film) const; + std::string processing_description (boost::shared_ptr<const Film> film); void set_length (Frame); @@ -191,6 +203,9 @@ private: friend struct best_dcp_frame_rate_test_single; friend struct best_dcp_frame_rate_test_double; friend struct audio_sampling_rate_test; + friend struct scaled_size_test1; + friend struct scaled_size_test2; + friend struct scaled_size_legacy_test; VideoContent (Content* parent, cxml::ConstNodePtr, int); void setup_default_colour_conversion (); @@ -201,7 +216,15 @@ private: dcp::Size _size; VideoFrameType _frame_type; Crop _crop; - VideoContentScale _scale; + /** ratio to scale cropped image to (or none to guess); i.e. if set, scale to _custom_ratio:1 */ + boost::optional<float> _custom_ratio; + /** size to scale cropped image to; only used if _custom_ratio is none */ + boost::optional<dcp::Size> _custom_size; + /** ratio obtained from an older metadata file; will be used to set up + * _custom_{ratio,size} (or not, if not required) on the first call to + * scaled_size() + */ + boost::optional<float> _legacy_ratio; /** Sample aspect ratio obtained from the content file's header, if there is one */ boost::optional<double> _sample_aspect_ratio; bool _yuv; diff --git a/src/lib/video_content_scale.cc b/src/lib/video_content_scale.cc deleted file mode 100644 index 73dfd27fe..000000000 --- a/src/lib/video_content_scale.cc +++ /dev/null @@ -1,171 +0,0 @@ -/* - Copyright (C) 2013-2018 Carl Hetherington <cth@carlh.net> - - This file is part of DCP-o-matic. - - DCP-o-matic is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - DCP-o-matic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "video_content_scale.h" -#include "video_content.h" -#include "ratio.h" -#include "util.h" -#include <libcxml/cxml.h> -#include <libxml++/libxml++.h> -#include <boost/optional.hpp> -#include <iostream> - -#include "i18n.h" - -using std::vector; -using std::string; -using std::min; -using std::cout; -using boost::shared_ptr; -using boost::optional; - -vector<VideoContentScale> VideoContentScale::_scales; - -VideoContentScale::VideoContentScale (Ratio const * r) - : _ratio (r) - , _scale (true) -{ - -} - -VideoContentScale::VideoContentScale () - : _ratio (0) - , _scale (false) -{ - -} - -VideoContentScale::VideoContentScale (bool scale) - : _ratio (0) - , _scale (scale) -{ - -} - -VideoContentScale::VideoContentScale (shared_ptr<cxml::Node> node) - : _ratio (0) - , _scale (true) -{ - optional<string> r = node->optional_string_child ("Ratio"); - if (r) { - _ratio = Ratio::from_id (r.get ()); - } else { - _scale = node->bool_child ("Scale"); - } -} - -void -VideoContentScale::as_xml (xmlpp::Node* node) const -{ - if (_ratio) { - node->add_child("Ratio")->add_child_text (_ratio->id ()); - } else { - node->add_child("Scale")->add_child_text (_scale ? "1" : "0"); - } -} - -string -VideoContentScale::id () const -{ - if (_ratio) { - return _ratio->id (); - } - - return (_scale ? "S1" : "S0"); -} - -string -VideoContentScale::name () const -{ - if (_ratio) { - return _ratio->image_nickname (); - } - - if (_scale) { - return _("No stretch"); - } - - return _("No scale"); -} - -/** @param display_container Size of the container that we are displaying this content in. - * @param film_container The size of the film's image. - * @return Size, in pixels that the VideoContent's image should be scaled to (taking into account its pixel aspect ratio) - */ -dcp::Size -VideoContentScale::size (shared_ptr<const VideoContent> c, dcp::Size display_container, dcp::Size film_container) const -{ - /* Work out the size of the content if it were put inside film_container */ - - dcp::Size video_size_after_crop = c->size_after_crop(); - video_size_after_crop.width *= c->sample_aspect_ratio().get_value_or(1); - - dcp::Size size; - - if (_ratio) { - /* Stretch to fit the requested ratio */ - size = fit_ratio_within (_ratio->ratio (), film_container); - } else if (_scale || video_size_after_crop.width > film_container.width || video_size_after_crop.height > film_container.height) { - /* Scale, preserving aspect ratio; this is either if we have been asked to scale with no stretch - or if the unscaled content is too big for film_container. - */ - size = fit_ratio_within (video_size_after_crop.ratio(), film_container); - } else { - /* No stretch nor scale */ - size = video_size_after_crop; - } - - /* Now scale it down if the display container is smaller than the film container */ - if (display_container != film_container) { - float const scale = min ( - float (display_container.width) / film_container.width, - float (display_container.height) / film_container.height - ); - - size.width = lrintf (size.width * scale); - size.height = lrintf (size.height * scale); - } - - return size; -} - -void -VideoContentScale::setup_scales () -{ - vector<Ratio const *> ratios = Ratio::all (); - for (vector<Ratio const *>::const_iterator i = ratios.begin(); i != ratios.end(); ++i) { - _scales.push_back (VideoContentScale (*i)); - } - - _scales.push_back (VideoContentScale (true)); - _scales.push_back (VideoContentScale (false)); -} - -bool -operator== (VideoContentScale const & a, VideoContentScale const & b) -{ - return (a.ratio() == b.ratio() && a.scale() == b.scale()); -} - -bool -operator!= (VideoContentScale const & a, VideoContentScale const & b) -{ - return (a.ratio() != b.ratio() || a.scale() != b.scale()); -} diff --git a/src/lib/video_content_scale.h b/src/lib/video_content_scale.h deleted file mode 100644 index 845c71a52..000000000 --- a/src/lib/video_content_scale.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - Copyright (C) 2013-2018 Carl Hetherington <cth@carlh.net> - - This file is part of DCP-o-matic. - - DCP-o-matic is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - DCP-o-matic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>. - -*/ - -#ifndef DCPOMATIC_VIDEO_CONTENT_SCALE_H -#define DCPOMATIC_VIDEO_CONTENT_SCALE_H - -#include <dcp/util.h> -#include <boost/shared_ptr.hpp> -#include <vector> - -namespace cxml { - class Node; -} - -namespace xmlpp { - class Node; -} - -class Ratio; -class VideoContent; - -class VideoContentScale -{ -public: - VideoContentScale (); - explicit VideoContentScale (Ratio const *); - explicit VideoContentScale (bool); - explicit VideoContentScale (boost::shared_ptr<cxml::Node>); - - dcp::Size size (boost::shared_ptr<const VideoContent>, dcp::Size display_container, dcp::Size film_container) const; - std::string id () const; - std::string name () const; - void as_xml (xmlpp::Node *) const; - - Ratio const * ratio () const { - return _ratio; - } - - bool scale () const { - return _scale; - } - - static void setup_scales (); - static std::vector<VideoContentScale> all () { - return _scales; - } - -private: - /** a ratio to stretch the content to, or 0 for no stretch */ - Ratio const * _ratio; - /** true if we want to change the size of the content in any way */ - bool _scale; - - /* If _ratio is 0 and _scale is false there is no scale at all (i.e. - the content is used at its original size) - */ - - static std::vector<VideoContentScale> _scales; -}; - -bool operator== (VideoContentScale const & a, VideoContentScale const & b); -bool operator!= (VideoContentScale const & a, VideoContentScale const & b); - -#endif diff --git a/src/lib/wscript b/src/lib/wscript index 0f2a5d197..fb222fcf4 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -177,7 +177,6 @@ sources = """ util.cc verify_dcp_job.cc video_content.cc - video_content_scale.cc video_decoder.cc video_filter_graph.cc video_mxf_content.cc diff --git a/src/tools/dcpomatic_cli.cc b/src/tools/dcpomatic_cli.cc index 6a243e126..edf4808a0 100644 --- a/src/tools/dcpomatic_cli.cc +++ b/src/tools/dcpomatic_cli.cc @@ -96,8 +96,10 @@ print_dump (shared_ptr<Film> film) << "\tcrop left " << c->video->left_crop() << " right " << c->video->right_crop() << " top " << c->video->top_crop() - << " bottom " << c->video->bottom_crop() << "\n" - << "\tscale " << c->video->scale().name() << "\n"; + << " bottom " << c->video->bottom_crop() << "\n"; + if (c->video->custom_ratio()) { + cout << "\tscale to custom ratio " << *c->video->custom_ratio() << ":1\n"; + } if (c->video->colour_conversion()) { if (c->video->colour_conversion().get().preset()) { cout << "\tcolour conversion " diff --git a/src/tools/dcpomatic_create.cc b/src/tools/dcpomatic_create.cc index 68ae09c31..bcfc2f68b 100644 --- a/src/tools/dcpomatic_create.cc +++ b/src/tools/dcpomatic_create.cc @@ -131,7 +131,6 @@ main (int argc, char* argv[]) BOOST_FOREACH (shared_ptr<Content> j, content) { if (j->video) { - j->video->set_scale (VideoContentScale(cc.content_ratio)); j->video->set_frame_type (i.frame_type); } } diff --git a/src/wx/custom_scale_dialog.cc b/src/wx/custom_scale_dialog.cc new file mode 100644 index 000000000..5725d2378 --- /dev/null +++ b/src/wx/custom_scale_dialog.cc @@ -0,0 +1,142 @@ +/* + Copyright (C) 2020 Carl Hetherington <cth@carlh.net> + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>. + +*/ + + +#include "custom_scale_dialog.h" +#include "wx_util.h" +#include "lib/util.h" +#include <dcp/raw_convert.h> +#include <wx/wx.h> +#include <wx/propgrid/property.h> +#include <wx/propgrid/props.h> + + +using boost::optional; +using namespace dcp; + + +CustomScaleDialog::CustomScaleDialog (wxWindow* parent, dcp::Size initial, dcp::Size film_container, optional<float> custom_ratio, optional<dcp::Size> custom_size) + : TableDialog (parent, _("Custom scale"), 3, 1, true) + , _film_container (film_container) +{ + _ratio_to_fit = new wxRadioButton (this, wxID_ANY, _("Set ratio and fit to DCP container")); + add (_ratio_to_fit); + wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); + _ratio = new wxTextCtrl (this, wxID_ANY, _(""), wxDefaultPosition, wxDefaultSize, 0, wxNumericPropertyValidator(wxNumericPropertyValidator::Float)); + s->Add (_ratio, 1, wxRIGHT, 4); + add_label_to_sizer (s, this, wxT(":1"), false); + add (s); + _size_from_ratio = new wxStaticText (this, wxID_ANY, wxT("")); + add (_size_from_ratio, 1, wxALIGN_CENTER_VERTICAL); + + _size = new wxRadioButton (this, wxID_ANY, _("Set size")); + add (_size); + s = new wxBoxSizer (wxHORIZONTAL); + _width = new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(64, -1), wxSP_ARROW_KEYS, 1, film_container.width); + s->Add (_width, 1, wxRIGHT, 4); + add_label_to_sizer (s, this, wxT("x"), false); + _height = new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(64, -1), wxSP_ARROW_KEYS, 1, film_container.height); + s->Add (_height, 1, wxRIGHT, 4); + add (s); + _ratio_from_size = new wxStaticText (this, wxID_ANY, wxT("")); + add (_ratio_from_size, 1, wxALIGN_CENTER_VERTICAL); + + if (custom_ratio) { + _ratio_to_fit->SetValue (true); + _size->SetValue (false); + _ratio->SetValue (wxString::Format("%.2f", *custom_ratio)); + _width->SetValue (initial.width); + _height->SetValue (initial.height); + } else if (custom_size) { + _ratio_to_fit->SetValue (false); + _size->SetValue (true); + _ratio->SetValue (wxString::Format("%.2f", initial.ratio())); + _width->SetValue (custom_size->width); + _height->SetValue (custom_size->height); + } else { + _ratio_to_fit->SetValue (true); + _size->SetValue (false); + _ratio->SetValue (wxString::Format("%.2f", initial.ratio())); + _width->SetValue (initial.width); + _height->SetValue (initial.height); + } + + setup_sensitivity (); + update_size_from_ratio (); + update_ratio_from_size (); + + layout (); + + _ratio_to_fit->Bind (wxEVT_RADIOBUTTON, boost::bind(&CustomScaleDialog::setup_sensitivity, this)); + _ratio->Bind (wxEVT_TEXT, boost::bind(&CustomScaleDialog::update_size_from_ratio, this)); + _size->Bind (wxEVT_RADIOBUTTON, boost::bind(&CustomScaleDialog::setup_sensitivity, this)); + _width->Bind (wxEVT_TEXT, boost::bind(&CustomScaleDialog::update_ratio_from_size, this)); + _height->Bind (wxEVT_TEXT, boost::bind(&CustomScaleDialog::update_ratio_from_size, this)); +} + + +void +CustomScaleDialog::update_size_from_ratio () +{ + dcp::Size const s = fit_ratio_within (raw_convert<float>(wx_to_std(_ratio->GetValue())), _film_container); + _size_from_ratio->SetLabelMarkup (wxString::Format("<i>%dx%d</i>", s.width, s.height)); +} + + +void +CustomScaleDialog::update_ratio_from_size () +{ + float const ratio = _height->GetValue() > 0 ? (float(_width->GetValue()) / _height->GetValue()) : 2; + _ratio_from_size->SetLabelMarkup (wxString::Format("<i>%.2f:1</i>", ratio)); +} + + +void +CustomScaleDialog::setup_sensitivity () +{ + _ratio->Enable (_ratio_to_fit->GetValue()); + _size_from_ratio->Enable (_ratio_to_fit->GetValue()); + _width->Enable (_size->GetValue()); + _height->Enable (_size->GetValue()); + _ratio_from_size->Enable (_size->GetValue()); +} + + +optional<float> +CustomScaleDialog::custom_ratio () const +{ + if (!_ratio_to_fit->GetValue()) { + return optional<float>(); + } + + return raw_convert<float>(wx_to_std(_ratio->GetValue())); +} + + +optional<dcp::Size> +CustomScaleDialog::custom_size () const +{ + if (!_size->GetValue()) { + return optional<dcp::Size>(); + } + + return dcp::Size (_width->GetValue(), _height->GetValue()); +} + diff --git a/src/wx/custom_scale_dialog.h b/src/wx/custom_scale_dialog.h new file mode 100644 index 000000000..4c9ccf388 --- /dev/null +++ b/src/wx/custom_scale_dialog.h @@ -0,0 +1,51 @@ +/* + Copyright (C) 2020 Carl Hetherington <cth@carlh.net> + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>. + +*/ + + +#include "table_dialog.h" +#include <dcp/types.h> +#include <wx/wx.h> +#include <wx/spinctrl.h> + + +class CustomScaleDialog : public TableDialog +{ +public: + CustomScaleDialog (wxWindow* parent, dcp::Size initial, dcp::Size film_container, boost::optional<float> custom_ratio, boost::optional<dcp::Size> custom_size); + + boost::optional<float> custom_ratio () const; + boost::optional<dcp::Size> custom_size () const; + +private: + void update_size_from_ratio (); + void update_ratio_from_size (); + void setup_sensitivity (); + + wxRadioButton* _ratio_to_fit; + wxTextCtrl* _ratio; + wxStaticText* _size_from_ratio; + wxRadioButton* _size; + wxSpinCtrl* _width; + wxSpinCtrl* _height; + wxStaticText* _ratio_from_size; + + dcp::Size _film_container; +}; + diff --git a/src/wx/video_panel.cc b/src/wx/video_panel.cc index b01e9b8aa..8a9136008 100644 --- a/src/wx/video_panel.cc +++ b/src/wx/video_panel.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net> This file is part of DCP-o-matic. @@ -26,6 +26,7 @@ #include "content_panel.h" #include "static_text.h" #include "check_box.h" +#include "custom_scale_dialog.h" #include "dcpomatic_button.h" #include "lib/filter.h" #include "lib/ffmpeg_content.h" @@ -55,27 +56,6 @@ using boost::bind; using boost::optional; using namespace dcpomatic; -static VideoContentScale -index_to_scale (int n) -{ - vector<VideoContentScale> scales = VideoContentScale::all (); - DCPOMATIC_ASSERT (n >= 0); - DCPOMATIC_ASSERT (n < int (scales.size ())); - return scales[n]; -} - -static int -scale_to_index (VideoContentScale scale) -{ - vector<VideoContentScale> scales = VideoContentScale::all (); - for (size_t i = 0; i < scales.size(); ++i) { - if (scales[i] == scale) { - return i; - } - } - - DCPOMATIC_ASSERT (false); -} VideoPanel::VideoPanel (ContentPanel* p) : ContentSubPanel (p, _("Video")) @@ -150,22 +130,15 @@ VideoPanel::VideoPanel (ContentPanel* p) _fade_out_label = create_label (this, _("Fade out"), true); _fade_out = new Timecode<ContentTime> (this); - _scale_to_label = create_label (this, _("Scale to"), true); - _scale = new ContentChoice<VideoContent, VideoContentScale> ( - this, - new wxChoice (this, wxID_ANY), - VideoContentProperty::SCALE, - &Content::video, - boost::mem_fn (&VideoContent::scale), - boost::mem_fn (&VideoContent::set_scale), - &index_to_scale, - &scale_to_index - ); - wxClientDC dc (this); wxSize size = dc.GetTextExtent (wxT ("A quite long name")); size.SetHeight (-1); + _scale_label = create_label (this, _("Scale"), true); + _scale_fit = new wxRadioButton (this, wxID_ANY, _("to fit DCP")); + _scale_custom = new wxRadioButton (this, wxID_ANY, _("custom"), wxDefaultPosition, size); + _scale_custom_edit = new Button (this, _("Edit...")); + _filters_label = create_label (this, _("Filters"), true); _filters = new StaticText (this, _("None"), wxDefaultPosition, size); _filters_button = new Button (this, _("Edit...")); @@ -194,11 +167,6 @@ VideoPanel::VideoPanel (ContentPanel* p) _right_crop->wrapped()->SetRange (0, 4096); _bottom_crop->wrapped()->SetRange (0, 4096); - _scale->wrapped()->Clear (); - BOOST_FOREACH (VideoContentScale const & i, VideoContentScale::all ()) { - _scale->wrapped()->Append (std_to_wx (i.name ())); - } - _frame_type->wrapped()->Append (_("2D")); _frame_type->wrapped()->Append (_("3D")); _frame_type->wrapped()->Append (_("3D left/right")); @@ -215,6 +183,9 @@ VideoPanel::VideoPanel (ContentPanel* p) _use->Bind (wxEVT_CHECKBOX, boost::bind (&VideoPanel::use_clicked, this)); _reference->Bind (wxEVT_CHECKBOX, boost::bind (&VideoPanel::reference_clicked, this)); _filters_button->Bind (wxEVT_BUTTON, boost::bind (&VideoPanel::edit_filters_clicked, this)); + _scale_fit->Bind (wxEVT_RADIOBUTTON, boost::bind (&VideoPanel::scale_fit_clicked, this)); + _scale_custom->Bind (wxEVT_RADIOBUTTON, boost::bind (&VideoPanel::scale_custom_clicked, this)); + _scale_custom_edit->Bind (wxEVT_BUTTON, boost::bind (&VideoPanel::scale_custom_edit_clicked, this)); _colour_conversion->Bind (wxEVT_CHOICE, boost::bind (&VideoPanel::colour_conversion_changed, this)); _range->Bind (wxEVT_CHOICE, boost::bind (&VideoPanel::range_changed, this)); _edit_colour_conversion_button->Bind (wxEVT_BUTTON, boost::bind (&VideoPanel::edit_colour_conversion_clicked, this)); @@ -260,11 +231,13 @@ VideoPanel::add_to_grid () add_label_to_sizer (crop, _bottom_crop_label, true, wxGBPosition (cr, 2)); _bottom_crop->add (crop, wxGBPosition (cr, 3)); add_label_to_sizer (_grid, _crop_label, true, wxGBPosition(r, 0)); - _grid->Add (crop, wxGBPosition(r, 1), wxGBSpan(2, 3)); - r += 2; + _grid->Add (crop, wxGBPosition(r, 1)); + ++r; - _scale_to_label->Show (full); - _scale->show (full); + _scale_label->Show (full); + _scale_fit->Show (full); + _scale_custom->Show (full); + _scale_custom_edit->Show (full); _filters_label->Show (full); _filters->Show (full); _filters_button->Show (full); @@ -283,8 +256,16 @@ VideoPanel::add_to_grid () ++r; if (full) { - add_label_to_sizer (_grid, _scale_to_label, true, wxGBPosition (r, 0)); - _scale->add (_grid, wxGBPosition (r, 1), wxGBSpan (1, 2)); + add_label_to_sizer (_grid, _scale_label, true, wxGBPosition (r, 0)); + { + wxSizer* v = new wxBoxSizer (wxVERTICAL); + v->Add (_scale_fit, 0, wxBOTTOM, 4); + wxSizer* h = new wxBoxSizer (wxHORIZONTAL); + h->Add (_scale_custom, 1, wxRIGHT, 6); + h->Add (_scale_custom_edit, 0); + v->Add (h, 0); + _grid->Add (v, wxGBPosition(r, 1)); + } ++r; add_label_to_sizer (_grid, _filters_label, true, wxGBPosition (r, 0)); @@ -486,6 +467,20 @@ VideoPanel::film_content_changed (int property) } setup_sensitivity (); + } else if (property == VideoContentProperty::CUSTOM_RATIO || property == VideoContentProperty::CUSTOM_SIZE) { + set<Frame> check; + BOOST_FOREACH (shared_ptr<const Content> i, vc) { + check.insert (i->video->custom_ratio() || i->video->custom_size()); + } + + if (check.size() == 1) { + checked_set (_scale_fit, !vc.front()->video->custom_ratio() && !vc.front()->video->custom_size()); + checked_set (_scale_custom, vc.front()->video->custom_ratio() || vc.front()->video->custom_size()); + } else { + checked_set (_scale_fit, true); + checked_set (_scale_custom, false); + } + setup_sensitivity (); } } @@ -576,7 +571,6 @@ VideoPanel::content_selection_changed () _right_crop->set_content (video_sel); _top_crop->set_content (video_sel); _bottom_crop->set_content (video_sel); - _scale->set_content (video_sel); film_content_changed (ContentProperty::VIDEO_FRAME_RATE); film_content_changed (VideoContentProperty::CROP); @@ -585,6 +579,8 @@ VideoPanel::content_selection_changed () film_content_changed (VideoContentProperty::FADE_OUT); film_content_changed (VideoContentProperty::RANGE); film_content_changed (VideoContentProperty::USE); + film_content_changed (VideoContentProperty::CUSTOM_RATIO); + film_content_changed (VideoContentProperty::CUSTOM_SIZE); film_content_changed (FFmpegContentProperty::FILTERS); film_content_changed (DCPContentProperty::REFERENCE_VIDEO); @@ -623,7 +619,9 @@ VideoPanel::setup_sensitivity () _bottom_crop->wrapped()->Enable (false); _fade_in->Enable (false); _fade_out->Enable (false); - _scale->wrapped()->Enable (false); + _scale_fit->Enable (false); + _scale_custom->Enable (false); + _scale_custom_edit->Enable (false); _description->Enable (false); _filters->Enable (false); _filters_button->Enable (false); @@ -641,7 +639,9 @@ VideoPanel::setup_sensitivity () _bottom_crop->wrapped()->Enable (true); _fade_in->Enable (!video_sel.empty ()); _fade_out->Enable (!video_sel.empty ()); - _scale->wrapped()->Enable (true); + _scale_fit->Enable (true); + _scale_custom->Enable (true); + _scale_custom_edit->Enable (_scale_custom->GetValue()); _description->Enable (true); _filters->Enable (true); _filters_button->Enable (single && !ffmpeg_sel.empty ()); @@ -703,3 +703,39 @@ VideoPanel::reference_clicked () d->set_reference_video (_reference->GetValue ()); } + + +void +VideoPanel::scale_fit_clicked () +{ + BOOST_FOREACH (shared_ptr<Content> i, _parent->selected_video()) { + i->video->set_custom_ratio (optional<float>()); + } +} + + +void +VideoPanel::scale_custom_clicked () +{ + if (!scale_custom_edit_clicked()) { + _scale_fit->SetValue (true); + } +} + + +bool +VideoPanel::scale_custom_edit_clicked () +{ + shared_ptr<const VideoContent> vc = _parent->selected_video().front()->video; + CustomScaleDialog* d = new CustomScaleDialog (this, vc->size(), _parent->film()->frame_size(), vc->custom_ratio(), vc->custom_size()); + int const r = d->ShowModal (); + if (r == wxID_OK) { + BOOST_FOREACH (shared_ptr<Content> i, _parent->selected_video()) { + i->video->set_custom_ratio (d->custom_ratio()); + i->video->set_custom_size (d->custom_size()); + } + } + d->Destroy (); + return r == wxID_OK; +} + diff --git a/src/wx/video_panel.h b/src/wx/video_panel.h index 04063ef54..22c564482 100644 --- a/src/wx/video_panel.h +++ b/src/wx/video_panel.h @@ -25,7 +25,6 @@ #include "content_sub_panel.h" #include "content_widget.h" #include "timecode.h" -#include "lib/video_content_scale.h" #include "lib/film.h" class wxChoice; @@ -55,6 +54,9 @@ private: void fade_in_changed (); void fade_out_changed (); void add_to_grid (); + void scale_fit_clicked (); + void scale_custom_clicked (); + bool scale_custom_edit_clicked (); void setup_description (); void setup_sensitivity (); @@ -77,8 +79,10 @@ private: Timecode<dcpomatic::ContentTime>* _fade_in; wxStaticText* _fade_out_label; Timecode<dcpomatic::ContentTime>* _fade_out; - wxStaticText* _scale_to_label; - ContentChoice<VideoContent, VideoContentScale>* _scale; + wxStaticText* _scale_label; + wxRadioButton* _scale_fit; + wxRadioButton* _scale_custom; + wxButton* _scale_custom_edit; wxStaticText* _description; wxStaticText* _filters_label; wxStaticText* _filters; diff --git a/src/wx/wscript b/src/wx/wscript index 22d9f0db6..a2fbe0c4e 100644 --- a/src/wx/wscript +++ b/src/wx/wscript @@ -49,6 +49,7 @@ sources = """ controls.cc closed_captions_dialog.cc credentials_download_certificate_panel.cc + custom_scale_dialog.cc dcp_panel.cc dcpomatic_button.cc disk_warning_dialog.cc @@ -165,7 +166,7 @@ sources = """ def configure(conf): - wx_libs = 'core,richtext,adv,html,xml' + wx_libs = 'core,richtext,adv,html,xml,propgrid' try: wx_config = '/usr/lib64/wx/config/gtk2-unicode-3.0' |
