Various improvements to the content properties dialogue (including #791).
authorCarl Hetherington <cth@carlh.net>
Thu, 18 Feb 2016 17:42:58 +0000 (17:42 +0000)
committerCarl Hetherington <cth@carlh.net>
Thu, 18 Feb 2016 17:42:58 +0000 (17:42 +0000)
15 files changed:
ChangeLog
src/lib/audio_content.cc
src/lib/audio_content.h
src/lib/content.cc
src/lib/content.h
src/lib/dcp_content.cc
src/lib/dcp_content.h
src/lib/ffmpeg_content.cc
src/lib/ffmpeg_content.h
src/lib/single_stream_audio_content.cc
src/lib/single_stream_audio_content.h
src/lib/video_content.cc
src/lib/video_content.h
src/wx/content_properties_dialog.cc
src/wx/table_dialog.cc

index 9e53166e947a9c2cce97998346dfb411c51504ab..dc5c28c11282293d2bf742c38027c9584f6ed360 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2016-02-18  c.hetherington  <cth@carlh.net>
+
+       * Add some more information to the content properties
+       dialogue (#791).
+
 2016-02-17  Carl Hetherington  <cth@carlh.net>
 
        * Store cinema / screen certificates in a separate
index 87a1d180343f563bb5fccb17926c7be2b8dbb84e..c17893c5aeb61402520fc079faa2e17c9e5a54f5 100644 (file)
@@ -296,7 +296,48 @@ AudioContent::audio_channel_names () const
 }
 
 void
-AudioContent::add_properties (list<pair<string, string> >& p) const
+AudioContent::add_properties (list<UserProperty>& p) const
 {
-       p.push_back (make_pair (_("DCP audio frame rate"), raw_convert<string> (resampled_audio_frame_rate ())));
+       shared_ptr<const AudioStream> stream;
+       if (audio_streams().size() == 1) {
+               stream = audio_streams().front ();
+       }
+
+       if (stream) {
+               p.push_back (UserProperty (_("Audio"), _("Channels"), stream->channels ()));
+               p.push_back (UserProperty (_("Audio"), _("Content audio frame rate"), stream->frame_rate(), _("Hz")));
+       }
+
+       shared_ptr<const Film> film = _film.lock ();
+       DCPOMATIC_ASSERT (film);
+
+       FrameRateChange const frc = film->active_frame_rate_change (position ());
+       ContentTime const c (full_length(), frc);
+
+       p.push_back (
+               UserProperty (_("Length"), _("Full length in video frames at content rate"), c.frames_round(frc.source))
+               );
+
+       if (stream) {
+               p.push_back (
+                       UserProperty (
+                               _("Length"),
+                               _("Full length in audio frames at content rate"),
+                               c.frames_round (stream->frame_rate ())
+                               )
+                       );
+       }
+
+       p.push_back (UserProperty (_("Audio"), _("DCP frame rate"), resampled_audio_frame_rate ()));
+       p.push_back (UserProperty (_("Length"), _("Full length in video frames at DCP rate"), c.frames_round (frc.dcp)));
+
+       if (stream) {
+               p.push_back (
+                       UserProperty (
+                               _("Length"),
+                               _("Full length in audio frames at DCP rate"),
+                               c.frames_round (resampled_audio_frame_rate ())
+                               )
+                       );
+       }
 }
index 95231a7d742382990057e0ddf644e76d693ae9ae..33c52aa73688d54b042c97adce84b96da4f074f9 100644 (file)
@@ -79,7 +79,7 @@ public:
 
 protected:
 
-       void add_properties (std::list<std::pair<std::string, std::string> > &) const;
+       void add_properties (std::list<UserProperty> &) const;
 
 private:
        /** Gain to apply to audio in dB */
index 2c89f7c346ffdb93374163f7cd4e6efdb19704d1..724cabb6c6ce28f4bf1d5057e08dc062ab07b525 100644 (file)
@@ -277,13 +277,11 @@ Content::path_summary () const
        return s;
 }
 
-/** @return a list of properties that might be interesting to the user; first string is the property name,
- *  second is the value.
- */
-list<pair<string, string> >
-Content::properties () const
+/** @return a list of properties that might be interesting to the user */
+list<Content::UserProperty>
+Content::user_properties () const
 {
-       list<pair<string, string> > p;
+       list<UserProperty> p;
        add_properties (p);
        return p;
 }
index 283889485d50d20bb321d317907d04c131fa0a0d..d87ae13d7fee53739f8a5d8ecb1173d177654929 100644 (file)
@@ -27,6 +27,7 @@
 #include "types.h"
 #include "signaller.h"
 #include "dcpomatic_time.h"
+#include "raw_convert.h"
 #include <libcxml/cxml.h>
 #include <boost/filesystem.hpp>
 #include <boost/signals2.hpp>
@@ -91,8 +92,6 @@ public:
         */
        virtual std::list<DCPTime> reel_split_points () const;
 
-       std::list<std::pair<std::string, std::string> > properties () const;
-
        boost::shared_ptr<Content> clone () const;
 
        void set_path (boost::filesystem::path);
@@ -162,11 +161,31 @@ public:
 
        boost::shared_ptr<const Film> film () const;
 
+       class UserProperty
+       {
+       public:
+               template <class T>
+               UserProperty (std::string category_, std::string key_, T value_, std::string unit_ = "")
+                       : category (category_)
+                       , key (key_)
+                       , value (raw_convert<std::string> (value_))
+                       , unit (unit_)
+               {}
+
+               std::string category;
+               std::string key;
+               std::string value;
+               std::string unit;
+       };
+
+       std::list<UserProperty> user_properties () const;
+
        boost::signals2::signal<void (boost::weak_ptr<Content>, int, bool)> Changed;
 
 protected:
        void signal_changed (int);
-       virtual void add_properties (std::list<std::pair<std::string, std::string> > &) const {}
+
+       virtual void add_properties (std::list<UserProperty> &) const {}
 
        boost::weak_ptr<const Film> _film;
 
index 84c864d990414a112ea7305edf546c6728aa4e0e..8698c4ecd8325ef712b59ad600333290d3e5d67f 100644 (file)
@@ -205,7 +205,7 @@ DCPContent::directory () const
 }
 
 void
-DCPContent::add_properties (list<pair<string, string> >& p) const
+DCPContent::add_properties (list<UserProperty>& p) const
 {
        SingleStreamAudioContent::add_properties (p);
 }
index 78c97bec513026d3470640ea01b1c02075693a13..26c1802bacb748557aa18ad60b827ce4686e541e 100644 (file)
@@ -125,7 +125,7 @@ public:
        bool can_reference_subtitle (std::list<std::string> &) const;
 
 protected:
-       void add_properties (std::list<std::pair<std::string, std::string> >& p) const;
+       void add_properties (std::list<UserProperty>& p) const;
 
 private:
        void read_directory (boost::filesystem::path);
index f2fe06f36aca3b182b892fc719654aeda96bcb82..9cd0395f2f6b22c02846a5f6d77859d1d0e9ef0d 100644 (file)
@@ -392,7 +392,7 @@ FFmpegContent::audio_streams () const
 }
 
 void
-FFmpegContent::add_properties (list<pair<string, string> >& p) const
+FFmpegContent::add_properties (list<UserProperty>& p) const
 {
        VideoContent::add_properties (p);
        AudioContent::add_properties (p);
@@ -405,17 +405,21 @@ FFmpegContent::add_properties (list<pair<string, string> >& p) const
                case AVCOL_RANGE_UNSPECIFIED:
                        /// TRANSLATORS: this means that the range of pixel values used in this
                        /// file is unknown (not specified in the file).
-                       p.push_back (make_pair (_("Colour range"), _("Unspecified")));
+                       p.push_back (UserProperty (_("Video"), _("Colour range"), _("Unspecified")));
                        break;
                case AVCOL_RANGE_MPEG:
                        /// TRANSLATORS: this means that the range of pixel values used in this
                        /// file is limited, so that not all possible values are valid.
-                       p.push_back (make_pair (_("Colour range"), String::compose (_("Limited (%1-%2)"), (total - sub) / 2, (total + sub) / 2)));
+                       p.push_back (
+                               UserProperty (
+                                       _("Video"), _("Colour range"), String::compose (_("Limited (%1-%2)"), (total - sub) / 2, (total + sub) / 2)
+                                       )
+                               );
                        break;
                case AVCOL_RANGE_JPEG:
                        /// TRANSLATORS: this means that the range of pixel values used in this
                        /// file is full, so that all possible pixel values are valid.
-                       p.push_back (make_pair (_("Colour range"), String::compose (_("Full (0-%1)"), total)));
+                       p.push_back (UserProperty (_("Video"), _("Colour range"), String::compose (_("Full (0-%1)"), total)));
                        break;
                default:
                        DCPOMATIC_ASSERT (false);
@@ -425,17 +429,17 @@ FFmpegContent::add_properties (list<pair<string, string> >& p) const
                case AVCOL_RANGE_UNSPECIFIED:
                        /// TRANSLATORS: this means that the range of pixel values used in this
                        /// file is unknown (not specified in the file).
-                       p.push_back (make_pair (_("Colour range"), _("Unspecified")));
+                       p.push_back (UserProperty (_("Video"), _("Colour range"), _("Unspecified")));
                        break;
                case AVCOL_RANGE_MPEG:
                        /// TRANSLATORS: this means that the range of pixel values used in this
                        /// file is limited, so that not all possible values are valid.
-                       p.push_back (make_pair (_("Colour range"), _("Limited")));
+                       p.push_back (UserProperty (_("Video"), _("Colour range"), _("Limited")));
                        break;
                case AVCOL_RANGE_JPEG:
                        /// TRANSLATORS: this means that the range of pixel values used in this
                        /// file is full, so that all possible pixel values are valid.
-                       p.push_back (make_pair (_("Colour range"), _("Full")));
+                       p.push_back (UserProperty (_("Video"), _("Colour range"), _("Full")));
                        break;
                default:
                        DCPOMATIC_ASSERT (false);
@@ -456,7 +460,7 @@ FFmpegContent::add_properties (list<pair<string, string> >& p) const
        };
 
        DCPOMATIC_ASSERT (AVCOL_PRI_NB == 10);
-       p.push_back (make_pair (_("Colour primaries"), primaries[_color_primaries]));
+       p.push_back (UserProperty (_("Video"), _("Colour primaries"), primaries[_color_primaries]));
 
        char const * transfers[] = {
                _("Unspecified"),
@@ -478,7 +482,7 @@ FFmpegContent::add_properties (list<pair<string, string> >& p) const
        };
 
        DCPOMATIC_ASSERT (AVCOL_TRC_NB == 16);
-       p.push_back (make_pair (_("Colour transfer characteristic"), transfers[_color_trc]));
+       p.push_back (UserProperty (_("Video"), _("Colour transfer characteristic"), transfers[_color_trc]));
 
        char const * spaces[] = {
                _("RGB / sRGB (IEC61966-2-1)"),
@@ -495,9 +499,9 @@ FFmpegContent::add_properties (list<pair<string, string> >& p) const
        };
 
        DCPOMATIC_ASSERT (AVCOL_SPC_NB == 11);
-       p.push_back (make_pair (_("Colourspace"), spaces[_colorspace]));
+       p.push_back (UserProperty (_("Video"), _("Colourspace"), spaces[_colorspace]));
 
        if (_bits_per_pixel) {
-               p.push_back (make_pair (_("Bits per pixel"), raw_convert<string> (_bits_per_pixel.get ())));
+               p.push_back (UserProperty (_("Video"), _("Bits per pixel"), raw_convert<string> (_bits_per_pixel.get ())));
        }
 }
index 8bd84c144dabd7efce225cdae1b3577f1a0829ef..c7dc374fdcd526df74ea5e0941080283eb169cb4 100644 (file)
@@ -106,7 +106,7 @@ public:
        std::list<ContentTimePeriod> text_subtitles_during (ContentTimePeriod, bool starting) const;
 
 protected:
-       void add_properties (std::list<std::pair<std::string, std::string> > &) const;
+       void add_properties (std::list<UserProperty> &) const;
 
 private:
        friend struct ffmpeg_pts_offset_test;
index b3c74d901e58f25fcd2709a4d4868a0f9829f330..b1291df453871b806a7977f62ab70cb527927f56 100644 (file)
@@ -85,11 +85,3 @@ SingleStreamAudioContent::audio_streams () const
        return s;
 }
 
-void
-SingleStreamAudioContent::add_properties (list<pair<string, string> >& p) const
-{
-       p.push_back (make_pair (_("Audio channels"), raw_convert<string> (audio_stream()->channels ())));
-       p.push_back (make_pair (_("Content audio frame rate"), raw_convert<string> (audio_stream()->frame_rate ())));
-
-       AudioContent::add_properties (p);
-}
index ad4de46ea22d0f63fec6ec35eb84700c77a50a63..7ae6dbaa46c3538d6fb5a951e05ebd829a7031b4 100644 (file)
@@ -49,8 +49,6 @@ public:
        void take_from_audio_examiner (boost::shared_ptr<AudioExaminer>);
 
 protected:
-       void add_properties (std::list<std::pair<std::string, std::string> > &) const;
-
        boost::shared_ptr<AudioStream> _audio_stream;
 };
 
index 514ecae2eaa7a12fd6e3f542e89c05d046bdf476..0fbcba7e0b4c6f9aee23da61372b0cea8221b097 100644 (file)
@@ -579,11 +579,11 @@ VideoContent::processing_description () const
 }
 
 void
-VideoContent::add_properties (list<pair<string, string> >& p) const
+VideoContent::add_properties (list<UserProperty>& p) const
 {
-       p.push_back (make_pair (_("Video length"), raw_convert<string> (video_length ()) + " " + _("video frames")));
-       p.push_back (make_pair (_("Video size"), raw_convert<string> (video_size().width) + "x" + raw_convert<string> (video_size().height)));
-       p.push_back (make_pair (_("Video frame rate"), raw_convert<string> (video_frame_rate()) + " " + _("frames per second")));
+       p.push_back (UserProperty (_("Video"), _("Length"), raw_convert<string> (video_length ()), _("video frames")));
+       p.push_back (UserProperty (_("Video"), _("Size"), raw_convert<string> (video_size().width) + "x" + raw_convert<string> (video_size().height)));
+       p.push_back (UserProperty (_("Video"), _("Frame rate"), raw_convert<string> (video_frame_rate()), _("frames per second")));
 }
 
 double
index 0e58bd1b17b88406303819a9cdeae5e0089210d9..f672e37b59b55d789fb674981c8032db691ff0a5 100644 (file)
@@ -174,7 +174,7 @@ public:
 
 protected:
        void take_from_video_examiner (boost::shared_ptr<VideoExaminer>);
-       void add_properties (std::list<std::pair<std::string, std::string> > &) const;
+       void add_properties (std::list<UserProperty> &) const;
 
        Frame _video_length;
        /** Video frame rate, or not set if this content should use the DCP's frame rate */
index 0b9bd0bb85b8b88f36a18700384f0a8be74fe816..8920ad9130c78e69358826ff84e3daa3080d2135 100644 (file)
 #include "lib/audio_content.h"
 #include "lib/single_stream_audio_content.h"
 #include <boost/algorithm/string.hpp>
+#include <boost/foreach.hpp>
 
 using std::string;
 using std::list;
 using std::pair;
+using std::map;
 using boost::shared_ptr;
 using boost::dynamic_pointer_cast;
 
@@ -40,10 +42,22 @@ ContentPropertiesDialog::ContentPropertiesDialog (wxWindow* parent, shared_ptr<C
        add (_("Filename"), true);
        add (new wxStaticText (this, wxID_ANY, std_to_wx (n)));
 
-       list<pair<string, string> > properties = content->properties ();
-       for (list<pair<string, string> >::const_iterator i = properties.begin(); i != properties.end(); ++i) {
-               add (std_to_wx (i->first), true);
-               add (new wxStaticText (this, wxID_ANY, std_to_wx (i->second)));
+       map<string, list<Content::UserProperty> > grouped;
+       BOOST_FOREACH (Content::UserProperty i, content->user_properties()) {
+               if (grouped.find(i.category) == grouped.end()) {
+                       grouped[i.category] = list<Content::UserProperty> ();
+               }
+               grouped[i.category].push_back (i);
+       }
+
+       for (map<string, list<Content::UserProperty> >::const_iterator i = grouped.begin(); i != grouped.end(); ++i) {
+               add (std_to_wx ("<b>" + i->first + "</b>"), false);
+               add_spacer ();
+
+               BOOST_FOREACH (Content::UserProperty j, i->second) {
+                       add (std_to_wx (j.key), true);
+                       add (new wxStaticText (this, wxID_ANY, std_to_wx (j.value + " " + j.unit)));
+               }
        }
 
        layout ();
index 3c5d9d3d53e8315041f0da069f95f46e9608f543..3f8d10fe14aee08e0459e9c5d30e01f71b63840b 100644 (file)
@@ -50,9 +50,22 @@ TableDialog::layout ()
 }
 
 void
+#ifdef DCPOMATIC_OSX
 TableDialog::add (wxString text, bool label)
+#else
+TableDialog::add (wxString text, bool)
+#endif
 {
-       add_label_to_sizer (_table, this, text, label);
+       int flags = wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT;
+#ifdef __WXOSX__
+       if (label) {
+               flags |= wxALIGN_RIGHT;
+               t += wxT (":");
+       }
+#endif
+       wxStaticText* m = new wxStaticText (this, wxID_ANY, wxT (""));
+       m->SetLabelMarkup (text);
+       _table->Add (m, 0, flags, 6);
 }
 
 void