--- /dev/null
+/*
+ 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));
+}
--- /dev/null
+/*
+ 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;
+};
#include <fstream>
#include <glib.h>
#include <boost/filesystem.hpp>
+#include <libdcp/colour_matrix.h>
#include <libcxml/cxml.h>
#include "config.h"
#include "server.h"
#include "ratio.h"
#include "dcp_content_type.h"
#include "sound_processor.h"
+#include "colour_conversion.h"
#include "i18n.h"
_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
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");
_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
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"));
}
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));
}
class SoundProcessor;
class DCPContentType;
class Ratio;
+class ColourConversion;
/** @class Config
* @brief A singleton class holding configuration.
}
/** @return J2K encoding servers to use */
- std::vector<ServerDescription*> servers () const {
+ std::vector<boost::shared_ptr<ServerDescription> > servers () const {
return _servers;
}
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;
}
/** @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;
}
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;
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 */
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;
* @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);
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;
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)));
}
}
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
void frame_done ();
- void encoder_thread (ServerDescription *);
+ void encoder_thread (boost::shared_ptr<ServerDescription>);
void terminate_threads ();
/** Film that we are encoding */
* @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)
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.
*/
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 */
audio_content.cc
audio_decoder.cc
audio_mapping.cc
+ colour_conversion.cc
config.cc
content.cc
content_factory.cc
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;
--- /dev/null
+/*
+ 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 ();
+}
+
--- /dev/null
+/*
+ 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;
+};
#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)
_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 ();
_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
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 ()
{
{
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)
+ );
+}
#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.
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;
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;
--- /dev/null
+/*
+ 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;
+};
#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);
_server->set_threads (_threads->GetValue ());
}
-ServerDescription *
+shared_ptr<ServerDescription>
ServerDialog::server () const
{
return _server;
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;
};
#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"
using std::string;
using std::pair;
using std::cout;
+using std::list;
using boost::shared_ptr;
using boost::dynamic_pointer_cast;
using boost::bind;
}
++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();
_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));
}
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 ()
+{
+
+}
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;
wxStaticText* _description;
wxStaticText* _filters;
wxButton* _filters_button;
+ wxChoice* _colour_conversion;
};
audio_mapping_view.cc
audio_panel.cc
audio_plot.cc
+ colour_conversion_dialog.cc
config_dialog.cc
content_menu.cc
dci_metadata_dialog.cc
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));
/* 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) {
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));