Very basics of colour conversion configuration.
authorCarl Hetherington <cth@carlh.net>
Fri, 16 Aug 2013 19:14:33 +0000 (20:14 +0100)
committerCarl Hetherington <cth@carlh.net>
Fri, 16 Aug 2013 20:51:15 +0000 (21:51 +0100)
24 files changed:
src/lib/colour_conversion.cc [new file with mode: 0644]
src/lib/colour_conversion.h [new file with mode: 0644]
src/lib/config.cc
src/lib/config.h
src/lib/dcp_video_frame.cc
src/lib/dcp_video_frame.h
src/lib/encoder.cc
src/lib/encoder.h
src/lib/server.cc
src/lib/server.h
src/lib/wscript
src/tools/dcpomatic_cli.cc
src/wx/colour_conversion_dialog.cc [new file with mode: 0644]
src/wx/colour_conversion_dialog.h [new file with mode: 0644]
src/wx/config_dialog.cc
src/wx/config_dialog.h
src/wx/editable_list.h [new file with mode: 0644]
src/wx/server_dialog.cc
src/wx/server_dialog.h
src/wx/video_panel.cc
src/wx/video_panel.h
src/wx/wscript
test/client_server_test.cc
test/test.cc

diff --git a/src/lib/colour_conversion.cc b/src/lib/colour_conversion.cc
new file mode 100644 (file)
index 0000000..96dc0e2
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+    Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+    This program 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.
+
+    This program 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 this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <boost/lexical_cast.hpp>
+#include <libxml++/libxml++.h>
+#include <libdcp/colour_matrix.h>
+#include <libcxml/cxml.h>
+#include "colour_conversion.h"
+
+#include "i18n.h"
+
+using std::list;
+using std::string;
+using boost::shared_ptr;
+using boost::lexical_cast;
+
+ColourConversion::ColourConversion ()
+       : name (_("Untitled"))
+       , input_gamma (2.4)
+       , input_gamma_linearised (true)
+       , matrix (3, 3)
+       , output_gamma (2.6)
+{
+       for (int i = 0; i < 3; ++i) {
+               for (int j = 0; j < 3; ++j) {
+                       matrix (i, j) = libdcp::colour_matrix::xyz_to_rgb[i][j];
+               }
+       }
+}
+
+ColourConversion::ColourConversion (string n, float i, bool il, float const m[3][3], float o)
+       : name (n)
+       , input_gamma (i)
+       , input_gamma_linearised (il)
+       , matrix (3, 3)
+       , output_gamma (o)
+{
+       for (int i = 0; i < 3; ++i) {
+               for (int j = 0; j < 3; ++j) {
+                       matrix (i, j) = m[i][j];
+               }
+       }
+}
+
+ColourConversion::ColourConversion (shared_ptr<cxml::Node> node)
+       : matrix (3, 3)
+{
+       name = node->string_child ("Name");
+       input_gamma = node->number_child<float> ("InputGamma");
+       input_gamma_linearised = node->bool_child ("InputGammaLinearised");
+
+       for (int i = 0; i < 3; ++i) {
+               for (int j = 0; j < 3; ++j) {
+                       matrix (i, j) = 0;
+               }
+       }
+
+       list<shared_ptr<cxml::Node> > m = node->node_children ("Matrix");
+       for (list<shared_ptr<cxml::Node> >::iterator i = m.begin(); i != m.end(); ++i) {
+               int const ti = (*i)->number_attribute<int> ("i");
+               int const tj = (*i)->number_attribute<int> ("j");
+               matrix(ti, tj) = lexical_cast<float> ((*i)->content ());
+       }
+
+       output_gamma = node->number_child<float> ("OutputGamma");
+}
+
+void
+ColourConversion::as_xml (xmlpp::Node* node) const
+{
+       node->add_child("Name")->add_child_text (name);
+       node->add_child("InputGamma")->add_child_text (lexical_cast<string> (input_gamma));
+       node->add_child("InputGammaLinearised")->add_child_text (input_gamma_linearised ? "1" : "0");
+
+       for (int i = 0; i < 3; ++i) {
+               for (int j = 0; j < 3; ++j) {
+                       xmlpp::Element* m = node->add_child("Matrix");
+                       m->set_attribute ("i", lexical_cast<string> (i));
+                       m->set_attribute ("j", lexical_cast<string> (j));
+                       m->add_child_text (lexical_cast<string> (matrix (i, j)));
+               }
+       }
+
+       node->add_child("OutputGamma")->add_child_text (lexical_cast<string> (output_gamma));
+}
diff --git a/src/lib/colour_conversion.h b/src/lib/colour_conversion.h
new file mode 100644 (file)
index 0000000..ed89f8c
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+    Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+    This program 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.
+
+    This program 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 this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <boost/utility.hpp>
+#include <boost/numeric/ublas/matrix.hpp>
+
+namespace cxml {
+       class Node;
+}
+
+namespace xmlpp {
+       class Node;
+}
+
+class ColourConversion : public boost::noncopyable
+{
+public:
+       ColourConversion ();
+       ColourConversion (std::string, float, bool, float const matrix[3][3], float);
+       ColourConversion (boost::shared_ptr<cxml::Node>);
+
+       void as_xml (xmlpp::Node *) const;
+
+       std::string name;
+       float input_gamma;
+       bool input_gamma_linearised;
+       boost::numeric::ublas::matrix<float> matrix;
+       float output_gamma;
+};
index 29b63b5c8217eb268175692a5f1d52dc11e800af..8f4e5aed02763a204593f22cab98ca4ead60ef11 100644 (file)
@@ -22,6 +22,7 @@
 #include <fstream>
 #include <glib.h>
 #include <boost/filesystem.hpp>
+#include <libdcp/colour_matrix.h>
 #include <libcxml/cxml.h>
 #include "config.h"
 #include "server.h"
@@ -30,6 +31,7 @@
 #include "ratio.h"
 #include "dcp_content_type.h"
 #include "sound_processor.h"
+#include "colour_conversion.h"
 
 #include "i18n.h"
 
@@ -62,6 +64,8 @@ Config::Config ()
        _allowed_dcp_frame_rates.push_back (48);
        _allowed_dcp_frame_rates.push_back (50);
        _allowed_dcp_frame_rates.push_back (60);
+
+       _colour_conversions.push_back (shared_ptr<ColourConversion> (new ColourConversion (_("sRGB"), 2.4, true, libdcp::colour_matrix::xyz_to_rgb, 2.6)));
 }
 
 void
@@ -81,7 +85,7 @@ Config::read ()
        
        list<shared_ptr<cxml::Node> > servers = f.node_children ("Server");
        for (list<shared_ptr<cxml::Node> >::iterator i = servers.begin(); i != servers.end(); ++i) {
-               _servers.push_back (new ServerDescription (*i));
+               _servers.push_back (shared_ptr<ServerDescription> (new ServerDescription (*i)));
        }
 
        _tms_ip = f.string_child ("TMSIP");
@@ -111,7 +115,17 @@ Config::read ()
 
        _default_dci_metadata = DCIMetadata (f.node_child ("DCIMetadata"));
        _default_still_length = f.optional_number_child<int>("DefaultStillLength").get_value_or (10);
-       _default_j2k_bandwidth = f.optional_number_child<int>("DefaultJ2KBandwidth").get_value_or (200000000); 
+       _default_j2k_bandwidth = f.optional_number_child<int>("DefaultJ2KBandwidth").get_value_or (200000000);
+
+       list<shared_ptr<cxml::Node> > cc = f.node_children ("ColourConversion");
+
+       if (!cc.empty ()) {
+               _colour_conversions.clear ();
+       }
+       
+       for (list<shared_ptr<cxml::Node> >::iterator i = cc.begin(); i != cc.end(); ++i) {
+               _colour_conversions.push_back (shared_ptr<ColourConversion> (new ColourConversion (*i)));
+       }
 }
 
 void
@@ -217,7 +231,7 @@ Config::write () const
        root->add_child("DefaultDirectory")->add_child_text (_default_directory);
        root->add_child("ServerPort")->add_child_text (lexical_cast<string> (_server_port));
        
-       for (vector<ServerDescription*>::const_iterator i = _servers.begin(); i != _servers.end(); ++i) {
+       for (vector<shared_ptr<ServerDescription> >::const_iterator i = _servers.begin(); i != _servers.end(); ++i) {
                (*i)->as_xml (root->add_child ("Server"));
        }
 
@@ -245,6 +259,10 @@ Config::write () const
        root->add_child("DefaultStillLength")->add_child_text (lexical_cast<string> (_default_still_length));
        root->add_child("DefaultJ2KBandwidth")->add_child_text (lexical_cast<string> (_default_j2k_bandwidth));
 
+       for (vector<shared_ptr<ColourConversion> >::const_iterator i = _colour_conversions.begin(); i != _colour_conversions.end(); ++i) {
+               (*i)->as_xml (root->add_child ("ColourConversion"));
+       }
+
        doc.write_to_file_formatted (file (false));
 }
 
index 77287e6868a85c0f894708540247d5e099342358..40d06a1721493ab8105b13109c881ec37fd3b19c 100644 (file)
@@ -36,6 +36,7 @@ class Filter;
 class SoundProcessor;
 class DCPContentType;
 class Ratio;
+class ColourConversion;
 
 /** @class Config
  *  @brief A singleton class holding configuration.
@@ -61,7 +62,7 @@ public:
        }
 
        /** @return J2K encoding servers to use */
-       std::vector<ServerDescription*> servers () const {
+       std::vector<boost::shared_ptr<ServerDescription> > servers () const {
                return _servers;
        }
 
@@ -122,6 +123,10 @@ public:
                return _default_j2k_bandwidth;
        }
 
+       std::vector<boost::shared_ptr<ColourConversion> > colour_conversions () const {
+               return _colour_conversions;
+       }
+
        /** @param n New number of local encoding threads */
        void set_num_local_encoding_threads (int n) {
                _num_local_encoding_threads = n;
@@ -137,7 +142,7 @@ public:
        }
 
        /** @param s New list of servers */
-       void set_servers (std::vector<ServerDescription*> s) {
+       void set_servers (std::vector<boost::shared_ptr<ServerDescription> > s) {
                _servers = s;
        }
 
@@ -204,6 +209,10 @@ public:
        void set_default_j2k_bandwidth (int b) {
                _default_j2k_bandwidth = b;
        }
+
+       void set_colour_conversions (std::vector<boost::shared_ptr<ColourConversion> > const & c) {
+               _colour_conversions = c;
+       }
        
        void write () const;
 
@@ -224,7 +233,7 @@ private:
        int _server_port;
 
        /** J2K encoding servers to use */
-       std::vector<ServerDescription *> _servers;
+       std::vector<boost::shared_ptr<ServerDescription> > _servers;
        /** Scaler to use for the "A" part of A/B comparisons */
        Scaler const * _reference_scaler;
        /** Filters to use for the "A" part of A/B comparisons */
@@ -248,6 +257,7 @@ private:
        DCPContentType const * _default_dcp_content_type;
        libdcp::XMLMetadata _dcp_metadata;
        int _default_j2k_bandwidth;
+       std::vector<boost::shared_ptr<ColourConversion> > _colour_conversions;
 
        /** Singleton instance, or 0 */
        static Config* _instance;
index 4f6ff99872e6557733cbad77ad2123f7423155cf..53cf1753a2d7bc117447fa455456b34053b0ae37 100644 (file)
@@ -213,7 +213,7 @@ DCPVideoFrame::encode_locally ()
  *  @return Encoded data.
  */
 shared_ptr<EncodedData>
-DCPVideoFrame::encode_remotely (ServerDescription const * serv)
+DCPVideoFrame::encode_remotely (boost::shared_ptr<const ServerDescription> serv)
 {
        boost::asio::io_service io_service;
        boost::asio::ip::tcp::resolver resolver (io_service);
index 96a773a6fb1c71bf041ad3b81356fc3ecc278fc3..18c8fe628a20e2c1cabb5892ed9bed0d9b615482 100644 (file)
@@ -105,7 +105,7 @@ public:
        DCPVideoFrame (boost::shared_ptr<const Image>, int, Eyes, int, int, boost::shared_ptr<Log>);
 
        boost::shared_ptr<EncodedData> encode_locally ();
-       boost::shared_ptr<EncodedData> encode_remotely (ServerDescription const *);
+       boost::shared_ptr<EncodedData> encode_remotely (boost::shared_ptr<const ServerDescription>);
 
        Eyes eyes () const {
                return _eyes;
index 0c7434220812551e44ef8e4c72601e692538f603..a1c02479936d00fbb2af25f9f81cf04ae35fe539 100644 (file)
@@ -71,12 +71,12 @@ void
 Encoder::process_begin ()
 {
        for (int i = 0; i < Config::instance()->num_local_encoding_threads (); ++i) {
-               _threads.push_back (new boost::thread (boost::bind (&Encoder::encoder_thread, this, (ServerDescription *) 0)));
+               _threads.push_back (new boost::thread (boost::bind (&Encoder::encoder_thread, this, shared_ptr<ServerDescription> ())));
        }
 
-       vector<ServerDescription*> servers = Config::instance()->servers ();
+       vector<shared_ptr<ServerDescription> > servers = Config::instance()->servers ();
 
-       for (vector<ServerDescription*>::iterator i = servers.begin(); i != servers.end(); ++i) {
+       for (vector<shared_ptr<ServerDescription> >::iterator i = servers.begin(); i != servers.end(); ++i) {
                for (int j = 0; j < (*i)->threads (); ++j) {
                        _threads.push_back (new boost::thread (boost::bind (&Encoder::encoder_thread, this, *i)));
                }
@@ -244,7 +244,7 @@ Encoder::terminate_threads ()
 }
 
 void
-Encoder::encoder_thread (ServerDescription* server)
+Encoder::encoder_thread (shared_ptr<ServerDescription> server)
 {
        /* Number of seconds that we currently wait between attempts
           to connect to the server; not relevant for localhost
index a866a77f19c43998e0f96572e5a71a80d657861e..a4df202a21e6758da1cffb35dff53f0c73e3fcd0 100644 (file)
@@ -81,7 +81,7 @@ private:
        
        void frame_done ();
        
-       void encoder_thread (ServerDescription *);
+       void encoder_thread (boost::shared_ptr<ServerDescription>);
        void terminate_threads ();
 
        /** Film that we are encoding */
index 37a076a5485d55e6174e3e7355a74027b049bfc9..54cffc0774b0ed1a64d6c3e3873c7d0054806843 100644 (file)
@@ -68,17 +68,17 @@ ServerDescription::as_xml (xmlpp::Node* root) const
  *  @param v Metadata.
  *  @return ServerDescription, or 0.
  */
-ServerDescription *
+shared_ptr<ServerDescription>
 ServerDescription::create_from_metadata (string v)
 {
        vector<string> b;
        split (b, v, is_any_of (N_(" ")));
 
        if (b.size() != 2) {
-               return 0;
+               return shared_ptr<ServerDescription> ();
        }
 
-       return new ServerDescription (b[0], atoi (b[1].c_str ()));
+       return shared_ptr<ServerDescription> (new ServerDescription (b[0], atoi (b[1].c_str ())));
 }
 
 Server::Server (shared_ptr<Log> log)
index e6d3743691e09cc2b3054300e8683031b5534ea1..6307c1867686575fe3ac99ba9e13e0eaf5f2c238 100644 (file)
@@ -41,6 +41,11 @@ namespace cxml {
 class ServerDescription
 {
 public:
+       ServerDescription ()
+               : _host_name ("")
+               , _threads (1)
+       {}
+       
        /** @param h Server host name or IP address in string form.
         *  @param t Number of threads to use on the server.
         */
@@ -73,7 +78,7 @@ public:
 
        void as_xml (xmlpp::Node *) const;
        
-       static ServerDescription * create_from_metadata (std::string v);
+       static boost::shared_ptr<ServerDescription> create_from_metadata (std::string v);
 
 private:
        /** server's host name */
index 04dae7587403a29608d8163dd8ccc12b5d54921a..6c45d8b1ed3cdf5d4731f444385b9e6a8f733400 100644 (file)
@@ -8,6 +8,7 @@ sources = """
           audio_content.cc
           audio_decoder.cc
           audio_mapping.cc
+          colour_conversion.cc
           config.cc
           content.cc
           content_factory.cc
index 7c5852fcc5054e61de99805b8eb465317733e4b3..ff7ab6ffe59446f74a0628733b7a1768e8058e5d 100644 (file)
@@ -116,7 +116,7 @@ main (int argc, char* argv[])
        dcpomatic_setup ();
 
        if (no_remote) {
-               Config::instance()->set_servers (vector<ServerDescription*> ());
+               Config::instance()->set_servers (vector<shared_ptr<ServerDescription> > ());
        }
 
        cout << "DCP-o-matic " << dcpomatic_version << " git " << dcpomatic_git_commit;
diff --git a/src/wx/colour_conversion_dialog.cc b/src/wx/colour_conversion_dialog.cc
new file mode 100644 (file)
index 0000000..976d295
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+    Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+    This program 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.
+
+    This program 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 this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <boost/lexical_cast.hpp>
+#include <wx/spinctrl.h>
+#include <wx/gbsizer.h>
+#include "lib/colour_conversion.h"
+#include "wx_util.h"
+#include "colour_conversion_dialog.h"
+
+using std::string;
+using std::cout;
+using boost::shared_ptr;
+using boost::lexical_cast;
+
+ColourConversionDialog::ColourConversionDialog (wxWindow* parent, shared_ptr<ColourConversion> conversion)
+       : wxDialog (parent, wxID_ANY, _("Colour conversion"))
+       , _conversion (conversion)
+{
+       wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL);
+       SetSizer (overall_sizer);
+
+       wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
+       overall_sizer->Add (table, 1, wxEXPAND | wxALL, DCPOMATIC_DIALOG_BORDER);
+
+       int r = 0;
+
+       add_label_to_grid_bag_sizer (table, this, _("Name"), true, wxGBPosition (r, 0));
+       _name = new wxTextCtrl (this, wxID_ANY, wxT (""));
+       table->Add (_name, wxGBPosition (r, 1));
+       ++r;
+
+       add_label_to_grid_bag_sizer (table, this, _("Input gamma"), true, wxGBPosition (r, 0));
+       _input_gamma = new wxSpinCtrlDouble (this);
+       table->Add (_input_gamma, wxGBPosition (r, 1));
+       ++r;
+
+       _input_gamma_linearised = new wxCheckBox (this, wxID_ANY, _("Linearise input gamma curve for low values"));
+       table->Add (_input_gamma_linearised, wxGBPosition (r, 0), wxGBSpan (1, 2));
+       ++r;
+
+        wxClientDC dc (parent);
+        wxSize size = dc.GetTextExtent (wxT ("0.123456789012"));
+        size.SetHeight (-1);
+
+        wxTextValidator validator (wxFILTER_INCLUDE_CHAR_LIST);
+        wxArrayString list;
+
+        wxString n (wxT ("0123456789.-"));
+        for (size_t i = 0; i < n.Length(); ++i) {
+                list.Add (n[i]);
+        }
+
+        validator.SetIncludes (list);
+
+       add_label_to_grid_bag_sizer (table, this, _("Matrix"), true, wxGBPosition (r, 0));
+       wxFlexGridSizer* matrix_sizer = new wxFlexGridSizer (3, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
+       for (int x = 0; x < 3; ++x) {
+               for (int y = 0; y < 3; ++y) {
+                       _matrix[x][y] = new wxTextCtrl (this, wxID_ANY, wxT (""), wxDefaultPosition, size, 0, validator);
+                       matrix_sizer->Add (_matrix[x][y]);
+               }
+       }
+       table->Add (matrix_sizer, wxGBPosition (r, 1));
+       ++r;
+
+       add_label_to_grid_bag_sizer (table, this, _("Output gamma"), true, wxGBPosition (r, 0));
+       wxBoxSizer* output_sizer = new wxBoxSizer (wxHORIZONTAL);
+       /* TRANSLATORS: this means the mathematical reciprocal operation, i.e. we are dividing 1 by the control that
+          comes after it.
+       */
+       add_label_to_sizer (output_sizer, this, _("1 / "), false);
+       _output_gamma = new wxSpinCtrlDouble (this);
+       output_sizer->Add (_output_gamma);
+       table->Add (output_sizer, wxGBPosition (r, 1));
+       ++r;
+
+       wxSizer* buttons = CreateSeparatedButtonSizer (wxOK);
+       if (buttons) {
+               overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
+       }
+
+       SetSizer (overall_sizer);
+       overall_sizer->Layout ();
+       overall_sizer->SetSizeHints (this);
+
+       _input_gamma->SetRange(0.1, 4.0);
+       _input_gamma->SetDigits (1);
+       _input_gamma->SetIncrement (0.1);
+       _output_gamma->SetRange(0.1, 4.0);
+       _output_gamma->SetDigits (1);
+       _output_gamma->SetIncrement (0.1);
+
+       _name->SetValue (std_to_wx (conversion->name));
+       _input_gamma->SetValue (conversion->input_gamma);
+       _input_gamma_linearised->SetValue (conversion->input_gamma_linearised);
+       for (int i = 0; i < 3; ++i) {
+               for (int j = 0; j < 3; ++j) {
+                       _matrix[i][j]->SetValue (std_to_wx (lexical_cast<string> (conversion->matrix(i, j))));
+               }
+       }
+       _output_gamma->SetValue (conversion->output_gamma);
+
+       _name->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&ColourConversionDialog::changed, this));
+       _input_gamma->Bind (wxEVT_COMMAND_SPINCTRLDOUBLE_UPDATED, boost::bind (&ColourConversionDialog::changed, this));
+       _input_gamma_linearised->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&ColourConversionDialog::changed, this));
+       _output_gamma->Bind (wxEVT_COMMAND_SPINCTRLDOUBLE_UPDATED, boost::bind (&ColourConversionDialog::changed, this));
+       for (int i = 0; i < 3; ++i) {
+               for (int j = 0; j < 3; ++j) {
+                       _matrix[i][j]->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&ColourConversionDialog::changed, this));
+               }
+       }
+}
+
+void
+ColourConversionDialog::changed ()
+{
+       _conversion->name = wx_to_std (_name->GetValue ());
+       _conversion->input_gamma = _input_gamma->GetValue ();
+       _conversion->input_gamma_linearised = _input_gamma_linearised->GetValue ();
+
+       for (int i = 0; i < 3; ++i) {
+               for (int j = 0; j < 3; ++j) {
+                       string const v = wx_to_std (_matrix[i][j]->GetValue ());
+                       if (v.empty ()) {
+                               _conversion->matrix (i, j) = 0;
+                       } else {
+                               _conversion->matrix (i, j) = lexical_cast<float> (v);
+                       }
+               }
+       }
+       _conversion->output_gamma = _output_gamma->GetValue ();
+}
+       
diff --git a/src/wx/colour_conversion_dialog.h b/src/wx/colour_conversion_dialog.h
new file mode 100644 (file)
index 0000000..8da6df1
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+    Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+    This program 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.
+
+    This program 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 this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <wx/wx.h>
+
+class wxSpinCtrlDouble;
+class ColourConversion;
+
+class ColourConversionDialog : public wxDialog
+{
+public:
+       ColourConversionDialog (wxWindow *, boost::shared_ptr<ColourConversion>);
+
+private:
+       void changed ();
+       
+       boost::shared_ptr<ColourConversion> _conversion;
+       wxTextCtrl* _name;
+       wxSpinCtrlDouble* _input_gamma;
+       wxCheckBox* _input_gamma_linearised;
+       wxTextCtrl* _matrix[3][3];
+       wxSpinCtrlDouble* _output_gamma;
+};
index cbcae78f88fcf69c486b826fd56d38444cb5d4ed..66f0cd186b99a42317f25636ff6346f22a7f5788 100644 (file)
 #include <boost/filesystem.hpp>
 #include <wx/stdpaths.h>
 #include <wx/notebook.h>
+#include <libdcp/colour_matrix.h>
 #include "lib/config.h"
 #include "lib/server.h"
 #include "lib/ratio.h"
 #include "lib/scaler.h"
 #include "lib/filter.h"
 #include "lib/dcp_content_type.h"
+#include "lib/colour_conversion.h"
 #include "config_dialog.h"
 #include "wx_util.h"
 #include "filter_dialog.h"
 #include "server_dialog.h"
 #include "dir_picker_ctrl.h"
 #include "dci_metadata_dialog.h"
+#include "colour_conversion_dialog.h"
 
-using namespace std;
+using std::vector;
+using std::string;
+using std::list;
 using boost::bind;
+using boost::shared_ptr;
+using boost::lexical_cast;
 
 ConfigDialog::ConfigDialog (wxWindow* parent)
        : wxDialog (parent, wxID_ANY, _("DCP-o-matic Preferences"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
@@ -53,6 +60,8 @@ ConfigDialog::ConfigDialog (wxWindow* parent)
        _notebook->AddPage (_misc_panel, _("Miscellaneous"), true);
        make_servers_panel ();
        _notebook->AddPage (_servers_panel, _("Encoding servers"), false);
+       make_colour_conversions_panel ();
+       _notebook->AddPage (_colour_conversions_panel, _("Colour conversions"), false);
        make_metadata_panel ();
        _notebook->AddPage (_metadata_panel, _("Metadata"), false);
        make_tms_panel ();
@@ -270,54 +279,32 @@ ConfigDialog::make_metadata_panel ()
        _creator->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&ConfigDialog::creator_changed, this));
 }
 
-void
-ConfigDialog::make_servers_panel ()
+static std::string
+server_column (shared_ptr<ServerDescription> s, int c)
 {
-       _servers_panel = new wxPanel (_notebook);
-       wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
-       _servers_panel->SetSizer (s);
-
-       wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
-       table->AddGrowableCol (0, 1);
-       s->Add (table, 1, wxALL | wxEXPAND, 8);
-
-       Config* config = Config::instance ();
-
-       _servers = new wxListCtrl (_servers_panel, wxID_ANY, wxDefaultPosition, wxSize (220, 100), wxLC_REPORT | wxLC_SINGLE_SEL);
-       wxListItem ip;
-       ip.SetId (0);
-       ip.SetText (_("IP address"));
-       ip.SetWidth (120);
-       _servers->InsertColumn (0, ip);
-       ip.SetId (1);
-       ip.SetText (_("Threads"));
-       ip.SetWidth (80);
-       _servers->InsertColumn (1, ip);
-       table->Add (_servers, 1, wxEXPAND | wxALL);
-
-       {
-               wxSizer* s = new wxBoxSizer (wxVERTICAL);
-               _add_server = new wxButton (_servers_panel, wxID_ANY, _("Add"));
-               s->Add (_add_server, 0, wxTOP | wxBOTTOM, 2);
-               _edit_server = new wxButton (_servers_panel, wxID_ANY, _("Edit"));
-               s->Add (_edit_server, 0, wxTOP | wxBOTTOM, 2);
-               _remove_server = new wxButton (_servers_panel, wxID_ANY, _("Remove"));
-               s->Add (_remove_server, 0, wxTOP | wxBOTTOM, 2);
-               table->Add (s, 0);
+       switch (c) {
+       case 0:
+               return s->host_name ();
+       case 1:
+               return lexical_cast<string> (s->threads ());
        }
 
-       vector<ServerDescription*> servers = config->servers ();
-       for (vector<ServerDescription*>::iterator i = servers.begin(); i != servers.end(); ++i) {
-               add_server_to_control (*i);
-       }
-       
-       _add_server->Bind    (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&ConfigDialog::add_server_clicked,    this));
-       _edit_server->Bind   (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&ConfigDialog::edit_server_clicked,   this));
-       _remove_server->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&ConfigDialog::remove_server_clicked, this));
+       return "";
+}
 
-       _servers->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED,   boost::bind (&ConfigDialog::server_selection_changed, this));
-       _servers->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&ConfigDialog::server_selection_changed, this));
-       server_selection_changed ();
+void
+ConfigDialog::make_servers_panel ()
+{
+       vector<string> columns;
+       columns.push_back (wx_to_std (_("IP address")));
+       columns.push_back (wx_to_std (_("Threads")));
+       _servers_panel = new EditableList<ServerDescription, ServerDialog> (
+               _notebook,
+               columns,
+               boost::bind (&Config::servers, Config::instance()),
+               boost::bind (&Config::set_servers, Config::instance(), _1),
+               boost::bind (&server_column, _1, _2)
+               );
 }
 
 void
@@ -378,76 +365,6 @@ ConfigDialog::default_directory_changed ()
        Config::instance()->set_default_directory (wx_to_std (_default_directory->GetPath ()));
 }
 
-void
-ConfigDialog::add_server_to_control (ServerDescription* s)
-{
-       wxListItem item;
-       int const n = _servers->GetItemCount ();
-       item.SetId (n);
-       _servers->InsertItem (item);
-       _servers->SetItem (n, 0, std_to_wx (s->host_name ()));
-       _servers->SetItem (n, 1, std_to_wx (boost::lexical_cast<string> (s->threads ())));
-}
-
-void
-ConfigDialog::add_server_clicked ()
-{
-       ServerDialog* d = new ServerDialog (this, 0);
-       d->ShowModal ();
-       ServerDescription* s = d->server ();
-       d->Destroy ();
-       
-       add_server_to_control (s);
-       vector<ServerDescription*> o = Config::instance()->servers ();
-       o.push_back (s);
-       Config::instance()->set_servers (o);
-}
-
-void
-ConfigDialog::edit_server_clicked ()
-{
-       int i = _servers->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
-       if (i == -1) {
-               return;
-       }
-
-       wxListItem item;
-       item.SetId (i);
-       item.SetColumn (0);
-       _servers->GetItem (item);
-
-       vector<ServerDescription*> servers = Config::instance()->servers ();
-       assert (i >= 0 && i < int (servers.size ()));
-
-       ServerDialog* d = new ServerDialog (this, servers[i]);
-       d->ShowModal ();
-       d->Destroy ();
-
-       _servers->SetItem (i, 0, std_to_wx (servers[i]->host_name ()));
-       _servers->SetItem (i, 1, std_to_wx (boost::lexical_cast<string> (servers[i]->threads ())));
-}
-
-void
-ConfigDialog::remove_server_clicked ()
-{
-       int i = _servers->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
-       if (i >= 0) {
-               _servers->DeleteItem (i);
-       }
-
-       vector<ServerDescription*> o = Config::instance()->servers ();
-       o.erase (o.begin() + i);
-       Config::instance()->set_servers (o);
-}
-
-void
-ConfigDialog::server_selection_changed ()
-{
-       int const i = _servers->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
-       _edit_server->Enable (i >= 0);
-       _remove_server->Enable (i >= 0);
-}
-
 void
 ConfigDialog::edit_default_dci_metadata_clicked ()
 {
@@ -515,3 +432,23 @@ ConfigDialog::default_j2k_bandwidth_changed ()
 {
        Config::instance()->set_default_j2k_bandwidth (_default_j2k_bandwidth->GetValue() * 1e6);
 }
+
+static std::string
+colour_conversion_column (shared_ptr<ColourConversion> c)
+{
+       return c->name;
+}
+
+void
+ConfigDialog::make_colour_conversions_panel ()
+{
+       vector<string> columns;
+       columns.push_back (wx_to_std (_("Name")));
+       _colour_conversions_panel = new EditableList<ColourConversion, ColourConversionDialog> (
+               _notebook,
+               columns,
+               boost::bind (&Config::colour_conversions, Config::instance()),
+               boost::bind (&Config::set_colour_conversions, Config::instance(), _1),
+               boost::bind (&colour_conversion_column, _1)
+               );
+}
index 444b886f475a49b822ecde38402ee53501821bb6..60d9229c46ab63650c2ad6c5a4f909976f474bcc 100644 (file)
 #include <wx/listctrl.h>
 #include <wx/filepicker.h>
 #include "wx_util.h"
+#include "editable_list.h"
 
 class DirPickerCtrl;
 class wxNotebook;
-
 class ServerDescription;
+class ColourConversion;
+class ColourConversionDialog;
+class ServerDialog;
 
 /** @class ConfigDialog
  *  @brief A dialogue to edit DCP-o-matic configuration.
@@ -51,28 +54,25 @@ private:
        void default_still_length_changed ();
        void default_directory_changed ();
        void edit_default_dci_metadata_clicked ();
-       void add_server_clicked ();
-       void edit_server_clicked ();
-       void remove_server_clicked ();
-       void server_selection_changed ();
        void default_container_changed ();
        void default_dcp_content_type_changed ();
        void issuer_changed ();
        void creator_changed ();
        void default_j2k_bandwidth_changed ();
 
-       void add_server_to_control (ServerDescription *);
        void setup_language_sensitivity ();
 
        void make_misc_panel ();
        void make_tms_panel ();
        void make_metadata_panel ();
        void make_servers_panel ();
+       void make_colour_conversions_panel ();
 
        wxNotebook* _notebook;
        wxPanel* _misc_panel;
        wxPanel* _tms_panel;
-       wxPanel* _servers_panel;
+       EditableList<ColourConversion, ColourConversionDialog>* _colour_conversions_panel;
+       EditableList<ServerDescription, ServerDialog>* _servers_panel;
        wxPanel* _metadata_panel;
        wxCheckBox* _set_language;
        wxChoice* _language;
@@ -90,10 +90,6 @@ private:
        wxDirPickerCtrl* _default_directory;
 #endif
        wxButton* _default_dci_metadata_button;
-       wxListCtrl* _servers;
-       wxButton* _add_server;
-       wxButton* _edit_server;
-       wxButton* _remove_server;
        wxTextCtrl* _issuer;
        wxTextCtrl* _creator;
        wxSpinCtrl* _default_j2k_bandwidth;
diff --git a/src/wx/editable_list.h b/src/wx/editable_list.h
new file mode 100644 (file)
index 0000000..32cc326
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+
+    This program 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.
+
+    This program 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 this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <wx/wx.h>
+
+template<class T, class S>
+class EditableList : public wxPanel
+{
+public:
+       EditableList (
+               wxWindow* parent,
+               std::vector<std::string> columns,
+               boost::function<std::vector<boost::shared_ptr<T> > ()> get,
+               boost::function<void (std::vector<boost::shared_ptr<T> >)> set,
+               boost::function<std::string (boost::shared_ptr<T>, int)> column
+               )
+               : wxPanel (parent)
+               , _get (get)
+               , _set (set)
+               , _columns (columns.size ())
+               , _column (column)
+       {
+               wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
+               SetSizer (s);
+
+               wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
+               table->AddGrowableCol (0, 1);
+               s->Add (table, 1, wxALL | wxEXPAND, 8);
+
+               _list = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (columns.size() * 200, 100), wxLC_REPORT | wxLC_SINGLE_SEL);
+
+               for (size_t i = 0; i < columns.size(); ++i) {
+                       wxListItem ip;
+                       ip.SetId (i);
+                       ip.SetText (std_to_wx (columns[i]));
+                       ip.SetWidth (200);
+                       _list->InsertColumn (i, ip);
+               }
+
+               table->Add (_list, 1, wxEXPAND | wxALL);
+
+               {
+                       wxSizer* s = new wxBoxSizer (wxVERTICAL);
+                       _add = new wxButton (this, wxID_ANY, _("Add..."));
+                       s->Add (_add, 0, wxTOP | wxBOTTOM, 2);
+                       _edit = new wxButton (this, wxID_ANY, _("Edit..."));
+                       s->Add (_edit, 0, wxTOP | wxBOTTOM, 2);
+                       _remove = new wxButton (this, wxID_ANY, _("Remove"));
+                       s->Add (_remove, 0, wxTOP | wxBOTTOM, 2);
+                       table->Add (s, 0);
+               }
+
+               std::vector<boost::shared_ptr<T> > current = _get ();
+               for (typename std::vector<boost::shared_ptr<T> >::iterator i = current.begin (); i != current.end(); ++i) {
+                       add_to_control (*i);
+               }
+
+               _add->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&EditableList::add_clicked, this));
+               _edit->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&EditableList::edit_clicked, this));
+               _remove->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&EditableList::remove_clicked, this));
+
+               _list->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&EditableList::selection_changed, this));
+               _list->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&EditableList::selection_changed, this));
+               selection_changed ();
+       }
+
+       void add_to_control (boost::shared_ptr<T> item)
+       {
+               wxListItem list_item;
+               int const n = _list->GetItemCount ();
+               list_item.SetId (n);
+               _list->InsertItem (list_item);
+
+               for (int i = 0; i < _columns; ++i) {
+                       _list->SetItem (n, i, std_to_wx (_column (item, i)));
+               }
+       }
+
+       void selection_changed ()
+       {
+               int const i = _list->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+               _edit->Enable (i >= 0);
+               _remove->Enable (i >= 0);
+       }
+
+       void add_clicked ()
+       {
+               boost::shared_ptr<T> new_item (new T);
+               S* dialog = new S (this, new_item);
+               dialog->ShowModal ();
+               dialog->Destroy ();
+
+               add_to_control (new_item);
+               std::vector<boost::shared_ptr<T> > all = _get ();
+               all.push_back (new_item);
+               _set (all);
+       }
+
+       void edit_clicked ()
+       {
+               int item = _list->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+               if (item == -1) {
+                       return;
+               }
+
+               std::vector<boost::shared_ptr<T> > all = _get ();
+               assert (item >= 0 && item < int (all.size ()));
+
+               S* dialog = new S (this, all[item]);
+               dialog->ShowModal ();
+               dialog->Destroy ();
+
+               for (int i = 0; i < _columns; ++i) {
+                       _list->SetItem (item, i, std_to_wx (_column (all[item], i)));
+               }
+       }
+
+       void remove_clicked ()
+       {
+               int i = _list->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+               if (i >= 0) {
+                       _list->DeleteItem (i);
+               }
+               
+               std::vector<boost::shared_ptr<T> > all = _get ();
+               all.erase (all.begin() + i);
+               _set (all);
+       }
+
+private:       
+       boost::function <std::vector<boost::shared_ptr<T> > ()> _get;
+       boost::function <void (std::vector<boost::shared_ptr<T> >)> _set;
+       int _columns;
+       boost::function<std::string (boost::shared_ptr<T>, int)> _column;
+
+       wxButton* _add;
+       wxButton* _edit;
+       wxButton* _remove;
+       wxListCtrl* _list;
+};
index 0f41b5b90f751b57793622885e5e4752899e7911..a0f1f04aea49098fd53492d270d9f4a452c686cd 100644 (file)
 #include "server_dialog.h"
 #include "wx_util.h"
 
-ServerDialog::ServerDialog (wxWindow* parent, ServerDescription* server)
+using boost::shared_ptr;
+
+ServerDialog::ServerDialog (wxWindow* parent, shared_ptr<ServerDescription> server)
        : wxDialog (parent, wxID_ANY, _("Server"))
 {
        if (server) {
                _server = server;
        } else {
-               _server = new ServerDescription (wx_to_std (N_("localhost")), 1);
+               _server.reset (new ServerDescription (wx_to_std (N_("localhost")), 1));
        }
                
        wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
@@ -73,7 +75,7 @@ ServerDialog::threads_changed ()
        _server->set_threads (_threads->GetValue ());
 }
 
-ServerDescription *
+shared_ptr<ServerDescription>
 ServerDialog::server () const
 {
        return _server;
index f42236771efbb6e3a7f7c5d34c0865b2f6f4ac12..3f1fa1f73021fb32bbc3c20d7e312163116326e1 100644 (file)
@@ -25,15 +25,15 @@ class ServerDescription;
 class ServerDialog : public wxDialog
 {
 public:
-       ServerDialog (wxWindow *, ServerDescription *);
+       ServerDialog (wxWindow *, boost::shared_ptr<ServerDescription>);
 
-       ServerDescription* server () const;
+       boost::shared_ptr<ServerDescription> server () const;
 
 private:
        void host_changed ();
        void threads_changed ();
 
-       ServerDescription* _server;
+       boost::shared_ptr<ServerDescription> _server;
        wxTextCtrl* _host;
        wxSpinCtrl* _threads;
 };
index 0c27029133e1a4913934011981b9d6e1e2691b5e..5ba06b12d45196fe41bc4e9577d0f4a3ceb19f57 100644 (file)
@@ -21,6 +21,8 @@
 #include "lib/ratio.h"
 #include "lib/filter.h"
 #include "lib/ffmpeg_content.h"
+#include "lib/colour_conversion.h"
+#include "lib/config.h"
 #include "filter_dialog.h"
 #include "video_panel.h"
 #include "wx_util.h"
@@ -30,6 +32,7 @@ using std::vector;
 using std::string;
 using std::pair;
 using std::cout;
+using std::list;
 using boost::shared_ptr;
 using boost::dynamic_pointer_cast;
 using boost::bind;
@@ -83,6 +86,11 @@ VideoPanel::VideoPanel (FilmEditor* e)
        }
        ++r;
 
+       add_label_to_grid_bag_sizer (grid, this, _("Colour conversion"), true, wxGBPosition (r, 0));
+       _colour_conversion = new wxChoice (this, wxID_ANY);
+       grid->Add (_colour_conversion, wxGBPosition (r, 1));
+       ++r;
+
        _description = new wxStaticText (this, wxID_ANY, wxT ("\n \n \n \n \n"), wxDefaultPosition, wxDefaultSize);
        grid->Add (_description, wxGBPosition (r, 0), wxGBSpan (1, 2), wxEXPAND | wxALIGN_CENTER_VERTICAL | wxALL, 6);
        wxFont font = _description->GetFont();
@@ -105,13 +113,16 @@ VideoPanel::VideoPanel (FilmEditor* e)
        _frame_type->Append (_("2D"));
        _frame_type->Append (_("3D left/right"));
 
-       _frame_type->Bind     (wxEVT_COMMAND_CHOICE_SELECTED,  boost::bind (&VideoPanel::frame_type_changed, this));
-       _left_crop->Bind      (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&VideoPanel::left_crop_changed, this));
-       _right_crop->Bind     (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&VideoPanel::right_crop_changed, this));
-       _top_crop->Bind       (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&VideoPanel::top_crop_changed, this));
-       _bottom_crop->Bind    (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&VideoPanel::bottom_crop_changed, this));
-       _ratio->Bind          (wxEVT_COMMAND_CHOICE_SELECTED,  boost::bind (&VideoPanel::ratio_changed, this));
-       _filters_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED,   boost::bind (&VideoPanel::edit_filters_clicked, this));
+       setup_colour_conversions ();
+
+       _frame_type->Bind        (wxEVT_COMMAND_CHOICE_SELECTED,  boost::bind (&VideoPanel::frame_type_changed, this));
+       _left_crop->Bind         (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&VideoPanel::left_crop_changed, this));
+       _right_crop->Bind        (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&VideoPanel::right_crop_changed, this));
+       _top_crop->Bind          (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&VideoPanel::top_crop_changed, this));
+       _bottom_crop->Bind       (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&VideoPanel::bottom_crop_changed, this));
+       _ratio->Bind             (wxEVT_COMMAND_CHOICE_SELECTED,  boost::bind (&VideoPanel::ratio_changed, this));
+       _filters_button->Bind    (wxEVT_COMMAND_BUTTON_CLICKED,   boost::bind (&VideoPanel::edit_filters_clicked, this));
+       _colour_conversion->Bind (wxEVT_COMMAND_CHOICE_SELECTED,  boost::bind (&VideoPanel::colour_conversion_changed, this));
 }
 
 
@@ -342,3 +353,18 @@ VideoPanel::frame_type_changed ()
                vc->set_video_frame_type (static_cast<VideoFrameType> (_frame_type->GetSelection ()));
        }
 }
+
+void
+VideoPanel::setup_colour_conversions ()
+{
+       vector<shared_ptr<ColourConversion> > cc = Config::instance()->colour_conversions ();
+       for (vector<shared_ptr<ColourConversion> >::iterator i = cc.begin(); i != cc.end(); ++i) {
+               _colour_conversion->Append (std_to_wx ((*i)->name));
+       }
+}
+
+void
+VideoPanel::colour_conversion_changed ()
+{
+
+}
index 5a22811505239289ef4cd016de58cad6f9ccf424..62332a0520ae13c8985638c26f22a4e5f6eefcf1 100644 (file)
@@ -41,8 +41,10 @@ private:
        void edit_filters_clicked ();
        void ratio_changed ();
        void frame_type_changed ();
+       void colour_conversion_changed ();
 
        void setup_description ();
+       void setup_colour_conversions ();
 
        wxChoice* _frame_type;
        wxSpinCtrl* _left_crop;
@@ -54,4 +56,5 @@ private:
        wxStaticText* _description;
        wxStaticText* _filters;
        wxButton* _filters_button;
+       wxChoice* _colour_conversion;
 };
index 883304effb68e8e3556bbb57eed1ce2e382d6799..e0566a6ed8deeb138ff57b238df01c43702fa40a 100644 (file)
@@ -9,6 +9,7 @@ sources = """
           audio_mapping_view.cc
           audio_panel.cc
           audio_plot.cc
+          colour_conversion_dialog.cc
           config_dialog.cc
           content_menu.cc
           dci_metadata_dialog.cc
index 2dc1545d603dd48192299276800f3f7977fd3dd5..d695f96ce182b3f15cba8a57d69836b83e2311e2 100644 (file)
@@ -29,7 +29,7 @@ using boost::shared_ptr;
 using boost::thread;
 
 void
-do_remote_encode (shared_ptr<DCPVideoFrame> frame, ServerDescription* description, shared_ptr<EncodedData> locally_encoded)
+do_remote_encode (shared_ptr<DCPVideoFrame> frame, shared_ptr<ServerDescription> description, shared_ptr<EncodedData> locally_encoded)
 {
        shared_ptr<EncodedData> remotely_encoded;
        BOOST_CHECK_NO_THROW (remotely_encoded = frame->encode_remotely (description));
@@ -92,11 +92,11 @@ BOOST_AUTO_TEST_CASE (client_server_test)
        /* Let the server get itself ready */
        dcpomatic_sleep (1);
 
-       ServerDescription description ("localhost", 2);
+       shared_ptr<ServerDescription> description (new ServerDescription ("localhost", 2));
 
        list<thread*> threads;
        for (int i = 0; i < 8; ++i) {
-               threads.push_back (new thread (boost::bind (do_remote_encode, frame, &description, locally_encoded)));
+               threads.push_back (new thread (boost::bind (do_remote_encode, frame, description, locally_encoded)));
        }
 
        for (list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i) {
index 2334523a1337696f74e271bec138503159343fb1..21cf18c76e82678e8495c22d8849670344a06a7c 100644 (file)
@@ -46,7 +46,7 @@ struct TestConfig
                dcpomatic_setup();
 
                Config::instance()->set_num_local_encoding_threads (1);
-               Config::instance()->set_servers (vector<ServerDescription*> ());
+               Config::instance()->set_servers (vector<shared_ptr<ServerDescription> > ());
                Config::instance()->set_server_port (61920);
                Config::instance()->set_default_dci_metadata (DCIMetadata ());
                Config::instance()->set_default_container (static_cast<Ratio*> (0));