summaryrefslogtreecommitdiff
path: root/src/wx
diff options
context:
space:
mode:
Diffstat (limited to 'src/wx')
-rw-r--r--src/wx/audio_dialog.cc54
-rw-r--r--src/wx/audio_dialog.h1
-rw-r--r--src/wx/audio_mapping_view.cc174
-rw-r--r--src/wx/audio_mapping_view.h41
-rw-r--r--src/wx/audio_plot.cc5
-rw-r--r--src/wx/config_dialog.cc100
-rw-r--r--src/wx/config_dialog.h6
-rw-r--r--src/wx/film_editor.cc1363
-rw-r--r--src/wx/film_editor.h138
-rw-r--r--src/wx/film_viewer.cc168
-rw-r--r--src/wx/film_viewer.h29
-rw-r--r--src/wx/imagemagick_content_dialog.cc72
-rw-r--r--src/wx/imagemagick_content_dialog.h38
-rw-r--r--src/wx/job_manager_view.cc23
-rw-r--r--src/wx/job_manager_view.h1
-rw-r--r--src/wx/po/es_ES.po20
-rw-r--r--src/wx/po/fr_FR.po19
-rw-r--r--src/wx/po/it_IT.po22
-rw-r--r--src/wx/po/sv_SE.po24
-rw-r--r--src/wx/properties_dialog.cc21
-rw-r--r--src/wx/timecode.cc115
-rw-r--r--src/wx/timecode.h43
-rw-r--r--src/wx/timeline.cc561
-rw-r--r--src/wx/timeline.h86
-rw-r--r--src/wx/timeline_dialog.cc42
-rw-r--r--src/wx/timeline_dialog.h34
-rw-r--r--src/wx/wscript17
-rw-r--r--src/wx/wx_util.cc14
-rw-r--r--src/wx/wx_util.h2
29 files changed, 2224 insertions, 1009 deletions
diff --git a/src/wx/audio_dialog.cc b/src/wx/audio_dialog.cc
index d12b5516f..1241b61fb 100644
--- a/src/wx/audio_dialog.cc
+++ b/src/wx/audio_dialog.cc
@@ -1,3 +1,5 @@
+/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */
+
/*
Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
@@ -18,10 +20,10 @@
*/
#include <boost/filesystem.hpp>
+#include "lib/audio_analysis.h"
+#include "lib/film.h"
#include "audio_dialog.h"
#include "audio_plot.h"
-#include "audio_analysis.h"
-#include "film.h"
#include "wx_util.h"
using boost::shared_ptr;
@@ -43,7 +45,6 @@ AudioDialog::AudioDialog (wxWindow* parent)
wxStaticText* m = new wxStaticText (this, wxID_ANY, _("Channels"));
side->Add (m, 1, wxALIGN_CENTER_VERTICAL | wxTOP, 16);
}
-
for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
_channel_checkbox[i] = new wxCheckBox (this, wxID_ANY, std_to_wx (audio_channel_name (i)));
@@ -84,7 +85,7 @@ AudioDialog::AudioDialog (wxWindow* parent)
}
void
-AudioDialog::set_film (boost::shared_ptr<Film> f)
+AudioDialog::set_film (shared_ptr<Film> f)
{
_film_changed_connection.disconnect ();
_film_audio_analysis_succeeded_connection.disconnect ();
@@ -92,32 +93,14 @@ AudioDialog::set_film (boost::shared_ptr<Film> f)
_film = f;
try_to_load_analysis ();
- setup_channels ();
- _plot->set_gain (_film->audio_gain ());
+// _plot->set_gain (_film->audio_gain ());
_film_changed_connection = _film->Changed.connect (bind (&AudioDialog::film_changed, this, _1));
_film_audio_analysis_succeeded_connection = _film->AudioAnalysisSucceeded.connect (bind (&AudioDialog::try_to_load_analysis, this));
- SetTitle (wxString::Format (_("DVD-o-matic audio - %s"), std_to_wx(_film->name()).data()));
+ SetTitle (wxString::Format (_("DCP-o-matic audio - %s"), std_to_wx(_film->name()).data()));
}
-void
-AudioDialog::setup_channels ()
-{
- if (!_film->audio_stream()) {
- return;
- }
-
- AudioMapping m (_film->audio_stream()->channels ());
-
- for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
- if (m.dcp_to_source(static_cast<libdcp::Channel>(i))) {
- _channel_checkbox[i]->Show ();
- } else {
- _channel_checkbox[i]->Hide ();
- }
- }
-}
void
AudioDialog::try_to_load_analysis ()
@@ -134,12 +117,10 @@ AudioDialog::try_to_load_analysis ()
_plot->set_analysis (a);
- AudioMapping m (_film->audio_stream()->channels ());
- optional<libdcp::Channel> c = m.source_to_dcp (0);
- if (c) {
- _channel_checkbox[c.get()]->SetValue (true);
- _plot->set_channel_visible (0, true);
+ if (_channel_checkbox[0]) {
+ _channel_checkbox[0]->SetValue (true);
}
+ _plot->set_channel_visible (0, true);
for (int i = 0; i < AudioPoint::COUNT; ++i) {
_type_checkbox[i]->SetValue (true);
@@ -157,24 +138,15 @@ AudioDialog::channel_clicked (wxCommandEvent& ev)
assert (c < MAX_AUDIO_CHANNELS);
- AudioMapping m (_film->audio_stream()->channels ());
- optional<int> s = m.dcp_to_source (static_cast<libdcp::Channel> (c));
- if (s) {
- _plot->set_channel_visible (s.get(), _channel_checkbox[c]->GetValue ());
- }
+ _plot->set_channel_visible (c, _channel_checkbox[c]->GetValue ());
}
void
AudioDialog::film_changed (Film::Property p)
{
switch (p) {
- case Film::AUDIO_GAIN:
- _plot->set_gain (_film->audio_gain ());
- break;
- case Film::CONTENT_AUDIO_STREAM:
- case Film::EXTERNAL_AUDIO:
- case Film::USE_CONTENT_AUDIO:
- setup_channels ();
+// case Film::AUDIO_GAIN:
+// _plot->set_gain (_film->audio_gain ());
break;
default:
break;
diff --git a/src/wx/audio_dialog.h b/src/wx/audio_dialog.h
index 514faeea0..db1d74f30 100644
--- a/src/wx/audio_dialog.h
+++ b/src/wx/audio_dialog.h
@@ -39,7 +39,6 @@ private:
void type_clicked (wxCommandEvent &);
void smoothing_changed (wxScrollEvent &);
void try_to_load_analysis ();
- void setup_channels ();
boost::shared_ptr<Film> _film;
AudioPlot* _plot;
diff --git a/src/wx/audio_mapping_view.cc b/src/wx/audio_mapping_view.cc
new file mode 100644
index 000000000..3ea0cdd1d
--- /dev/null
+++ b/src/wx/audio_mapping_view.cc
@@ -0,0 +1,174 @@
+/*
+ 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>
+#include <wx/renderer.h>
+#include <wx/grid.h>
+#include <libdcp/types.h>
+#include "lib/audio_mapping.h"
+#include "audio_mapping_view.h"
+#include "wx_util.h"
+
+using std::cout;
+using std::list;
+using boost::shared_ptr;
+
+/* This could go away with wxWidgets 2.9, which has an API call
+ to find these values.
+*/
+
+#ifdef __WXMSW__
+#define CHECKBOX_WIDTH 16
+#define CHECKBOX_HEIGHT 16
+#endif
+
+#ifdef __WXGTK__
+#define CHECKBOX_WIDTH 20
+#define CHECKBOX_HEIGHT 20
+#endif
+
+
+class NoSelectionStringRenderer : public wxGridCellStringRenderer
+{
+public:
+ void Draw (wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, const wxRect& rect, int row, int col, bool)
+ {
+ wxGridCellStringRenderer::Draw (grid, attr, dc, rect, row, col, false);
+ }
+};
+
+class CheckBoxRenderer : public wxGridCellRenderer
+{
+public:
+
+ void Draw (wxGrid& grid, wxGridCellAttr &, wxDC& dc, const wxRect& rect, int row, int col, bool)
+ {
+#if wxMAJOR_VERSION == 2 && wxMINOR_VERSION >= 9
+ dc.SetPen (*wxThePenList->FindOrCreatePen (wxColour (255, 255, 255), 0, wxPENSTYLE_SOLID));
+#else
+ dc.SetPen (*wxThePenList->FindOrCreatePen (wxColour (255, 255, 255), 0, wxSOLID));
+#endif
+ dc.DrawRectangle (rect);
+
+ wxRendererNative::Get().DrawCheckBox (
+ &grid,
+ dc, rect,
+ grid.GetCellValue (row, col) == wxT("1") ? static_cast<int>(wxCONTROL_CHECKED) : 0
+ );
+ }
+
+ wxSize GetBestSize (wxGrid &, wxGridCellAttr &, wxDC &, int, int)
+ {
+ return wxSize (CHECKBOX_WIDTH + 4, CHECKBOX_HEIGHT + 4);
+ }
+
+ wxGridCellRenderer* Clone () const
+ {
+ return new CheckBoxRenderer;
+ }
+};
+
+
+AudioMappingView::AudioMappingView (wxWindow* parent)
+ : wxPanel (parent, wxID_ANY)
+{
+ _grid = new wxGrid (this, wxID_ANY);
+
+ _grid->CreateGrid (0, 7);
+#if wxMINOR_VERSION == 9
+ _grid->HideRowLabels ();
+#else
+ _grid->SetRowLabelSize (0);
+#endif
+ _grid->DisableDragRowSize ();
+ _grid->DisableDragColSize ();
+ _grid->EnableEditing (false);
+ _grid->SetCellHighlightPenWidth (0);
+ _grid->SetDefaultRenderer (new NoSelectionStringRenderer);
+
+ _grid->SetColLabelValue (0, _("Content channel"));
+ _grid->SetColLabelValue (1, _("L"));
+ _grid->SetColLabelValue (2, _("R"));
+ _grid->SetColLabelValue (3, _("C"));
+ _grid->SetColLabelValue (4, _("Lfe"));
+ _grid->SetColLabelValue (5, _("Ls"));
+ _grid->SetColLabelValue (6, _("Rs"));
+
+ _grid->AutoSize ();
+
+ _sizer = new wxBoxSizer (wxVERTICAL);
+ _sizer->Add (_grid, 1, wxEXPAND | wxALL);
+ SetSizerAndFit (_sizer);
+
+ Connect (wxID_ANY, wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler (AudioMappingView::left_click), 0, this);
+}
+
+void
+AudioMappingView::left_click (wxGridEvent& ev)
+{
+ if (ev.GetCol() == 0) {
+ return;
+ }
+
+ if (_grid->GetCellValue (ev.GetRow(), ev.GetCol()) == wxT("1")) {
+ _grid->SetCellValue (ev.GetRow(), ev.GetCol(), wxT("0"));
+ } else {
+ _grid->SetCellValue (ev.GetRow(), ev.GetCol(), wxT("1"));
+ }
+
+ AudioMapping mapping;
+ for (int i = 0; i < _grid->GetNumberRows(); ++i) {
+ for (int j = 1; j < _grid->GetNumberCols(); ++j) {
+ if (_grid->GetCellValue (i, j) == wxT ("1")) {
+ mapping.add (i, static_cast<libdcp::Channel> (j - 1));
+ }
+ }
+ }
+
+ Changed (mapping);
+}
+
+void
+AudioMappingView::set (AudioMapping map)
+{
+ if (_grid->GetNumberRows ()) {
+ _grid->DeleteRows (0, _grid->GetNumberRows ());
+ }
+
+ list<int> content_channels = map.content_channels ();
+ _grid->InsertRows (0, content_channels.size ());
+
+ for (size_t r = 0; r < content_channels.size(); ++r) {
+ for (int c = 1; c < 7; ++c) {
+ _grid->SetCellRenderer (r, c, new CheckBoxRenderer);
+ }
+ }
+
+ int n = 0;
+ for (list<int>::iterator i = content_channels.begin(); i != content_channels.end(); ++i) {
+ _grid->SetCellValue (n, 0, wxString::Format (wxT("%d"), *i + 1));
+
+ list<libdcp::Channel> const d = map.content_to_dcp (*i);
+ for (list<libdcp::Channel>::const_iterator j = d.begin(); j != d.end(); ++j) {
+ _grid->SetCellValue (n, static_cast<int> (*j) + 1, wxT("1"));
+ }
+ ++n;
+ }
+}
+
diff --git a/src/wx/audio_mapping_view.h b/src/wx/audio_mapping_view.h
new file mode 100644
index 000000000..824356a9f
--- /dev/null
+++ b/src/wx/audio_mapping_view.h
@@ -0,0 +1,41 @@
+/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */
+
+/*
+ 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/signals2.hpp>
+#include <wx/wx.h>
+#include <wx/grid.h>
+#include "lib/audio_mapping.h"
+
+class AudioMappingView : public wxPanel
+{
+public:
+ AudioMappingView (wxWindow *);
+
+ void set (AudioMapping);
+
+ boost::signals2::signal<void (AudioMapping)> Changed;
+
+private:
+ void left_click (wxGridEvent &);
+
+ wxGrid* _grid;
+ wxSizer* _sizer;
+};
diff --git a/src/wx/audio_plot.cc b/src/wx/audio_plot.cc
index 3fec1d3fe..fb02fea7b 100644
--- a/src/wx/audio_plot.cc
+++ b/src/wx/audio_plot.cc
@@ -1,3 +1,5 @@
+/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */
+
/*
Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
@@ -21,7 +23,6 @@
#include <boost/bind.hpp>
#include <wx/graphics.h>
#include "audio_plot.h"
-#include "lib/decoder_factory.h"
#include "lib/audio_decoder.h"
#include "lib/audio_analysis.h"
#include "wx/wx_util.h"
@@ -38,7 +39,7 @@ int const AudioPlot::_minimum = -70;
int const AudioPlot::max_smoothing = 128;
AudioPlot::AudioPlot (wxWindow* parent)
- : wxPanel (parent)
+ : wxPanel (parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE)
, _gain (0)
, _smoothing (max_smoothing / 2)
{
diff --git a/src/wx/config_dialog.cc b/src/wx/config_dialog.cc
index 4daf581ba..0b13b9c88 100644
--- a/src/wx/config_dialog.cc
+++ b/src/wx/config_dialog.cc
@@ -28,7 +28,7 @@
#include <wx/notebook.h>
#include "lib/config.h"
#include "lib/server.h"
-#include "lib/format.h"
+#include "lib/ratio.h"
#include "lib/scaler.h"
#include "lib/filter.h"
#include "lib/dcp_content_type.h"
@@ -108,6 +108,11 @@ ConfigDialog::make_misc_panel ()
table->Add (_num_local_encoding_threads, 1, wxEXPAND);
table->AddSpacer (0);
+ add_label_to_sizer (table, _misc_panel, _("Default duration of still images"));
+ _default_still_length = new wxSpinCtrl (_misc_panel);
+ table->Add (_default_still_length, 1, wxEXPAND);
+ add_label_to_sizer (table, _misc_panel, _("s"));
+
add_label_to_sizer (table, _misc_panel, _("Default directory for new films"));
#ifdef __WXMSW__
_default_directory = new DirPickerCtrl (_misc_panel);
@@ -122,9 +127,9 @@ ConfigDialog::make_misc_panel ()
table->Add (_default_dci_metadata_button);
table->AddSpacer (1);
- add_label_to_sizer (table, _misc_panel, _("Default format"));
- _default_format = new wxChoice (_misc_panel, wxID_ANY);
- table->Add (_default_format);
+ add_label_to_sizer (table, _misc_panel, _("Default container"));
+ _default_container = new wxChoice (_misc_panel, wxID_ANY);
+ table->Add (_default_container);
table->AddSpacer (1);
add_label_to_sizer (table, _misc_panel, _("Default content type"));
@@ -157,22 +162,26 @@ ConfigDialog::make_misc_panel ()
_num_local_encoding_threads->SetValue (config->num_local_encoding_threads ());
_num_local_encoding_threads->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (ConfigDialog::num_local_encoding_threads_changed), 0, this);
+ _default_still_length->SetRange (1, 3600);
+ _default_still_length->SetValue (config->default_still_length ());
+ _default_still_length->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (ConfigDialog::default_still_length_changed), 0, this);
+
_default_directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir()))));
_default_directory->Connect (wxID_ANY, wxEVT_COMMAND_DIRPICKER_CHANGED, wxCommandEventHandler (ConfigDialog::default_directory_changed), 0, this);
_default_dci_metadata_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (ConfigDialog::edit_default_dci_metadata_clicked), 0, this);
- vector<Format const *> fmt = Format::all ();
+ vector<Ratio const *> ratio = Ratio::all ();
int n = 0;
- for (vector<Format const *>::iterator i = fmt.begin(); i != fmt.end(); ++i) {
- _default_format->Append (std_to_wx ((*i)->name ()));
- if (*i == config->default_format ()) {
- _default_format->SetSelection (n);
+ for (vector<Ratio const *>::iterator i = ratio.begin(); i != ratio.end(); ++i) {
+ _default_container->Append (std_to_wx ((*i)->nickname ()));
+ if (*i == config->default_container ()) {
+ _default_container->SetSelection (n);
}
++n;
}
- _default_format->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (ConfigDialog::default_format_changed), 0, this);
+ _default_container->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (ConfigDialog::default_container_changed), 0, this);
vector<DCPContentType const *> const ct = DCPContentType::all ();
n = 0;
@@ -227,33 +236,6 @@ ConfigDialog::make_tms_panel ()
}
void
-ConfigDialog::make_metadata_panel ()
-{
- _metadata_panel = new wxPanel (_notebook);
- wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
- _metadata_panel->SetSizer (s);
-
- wxFlexGridSizer* table = new wxFlexGridSizer (2, 6, 6);
- table->AddGrowableCol (1, 1);
- s->Add (table, 1, wxALL | wxEXPAND, 8);
-
- add_label_to_sizer (table, _metadata_panel, _("Issuer"));
- _issuer = new wxTextCtrl (_metadata_panel, wxID_ANY);
- table->Add (_issuer, 1, wxEXPAND);
-
- add_label_to_sizer (table, _metadata_panel, _("Creator"));
- _creator = new wxTextCtrl (_metadata_panel, wxID_ANY);
- table->Add (_creator, 1, wxEXPAND);
-
- Config* config = Config::instance ();
-
- _issuer->SetValue (std_to_wx (config->dcp_metadata().issuer));
- _issuer->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (ConfigDialog::issuer_changed), 0, this);
- _creator->SetValue (std_to_wx (config->dcp_metadata().creator));
- _creator->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (ConfigDialog::creator_changed), 0, this);
-}
-
-void
ConfigDialog::make_ab_panel ()
{
_ab_panel = new wxPanel (_notebook);
@@ -278,21 +260,39 @@ ConfigDialog::make_ab_panel ()
add_label_to_sizer (table, _ab_panel, _("Reference filters"));
wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
_reference_filters = new wxStaticText (_ab_panel, wxID_ANY, wxT (""));
- s->Add (_reference_filters, 1, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxALL, 6);
+ s->Add (_reference_filters, 1, wxEXPAND);
_reference_filters_button = new wxButton (_ab_panel, wxID_ANY, _("Edit..."));
s->Add (_reference_filters_button, 0);
table->Add (s, 1, wxEXPAND);
table->AddSpacer (0);
}
+}
+
+void
+ConfigDialog::make_metadata_panel ()
+{
+ _metadata_panel = new wxPanel (_notebook);
+ wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
+ _metadata_panel->SetSizer (s);
+
+ wxFlexGridSizer* table = new wxFlexGridSizer (2, 6, 6);
+ table->AddGrowableCol (1, 1);
+ s->Add (table, 1, wxALL | wxEXPAND, 8);
+
+ add_label_to_sizer (table, _metadata_panel, _("Issuer"));
+ _issuer = new wxTextCtrl (_metadata_panel, wxID_ANY);
+ table->Add (_issuer, 1, wxEXPAND);
+
+ add_label_to_sizer (table, _metadata_panel, _("Creator"));
+ _creator = new wxTextCtrl (_metadata_panel, wxID_ANY);
+ table->Add (_creator, 1, wxEXPAND);
Config* config = Config::instance ();
-
- _reference_scaler->SetSelection (Scaler::as_index (config->reference_scaler ()));
- _reference_scaler->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (ConfigDialog::reference_scaler_changed), 0, this);
- pair<string, string> p = Filter::ffmpeg_strings (config->reference_filters ());
- _reference_filters->SetLabel (std_to_wx (p.first) + N_(" ") + std_to_wx (p.second));
- _reference_filters_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (ConfigDialog::edit_reference_filters_clicked), 0, this);
+ _issuer->SetValue (std_to_wx (config->dcp_metadata().issuer));
+ _issuer->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (ConfigDialog::issuer_changed), 0, this);
+ _creator->SetValue (std_to_wx (config->dcp_metadata().creator));
+ _creator->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (ConfigDialog::creator_changed), 0, this);
}
void
@@ -527,10 +527,16 @@ ConfigDialog::setup_language_sensitivity ()
}
void
-ConfigDialog::default_format_changed (wxCommandEvent &)
+ConfigDialog::default_still_length_changed (wxCommandEvent &)
+{
+ Config::instance()->set_default_still_length (_default_still_length->GetValue ());
+}
+
+void
+ConfigDialog::default_container_changed (wxCommandEvent &)
{
- vector<Format const *> fmt = Format::all ();
- Config::instance()->set_default_format (fmt[_default_format->GetSelection()]);
+ vector<Ratio const *> ratio = Ratio::all ();
+ Config::instance()->set_default_container (ratio[_default_container->GetSelection()]);
}
void
diff --git a/src/wx/config_dialog.h b/src/wx/config_dialog.h
index 526480912..dda846b7d 100644
--- a/src/wx/config_dialog.h
+++ b/src/wx/config_dialog.h
@@ -47,6 +47,7 @@ private:
void tms_user_changed (wxCommandEvent &);
void tms_password_changed (wxCommandEvent &);
void num_local_encoding_threads_changed (wxCommandEvent &);
+ void default_still_length_changed (wxCommandEvent &);
void default_directory_changed (wxCommandEvent &);
void edit_default_dci_metadata_clicked (wxCommandEvent &);
void reference_scaler_changed (wxCommandEvent &);
@@ -56,7 +57,7 @@ private:
void edit_server_clicked (wxCommandEvent &);
void remove_server_clicked (wxCommandEvent &);
void server_selection_changed (wxListEvent &);
- void default_format_changed (wxCommandEvent &);
+ void default_container_changed (wxCommandEvent &);
void default_dcp_content_type_changed (wxCommandEvent &);
void issuer_changed (wxCommandEvent &);
void creator_changed (wxCommandEvent &);
@@ -78,13 +79,14 @@ private:
wxPanel* _metadata_panel;
wxCheckBox* _set_language;
wxChoice* _language;
- wxChoice* _default_format;
+ wxChoice* _default_container;
wxChoice* _default_dcp_content_type;
wxTextCtrl* _tms_ip;
wxTextCtrl* _tms_path;
wxTextCtrl* _tms_user;
wxTextCtrl* _tms_password;
wxSpinCtrl* _num_local_encoding_threads;
+ wxSpinCtrl* _default_still_length;
#ifdef __WXMSW__
DirPickerCtrl* _default_directory;
#else
diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc
index 6456ae247..bddce18be 100644
--- a/src/wx/film_editor.cc
+++ b/src/wx/film_editor.cc
@@ -25,18 +25,21 @@
#include <iomanip>
#include <wx/wx.h>
#include <wx/notebook.h>
+#include <wx/listctrl.h>
#include <boost/thread.hpp>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
-#include "lib/format.h"
#include "lib/film.h"
#include "lib/transcode_job.h"
#include "lib/exceptions.h"
#include "lib/ab_transcode_job.h"
#include "lib/job_manager.h"
#include "lib/filter.h"
+#include "lib/ratio.h"
#include "lib/config.h"
-#include "lib/ffmpeg_decoder.h"
+#include "lib/imagemagick_content.h"
+#include "lib/sndfile_content.h"
+#include "lib/dcp_content_type.h"
#include "filter_dialog.h"
#include "wx_util.h"
#include "film_editor.h"
@@ -45,6 +48,10 @@
#include "dci_metadata_dialog.h"
#include "scaler.h"
#include "audio_dialog.h"
+#include "imagemagick_content_dialog.h"
+#include "timeline_dialog.h"
+#include "audio_mapping_view.h"
+#include "timecode.h"
using std::string;
using std::cout;
@@ -54,150 +61,114 @@ using std::fixed;
using std::setprecision;
using std::list;
using std::vector;
+using std::max;
using boost::shared_ptr;
+using boost::weak_ptr;
using boost::dynamic_pointer_cast;
+using boost::lexical_cast;
/** @param f Film to edit */
FilmEditor::FilmEditor (shared_ptr<Film> f, wxWindow* parent)
: wxPanel (parent)
- , _film (f)
, _generally_sensitive (true)
, _audio_dialog (0)
+ , _timeline_dialog (0)
{
wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
- SetSizer (s);
- _notebook = new wxNotebook (this, wxID_ANY);
- s->Add (_notebook, 1);
- make_film_panel ();
- _notebook->AddPage (_film_panel, _("Film"), true);
- make_video_panel ();
- _notebook->AddPage (_video_panel, _("Video"), false);
- make_audio_panel ();
- _notebook->AddPage (_audio_panel, _("Audio"), false);
- make_subtitle_panel ();
- _notebook->AddPage (_subtitle_panel, _("Subtitles"), false);
+ _main_notebook = new wxNotebook (this, wxID_ANY);
+ s->Add (_main_notebook, 1);
- set_film (_film);
+ make_content_panel ();
+ _main_notebook->AddPage (_content_panel, _("Content"), true);
+ make_dcp_panel ();
+ _main_notebook->AddPage (_dcp_panel, _("DCP"), false);
+
+ setup_ratios ();
+
+ set_film (f);
connect_to_widgets ();
JobManager::instance()->ActiveJobsChanged.connect (
bind (&FilmEditor::active_jobs_changed, this, _1)
);
- setup_visibility ();
- setup_formats ();
+ SetSizerAndFit (s);
}
void
-FilmEditor::make_film_panel ()
+FilmEditor::make_dcp_panel ()
{
- _film_panel = new wxPanel (_notebook);
- _film_sizer = new wxBoxSizer (wxVERTICAL);
- _film_panel->SetSizer (_film_sizer);
+ _dcp_panel = new wxPanel (_main_notebook);
+ _dcp_sizer = new wxBoxSizer (wxVERTICAL);
+ _dcp_panel->SetSizer (_dcp_sizer);
wxGridBagSizer* grid = new wxGridBagSizer (4, 4);
- _film_sizer->Add (grid, 0, wxALL, 8);
+ _dcp_sizer->Add (grid, 0, wxEXPAND | wxALL, 8);
int r = 0;
- add_label_to_grid_bag_sizer (grid, _film_panel, _("Name"), wxGBPosition (r, 0));
- _name = new wxTextCtrl (_film_panel, wxID_ANY);
+ add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Name"), wxGBPosition (r, 0));
+ _name = new wxTextCtrl (_dcp_panel, wxID_ANY);
grid->Add (_name, wxGBPosition(r, 1), wxDefaultSpan, wxEXPAND);
++r;
- add_label_to_grid_bag_sizer (grid, _film_panel, _("DCP Name"), wxGBPosition (r, 0));
- _dcp_name = new wxStaticText (_film_panel, wxID_ANY, wxT (""));
+ add_label_to_grid_bag_sizer (grid, _dcp_panel, _("DCP Name"), wxGBPosition (r, 0));
+ _dcp_name = new wxStaticText (_dcp_panel, wxID_ANY, wxT (""));
grid->Add (_dcp_name, wxGBPosition(r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
++r;
- _use_dci_name = new wxCheckBox (_film_panel, wxID_ANY, _("Use DCI name"));
+ _use_dci_name = new wxCheckBox (_dcp_panel, wxID_ANY, _("Use DCI name"));
grid->Add (_use_dci_name, wxGBPosition (r, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
- _edit_dci_button = new wxButton (_film_panel, wxID_ANY, _("Details..."));
+ _edit_dci_button = new wxButton (_dcp_panel, wxID_ANY, _("Details..."));
grid->Add (_edit_dci_button, wxGBPosition (r, 1), wxDefaultSpan);
++r;
- add_label_to_grid_bag_sizer (grid, _film_panel, _("Content"), wxGBPosition (r, 0));
- _content = new wxFilePickerCtrl (_film_panel, wxID_ANY, wxT (""), _("Select Content File"), wxT("*.*"));
- grid->Add (_content, wxGBPosition (r, 1), wxDefaultSpan, wxEXPAND);
- ++r;
-
- _trust_content_header = new wxCheckBox (_film_panel, wxID_ANY, _("Trust content's header"));
- video_control (_trust_content_header);
- grid->Add (_trust_content_header, wxGBPosition (r, 0), wxGBSpan(1, 2));
+ add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Container"), wxGBPosition (r, 0));
+ _container = new wxChoice (_dcp_panel, wxID_ANY);
+ grid->Add (_container, wxGBPosition (r, 1));
++r;
- add_label_to_grid_bag_sizer (grid, _film_panel, _("Content Type"), wxGBPosition (r, 0));
- _dcp_content_type = new wxChoice (_film_panel, wxID_ANY);
+ add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Content Type"), wxGBPosition (r, 0));
+ _dcp_content_type = new wxChoice (_dcp_panel, wxID_ANY);
grid->Add (_dcp_content_type, wxGBPosition (r, 1));
++r;
- video_control (add_label_to_grid_bag_sizer (grid, _film_panel, _("Original Frame Rate"), wxGBPosition (r, 0)));
- _source_frame_rate = new wxStaticText (_film_panel, wxID_ANY, wxT (""));
- grid->Add (video_control (_source_frame_rate), wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
- ++r;
-
{
- add_label_to_grid_bag_sizer (grid, _film_panel, _("DCP Frame Rate"), wxGBPosition (r, 0));
+ add_label_to_grid_bag_sizer (grid, _dcp_panel, _("DCP Frame Rate"), wxGBPosition (r, 0));
wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
- _dcp_frame_rate = new wxChoice (_film_panel, wxID_ANY);
+ _dcp_frame_rate = new wxChoice (_dcp_panel, wxID_ANY);
s->Add (_dcp_frame_rate, 1, wxALIGN_CENTER_VERTICAL);
- _best_dcp_frame_rate = new wxButton (_film_panel, wxID_ANY, _("Use best"));
- s->Add (_best_dcp_frame_rate, 1, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 6);
+ _best_dcp_frame_rate = new wxButton (_dcp_panel, wxID_ANY, _("Use best"));
+ s->Add (_best_dcp_frame_rate, 1, wxALIGN_CENTER_VERTICAL | wxEXPAND);
grid->Add (s, wxGBPosition (r, 1));
}
++r;
- _frame_rate_description = new wxStaticText (_film_panel, wxID_ANY, wxT ("\n \n "), wxDefaultPosition, wxDefaultSize);
- grid->Add (video_control (_frame_rate_description), wxGBPosition (r, 0), wxGBSpan (1, 2), wxEXPAND | wxALIGN_CENTER_VERTICAL | wxALL, 6);
- wxFont font = _frame_rate_description->GetFont();
- font.SetStyle(wxFONTSTYLE_ITALIC);
- font.SetPointSize(font.GetPointSize() - 1);
- _frame_rate_description->SetFont(font);
- ++r;
-
- video_control (add_label_to_grid_bag_sizer (grid, _film_panel, _("Length"), wxGBPosition (r, 0)));
- _length = new wxStaticText (_film_panel, wxID_ANY, wxT (""));
- grid->Add (video_control (_length), wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
- ++r;
-
-
{
- video_control (add_label_to_grid_bag_sizer (grid, _film_panel, _("Trim frames"), wxGBPosition (r, 0)));
- wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
- video_control (add_label_to_sizer (s, _film_panel, _("Start")));
- _trim_start = new wxSpinCtrl (_film_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1));
- s->Add (video_control (_trim_start));
- video_control (add_label_to_sizer (s, _film_panel, _("End")));
- _trim_end = new wxSpinCtrl (_film_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1));
- s->Add (video_control (_trim_end));
-
+ add_label_to_grid_bag_sizer (grid, _dcp_panel, _("JPEG2000 bandwidth"), wxGBPosition (r, 0));
+ wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
+ _j2k_bandwidth = new wxSpinCtrl (_dcp_panel, wxID_ANY);
+ s->Add (_j2k_bandwidth, 1);
+ add_label_to_sizer (s, _dcp_panel, _("MBps"));
grid->Add (s, wxGBPosition (r, 1));
}
++r;
- video_control (add_label_to_grid_bag_sizer (grid, _film_panel, _("Trim method"), wxGBPosition (r, 0)));
- _trim_type = new wxChoice (_film_panel, wxID_ANY);
- grid->Add (video_control (_trim_type), wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
+ add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Scaler"), wxGBPosition (r, 0));
+ _scaler = new wxChoice (_dcp_panel, wxID_ANY);
+ grid->Add (_scaler, wxGBPosition (r, 1));
++r;
- _dcp_ab = new wxCheckBox (_film_panel, wxID_ANY, _("A/B"));
- video_control (_dcp_ab);
- grid->Add (_dcp_ab, wxGBPosition (r, 0));
- ++r;
+ vector<Scaler const *> const sc = Scaler::all ();
+ for (vector<Scaler const *>::const_iterator i = sc.begin(); i != sc.end(); ++i) {
+ _scaler->Append (std_to_wx ((*i)->name()));
+ }
- /* STILL-only stuff */
- {
- still_control (add_label_to_grid_bag_sizer (grid, _film_panel, _("Duration"), wxGBPosition (r, 0)));
- wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
- _still_duration = new wxSpinCtrl (_film_panel);
- still_control (_still_duration);
- s->Add (_still_duration, 1, wxEXPAND);
- /// TRANSLATORS: `s' here is an abbreviation for seconds, the unit of time
- still_control (add_label_to_sizer (s, _film_panel, _("s")));
- grid->Add (s, wxGBPosition (r, 1));
+ vector<Ratio const *> const ratio = Ratio::all ();
+ for (vector<Ratio const *>::const_iterator i = ratio.begin(); i != ratio.end(); ++i) {
+ _container->Append (std_to_wx ((*i)->nickname ()));
}
- ++r;
vector<DCPContentType const *> const ct = DCPContentType::all ();
for (vector<DCPContentType const *>::const_iterator i = ct.begin(); i != ct.end(); ++i) {
@@ -209,71 +180,62 @@ FilmEditor::make_film_panel ()
_dcp_frame_rate->Append (std_to_wx (boost::lexical_cast<string> (*i)));
}
- _trim_type->Append (_("encode all frames and play the subset"));
- _trim_type->Append (_("encode only the subset"));
+ _j2k_bandwidth->SetRange (50, 250);
}
void
FilmEditor::connect_to_widgets ()
{
- _name->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (FilmEditor::name_changed), 0, this);
- _use_dci_name->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::use_dci_name_toggled), 0, this);
- _edit_dci_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::edit_dci_button_clicked), 0, this);
- _format->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::format_changed), 0, this);
- _content->Connect (wxID_ANY, wxEVT_COMMAND_FILEPICKER_CHANGED, wxCommandEventHandler (FilmEditor::content_changed), 0, this);
- _trust_content_header->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::trust_content_header_changed), 0, this);
- _left_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::left_crop_changed), 0, this);
- _right_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::right_crop_changed), 0, this);
- _top_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::top_crop_changed), 0, this);
- _bottom_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::bottom_crop_changed), 0, this);
- _filters_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::edit_filters_clicked), 0, this);
- _scaler->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::scaler_changed), 0, this);
- _dcp_content_type->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_content_type_changed), 0, this);
- _dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_frame_rate_changed), 0, this);
- _best_dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::best_dcp_frame_rate_clicked), 0, this);
- _dcp_ab->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::dcp_ab_toggled), 0, this);
- _still_duration->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::still_duration_changed), 0, this);
- _trim_start->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::trim_start_changed), 0, this);
- _trim_end->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::trim_end_changed), 0, this);
- _trim_type->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::trim_type_changed), 0, this);
- _with_subtitles->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::with_subtitles_toggled), 0, this);
- _subtitle_offset->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::subtitle_offset_changed), 0, this);
- _subtitle_scale->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::subtitle_scale_changed), 0, this);
- _colour_lut->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::colour_lut_changed), 0, this);
- _j2k_bandwidth->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::j2k_bandwidth_changed), 0, this);
- _subtitle_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::subtitle_stream_changed), 0, this);
- _audio_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::audio_stream_changed), 0, this);
- _audio_gain->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::audio_gain_changed), 0, this);
+ _name->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (FilmEditor::name_changed), 0, this);
+ _use_dci_name->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::use_dci_name_toggled), 0, this);
+ _edit_dci_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::edit_dci_button_clicked), 0, this);
+ _container->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::container_changed), 0, this);
+// _format->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::format_changed), 0, this);
+ _content->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler (FilmEditor::content_selection_changed), 0, this);
+ _content->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler (FilmEditor::content_selection_changed), 0, this);
+ _content_add->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_add_clicked), 0, this);
+ _content_remove->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_remove_clicked), 0, this);
+ _content_timeline->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_timeline_clicked), 0, this);
+ _loop_content->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::loop_content_toggled), 0, this);
+ _loop_count->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::loop_count_changed), 0, this);
+ _left_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::left_crop_changed), 0, this);
+ _right_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::right_crop_changed), 0, this);
+ _top_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::top_crop_changed), 0, this);
+ _bottom_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::bottom_crop_changed), 0, this);
+ _filters_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::edit_filters_clicked), 0, this);
+ _scaler->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::scaler_changed), 0, this);
+ _dcp_content_type->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_content_type_changed), 0, this);
+ _dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_frame_rate_changed), 0, this);
+ _best_dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::best_dcp_frame_rate_clicked), 0, this);
+ _with_subtitles->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::with_subtitles_toggled), 0, this);
+ _subtitle_offset->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::subtitle_offset_changed), 0, this);
+ _subtitle_scale->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::subtitle_scale_changed), 0, this);
+ _colour_lut->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::colour_lut_changed), 0, this);
+ _j2k_bandwidth->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::j2k_bandwidth_changed), 0, this);
+ _audio_gain->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::audio_gain_changed), 0, this);
_audio_gain_calculate_button->Connect (
wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::audio_gain_calculate_button_clicked), 0, this
);
- _show_audio->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::show_audio_clicked), 0, this);
- _audio_delay->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::audio_delay_changed), 0, this);
- _use_content_audio->Connect (wxID_ANY, wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler (FilmEditor::use_audio_changed), 0, this);
- _use_external_audio->Connect (wxID_ANY, wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler (FilmEditor::use_audio_changed), 0, this);
- for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
- _external_audio[i]->Connect (
- wxID_ANY, wxEVT_COMMAND_FILEPICKER_CHANGED, wxCommandEventHandler (FilmEditor::external_audio_changed), 0, this
- );
- }
+ _show_audio->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::show_audio_clicked), 0, this);
+ _audio_delay->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::audio_delay_changed), 0, this);
+ _audio_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::audio_stream_changed), 0, this);
+ _subtitle_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::subtitle_stream_changed), 0, this);
+ _audio_mapping->Changed.connect (boost::bind (&FilmEditor::audio_mapping_changed, this, _1));
+ _start->Changed.connect (boost::bind (&FilmEditor::start_changed, this));
+ _length->Changed.connect (boost::bind (&FilmEditor::length_changed, this));
}
void
FilmEditor::make_video_panel ()
{
- _video_panel = new wxPanel (_notebook);
- _video_sizer = new wxBoxSizer (wxVERTICAL);
- _video_panel->SetSizer (_video_sizer);
+ _video_panel = new wxPanel (_content_notebook);
+ wxBoxSizer* video_sizer = new wxBoxSizer (wxVERTICAL);
+ _video_panel->SetSizer (video_sizer);
wxGridBagSizer* grid = new wxGridBagSizer (4, 4);
- _video_sizer->Add (grid, 0, wxALL, 8);
+ video_sizer->Add (grid, 0, wxALL, 8);
int r = 0;
- add_label_to_grid_bag_sizer (grid, _video_panel, _("Format"), wxGBPosition (r, 0));
- _format = new wxChoice (_video_panel, wxID_ANY);
- grid->Add (_format, wxGBPosition (r, 1));
- ++r;
-
add_label_to_grid_bag_sizer (grid, _video_panel, _("Left crop"), wxGBPosition (r, 0));
_left_crop = new wxSpinCtrl (_video_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1));
grid->Add (_left_crop, wxGBPosition (r, 1));
@@ -294,6 +256,11 @@ FilmEditor::make_video_panel ()
grid->Add (_bottom_crop, wxGBPosition (r, 1));
++r;
+ add_label_to_grid_bag_sizer (grid, _video_panel, _("Scale to"), wxGBPosition (r, 0));
+ _ratio = new wxChoice (_video_panel, wxID_ANY);
+ grid->Add (_ratio, wxGBPosition (r, 1));
+ ++r;
+
_scaling_description = new wxStaticText (_video_panel, wxID_ANY, wxT ("\n \n \n \n"), wxDefaultPosition, wxDefaultSize);
grid->Add (_scaling_description, wxGBPosition (r, 0), wxGBSpan (1, 2), wxEXPAND | wxALIGN_CENTER_VERTICAL | wxALL, 6);
wxFont font = _scaling_description->GetFont();
@@ -304,28 +271,16 @@ FilmEditor::make_video_panel ()
/* VIDEO-only stuff */
{
- video_control (add_label_to_grid_bag_sizer (grid, _video_panel, _("Filters"), wxGBPosition (r, 0)));
+ add_label_to_grid_bag_sizer (grid, _video_panel, _("Filters"), wxGBPosition (r, 0));
wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
_filters = new wxStaticText (_video_panel, wxID_ANY, _("None"));
- video_control (_filters);
s->Add (_filters, 1, wxEXPAND | wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM | wxRIGHT, 6);
_filters_button = new wxButton (_video_panel, wxID_ANY, _("Edit..."));
- video_control (_filters_button);
s->Add (_filters_button, 0);
grid->Add (s, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
}
++r;
- video_control (add_label_to_grid_bag_sizer (grid, _video_panel, _("Scaler"), wxGBPosition (r, 0)));
- _scaler = new wxChoice (_video_panel, wxID_ANY);
- grid->Add (video_control (_scaler), wxGBPosition (r, 1));
- ++r;
-
- vector<Scaler const *> const sc = Scaler::all ();
- for (vector<Scaler const *>::const_iterator i = sc.begin(); i != sc.end(); ++i) {
- _scaler->Append (std_to_wx ((*i)->name()));
- }
-
add_label_to_grid_bag_sizer (grid, _video_panel, _("Colour look-up table"), wxGBPosition (r, 0));
_colour_lut = new wxChoice (_video_panel, wxID_ANY);
for (int i = 0; i < 2; ++i) {
@@ -335,82 +290,115 @@ FilmEditor::make_video_panel ()
grid->Add (_colour_lut, wxGBPosition (r, 1), wxDefaultSpan, wxEXPAND);
++r;
- {
- add_label_to_grid_bag_sizer (grid, _video_panel, _("JPEG2000 bandwidth"), wxGBPosition (r, 0));
- wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
- _j2k_bandwidth = new wxSpinCtrl (_video_panel, wxID_ANY);
- s->Add (_j2k_bandwidth, 1);
- add_label_to_sizer (s, _video_panel, _("MBps"));
- grid->Add (s, wxGBPosition (r, 1));
- }
- ++r;
-
_left_crop->SetRange (0, 1024);
_top_crop->SetRange (0, 1024);
_right_crop->SetRange (0, 1024);
_bottom_crop->SetRange (0, 1024);
- _still_duration->SetRange (1, 60 * 60);
- _trim_start->SetRange (0, 24 * 60 * 60);
- _trim_end->SetRange (0, 24 * 60 * 60);
- _j2k_bandwidth->SetRange (50, 250);
+}
+
+void
+FilmEditor::make_content_panel ()
+{
+ _content_panel = new wxPanel (_main_notebook);
+ _content_sizer = new wxBoxSizer (wxVERTICAL);
+ _content_panel->SetSizer (_content_sizer);
+
+ {
+ wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
+
+ _content = new wxListCtrl (_content_panel, wxID_ANY, wxDefaultPosition, wxSize (320, 160), wxLC_REPORT | wxLC_NO_HEADER | wxLC_SINGLE_SEL);
+ s->Add (_content, 1, wxEXPAND | wxTOP | wxBOTTOM, 6);
+
+ _content->InsertColumn (0, wxT(""));
+ _content->SetColumnWidth (0, 512);
+
+ wxBoxSizer* b = new wxBoxSizer (wxVERTICAL);
+ _content_add = new wxButton (_content_panel, wxID_ANY, _("Add..."));
+ b->Add (_content_add, 1, wxEXPAND | wxLEFT | wxRIGHT);
+ _content_remove = new wxButton (_content_panel, wxID_ANY, _("Remove"));
+ b->Add (_content_remove, 1, wxEXPAND | wxLEFT | wxRIGHT);
+ _content_timeline = new wxButton (_content_panel, wxID_ANY, _("Timeline..."));
+ b->Add (_content_timeline, 1, wxEXPAND | wxLEFT | wxRIGHT);
+
+ s->Add (b, 0, wxALL, 4);
+
+ _content_sizer->Add (s, 0.75, wxEXPAND | wxALL, 6);
+ }
+
+ wxBoxSizer* h = new wxBoxSizer (wxHORIZONTAL);
+ _loop_content = new wxCheckBox (_content_panel, wxID_ANY, _("Loop everything"));
+ h->Add (_loop_content, 0, wxALL, 6);
+ _loop_count = new wxSpinCtrl (_content_panel, wxID_ANY);
+ h->Add (_loop_count, 0, wxALL, 6);
+ add_label_to_sizer (h, _content_panel, _("times"));
+ _content_sizer->Add (h, 0, wxALL, 6);
+
+ _content_notebook = new wxNotebook (_content_panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_LEFT);
+ _content_sizer->Add (_content_notebook, 1, wxEXPAND | wxTOP, 6);
+
+ make_video_panel ();
+ _content_notebook->AddPage (_video_panel, _("Video"), false);
+ make_audio_panel ();
+ _content_notebook->AddPage (_audio_panel, _("Audio"), false);
+ make_subtitle_panel ();
+ _content_notebook->AddPage (_subtitle_panel, _("Subtitles"), false);
+ make_timing_panel ();
+ _content_notebook->AddPage (_timing_panel, _("Timing"), false);
+
+ _loop_count->SetRange (2, 1024);
}
void
FilmEditor::make_audio_panel ()
{
- _audio_panel = new wxPanel (_notebook);
- _audio_sizer = new wxBoxSizer (wxVERTICAL);
- _audio_panel->SetSizer (_audio_sizer);
+ _audio_panel = new wxPanel (_content_notebook);
+ wxBoxSizer* audio_sizer = new wxBoxSizer (wxVERTICAL);
+ _audio_panel->SetSizer (audio_sizer);
- wxFlexGridSizer* grid = new wxFlexGridSizer (2, 4, 4);
- _audio_sizer->Add (grid, 0, wxALL, 8);
+ wxFlexGridSizer* grid = new wxFlexGridSizer (3, 4, 4);
+ audio_sizer->Add (grid, 0, wxALL, 8);
_show_audio = new wxButton (_audio_panel, wxID_ANY, _("Show Audio..."));
grid->Add (_show_audio, 1);
grid->AddSpacer (0);
+ grid->AddSpacer (0);
+ add_label_to_sizer (grid, _audio_panel, _("Audio Gain"));
{
- video_control (add_label_to_sizer (grid, _audio_panel, _("Audio Gain")));
wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
_audio_gain = new wxSpinCtrl (_audio_panel);
- s->Add (video_control (_audio_gain), 1);
- video_control (add_label_to_sizer (s, _audio_panel, _("dB")));
- _audio_gain_calculate_button = new wxButton (_audio_panel, wxID_ANY, _("Calculate..."));
- video_control (_audio_gain_calculate_button);
- s->Add (_audio_gain_calculate_button, 1, wxEXPAND);
- grid->Add (s);
+ s->Add (_audio_gain, 1);
+ add_label_to_sizer (s, _audio_panel, _("dB"));
+ grid->Add (s, 1);
}
+
+ _audio_gain_calculate_button = new wxButton (_audio_panel, wxID_ANY, _("Calculate..."));
+ grid->Add (_audio_gain_calculate_button);
+ add_label_to_sizer (grid, _audio_panel, _("Audio Delay"));
{
- video_control (add_label_to_sizer (grid, _audio_panel, _("Audio Delay")));
wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
_audio_delay = new wxSpinCtrl (_audio_panel);
- s->Add (video_control (_audio_delay), 1);
+ s->Add (_audio_delay, 1);
/// TRANSLATORS: this is an abbreviation for milliseconds, the unit of time
- video_control (add_label_to_sizer (s, _audio_panel, _("ms")));
+ add_label_to_sizer (s, _audio_panel, _("ms"));
grid->Add (s);
}
- {
- _use_content_audio = new wxRadioButton (_audio_panel, wxID_ANY, _("Use content's audio"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
- grid->Add (video_control (_use_content_audio));
- wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
- _audio_stream = new wxChoice (_audio_panel, wxID_ANY);
- s->Add (video_control (_audio_stream), 1);
- _audio = new wxStaticText (_audio_panel, wxID_ANY, wxT (""));
- s->Add (video_control (_audio), 1, wxALIGN_CENTER_VERTICAL | wxLEFT, 8);
- grid->Add (s, 1, wxEXPAND);
- }
-
- _use_external_audio = new wxRadioButton (_audio_panel, wxID_ANY, _("Use external audio"));
- grid->Add (_use_external_audio);
grid->AddSpacer (0);
- for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
- add_label_to_sizer (grid, _audio_panel, std_to_wx (audio_channel_name (i)));
- _external_audio[i] = new wxFilePickerCtrl (_audio_panel, wxID_ANY, wxT (""), _("Select Audio File"), wxT ("*.wav"));
- grid->Add (_external_audio[i], 1, wxEXPAND);
- }
+ add_label_to_sizer (grid, _audio_panel, _("Audio Stream"));
+ _audio_stream = new wxChoice (_audio_panel, wxID_ANY);
+ grid->Add (_audio_stream, 1);
+ _audio_description = new wxStaticText (_audio_panel, wxID_ANY, wxT (""));
+ grid->AddSpacer (0);
+
+ grid->Add (_audio_description, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, 8);
+ grid->AddSpacer (0);
+ grid->AddSpacer (0);
+
+ _audio_mapping = new AudioMappingView (_audio_panel);
+ audio_sizer->Add (_audio_mapping, 1, wxEXPAND | wxALL, 6);
_audio_gain->SetRange (-60, 60);
_audio_delay->SetRange (-1000, 1000);
@@ -419,120 +407,107 @@ FilmEditor::make_audio_panel ()
void
FilmEditor::make_subtitle_panel ()
{
- _subtitle_panel = new wxPanel (_notebook);
- _subtitle_sizer = new wxBoxSizer (wxVERTICAL);
- _subtitle_panel->SetSizer (_subtitle_sizer);
+ _subtitle_panel = new wxPanel (_content_notebook);
+ wxBoxSizer* subtitle_sizer = new wxBoxSizer (wxVERTICAL);
+ _subtitle_panel->SetSizer (subtitle_sizer);
wxFlexGridSizer* grid = new wxFlexGridSizer (2, 4, 4);
- _subtitle_sizer->Add (grid, 0, wxALL, 8);
+ subtitle_sizer->Add (grid, 0, wxALL, 8);
_with_subtitles = new wxCheckBox (_subtitle_panel, wxID_ANY, _("With Subtitles"));
- video_control (_with_subtitles);
grid->Add (_with_subtitles, 1);
+ grid->AddSpacer (0);
- _subtitle_stream = new wxChoice (_subtitle_panel, wxID_ANY);
- grid->Add (video_control (_subtitle_stream));
-
{
- video_control (add_label_to_sizer (grid, _subtitle_panel, _("Subtitle Offset")));
+ add_label_to_sizer (grid, _subtitle_panel, _("Subtitle Offset"));
wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
_subtitle_offset = new wxSpinCtrl (_subtitle_panel);
s->Add (_subtitle_offset);
- video_control (add_label_to_sizer (s, _subtitle_panel, _("pixels")));
+ add_label_to_sizer (s, _subtitle_panel, _("pixels"));
grid->Add (s);
}
{
- video_control (add_label_to_sizer (grid, _subtitle_panel, _("Subtitle Scale")));
+ add_label_to_sizer (grid, _subtitle_panel, _("Subtitle Scale"));
wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
_subtitle_scale = new wxSpinCtrl (_subtitle_panel);
- s->Add (video_control (_subtitle_scale));
- video_control (add_label_to_sizer (s, _subtitle_panel, _("%")));
+ s->Add (_subtitle_scale);
+ add_label_to_sizer (s, _subtitle_panel, _("%"));
grid->Add (s);
}
+ add_label_to_sizer (grid, _subtitle_panel, _("Subtitle Stream"));
+ _subtitle_stream = new wxChoice (_subtitle_panel, wxID_ANY);
+ grid->Add (_subtitle_stream, 1, wxEXPAND | wxALL, 6);
+ grid->AddSpacer (0);
+
_subtitle_offset->SetRange (-1024, 1024);
_subtitle_scale->SetRange (1, 1000);
}
+void
+FilmEditor::make_timing_panel ()
+{
+ _timing_panel = new wxPanel (_content_notebook);
+ wxBoxSizer* timing_sizer = new wxBoxSizer (wxVERTICAL);
+ _timing_panel->SetSizer (timing_sizer);
+ wxFlexGridSizer* grid = new wxFlexGridSizer (2, 4, 4);
+ timing_sizer->Add (grid, 0, wxALL, 8);
+
+ add_label_to_sizer (grid, _timing_panel, _("Start time"));
+ _start = new Timecode (_timing_panel);
+ grid->Add (_start);
+ add_label_to_sizer (grid, _timing_panel, _("Length"));
+ _length = new Timecode (_timing_panel);
+ grid->Add (_length);
+}
+
+
/** Called when the left crop widget has been changed */
void
FilmEditor::left_crop_changed (wxCommandEvent &)
{
- if (!_film) {
+ shared_ptr<VideoContent> c = selected_video_content ();
+ if (!c) {
return;
}
- _film->set_left_crop (_left_crop->GetValue ());
+ c->set_left_crop (_left_crop->GetValue ());
}
/** Called when the right crop widget has been changed */
void
FilmEditor::right_crop_changed (wxCommandEvent &)
{
- if (!_film) {
+ shared_ptr<VideoContent> c = selected_video_content ();
+ if (!c) {
return;
}
- _film->set_right_crop (_right_crop->GetValue ());
+ c->set_right_crop (_right_crop->GetValue ());
}
/** Called when the top crop widget has been changed */
void
FilmEditor::top_crop_changed (wxCommandEvent &)
{
- if (!_film) {
+ shared_ptr<VideoContent> c = selected_video_content ();
+ if (!c) {
return;
}
- _film->set_top_crop (_top_crop->GetValue ());
+ c->set_top_crop (_top_crop->GetValue ());
}
/** Called when the bottom crop value has been changed */
void
FilmEditor::bottom_crop_changed (wxCommandEvent &)
{
- if (!_film) {
- return;
- }
-
- _film->set_bottom_crop (_bottom_crop->GetValue ());
-}
-
-/** Called when the content filename has been changed */
-void
-FilmEditor::content_changed (wxCommandEvent &)
-{
- if (!_film) {
- return;
- }
-
- try {
- _film->set_content (wx_to_std (_content->GetPath ()));
- } catch (std::exception& e) {
- _content->SetPath (std_to_wx (_film->directory ()));
- error_dialog (this, wxString::Format (_("Could not set content: %s"), std_to_wx (e.what()).data()));
- }
-}
-
-void
-FilmEditor::trust_content_header_changed (wxCommandEvent &)
-{
- if (!_film) {
+ shared_ptr<VideoContent> c = selected_video_content ();
+ if (!c) {
return;
}
- _film->set_trust_content_header (_trust_content_header->GetValue ());
-}
-
-/** Called when the DCP A/B switch has been toggled */
-void
-FilmEditor::dcp_ab_toggled (wxCommandEvent &)
-{
- if (!_film) {
- return;
- }
-
- _film->set_dcp_ab (_dcp_ab->GetValue ());
+ c->set_bottom_crop (_bottom_crop->GetValue ());
}
/** Called when the name widget has been changed */
@@ -593,7 +568,7 @@ FilmEditor::dcp_frame_rate_changed (wxCommandEvent &)
return;
}
- _film->set_dcp_frame_rate (
+ _film->set_dcp_video_frame_rate (
boost::lexical_cast<int> (
wx_to_std (_dcp_frame_rate->GetString (_dcp_frame_rate->GetSelection ()))
)
@@ -620,116 +595,31 @@ FilmEditor::film_changed (Film::Property p)
case Film::NONE:
break;
case Film::CONTENT:
- checked_set (_content, _film->content ());
- setup_visibility ();
- setup_formats ();
- setup_subtitle_control_sensitivity ();
- setup_streams ();
- setup_show_audio_sensitivity ();
- setup_frame_rate_description ();
- break;
- case Film::TRUST_CONTENT_HEADER:
- checked_set (_trust_content_header, _film->trust_content_header ());
- break;
- case Film::SUBTITLE_STREAMS:
+ setup_content ();
+ setup_ratios ();
+// setup_ratio ();
setup_subtitle_control_sensitivity ();
- setup_streams ();
- break;
- case Film::CONTENT_AUDIO_STREAMS:
- setup_streams ();
setup_show_audio_sensitivity ();
- setup_frame_rate_description ();
- break;
- case Film::FORMAT:
- {
- int n = 0;
- vector<Format const *>::iterator i = _formats.begin ();
- while (i != _formats.end() && *i != _film->format ()) {
- ++i;
- ++n;
- }
- if (i == _formats.end()) {
- checked_set (_format, -1);
- } else {
- checked_set (_format, n);
- }
- setup_dcp_name ();
- setup_scaling_description ();
break;
- }
- case Film::CROP:
- checked_set (_left_crop, _film->crop().left);
- checked_set (_right_crop, _film->crop().right);
- checked_set (_top_crop, _film->crop().top);
- checked_set (_bottom_crop, _film->crop().bottom);
- setup_scaling_description ();
+ case Film::LOOP:
+ checked_set (_loop_content, _film->loop() > 1);
+ checked_set (_loop_count, _film->loop());
+ setup_loop_sensitivity ();
break;
- case Film::FILTERS:
- {
- pair<string, string> p = Filter::ffmpeg_strings (_film->filters ());
- if (p.first.empty () && p.second.empty ()) {
- _filters->SetLabel (_("None"));
- } else {
- string const b = p.first + " " + p.second;
- _filters->SetLabel (std_to_wx (b));
- }
- _film_sizer->Layout ();
+ case Film::CONTAINER:
+ setup_container ();
break;
- }
case Film::NAME:
checked_set (_name, _film->name());
setup_dcp_name ();
break;
- case Film::SOURCE_FRAME_RATE:
- s << fixed << setprecision(2) << _film->source_frame_rate();
- _source_frame_rate->SetLabel (std_to_wx (s.str ()));
- setup_frame_rate_description ();
- break;
- case Film::SIZE:
- setup_scaling_description ();
- break;
- case Film::LENGTH:
- if (_film->source_frame_rate() > 0 && _film->length()) {
- s << _film->length().get() << " "
- << wx_to_std (_("frames")) << "; " << seconds_to_hms (_film->length().get() / _film->source_frame_rate());
- } else if (_film->length()) {
- s << _film->length().get() << " "
- << wx_to_std (_("frames"));
- }
- _length->SetLabel (std_to_wx (s.str ()));
- if (_film->length()) {
- _trim_start->SetRange (0, _film->length().get());
- _trim_end->SetRange (0, _film->length().get());
- }
- break;
case Film::DCP_CONTENT_TYPE:
checked_set (_dcp_content_type, DCPContentType::as_index (_film->dcp_content_type ()));
setup_dcp_name ();
break;
- case Film::DCP_AB:
- checked_set (_dcp_ab, _film->dcp_ab ());
- break;
case Film::SCALER:
checked_set (_scaler, Scaler::as_index (_film->scaler ()));
break;
- case Film::TRIM_START:
- checked_set (_trim_start, _film->trim_start());
- break;
- case Film::TRIM_END:
- checked_set (_trim_end, _film->trim_end());
- break;
- case Film::TRIM_TYPE:
- checked_set (_trim_type, _film->trim_type() == Film::CPL ? 0 : 1);
- break;
- case Film::AUDIO_GAIN:
- checked_set (_audio_gain, _film->audio_gain ());
- break;
- case Film::AUDIO_DELAY:
- checked_set (_audio_delay, _film->audio_delay ());
- break;
- case Film::STILL_DURATION:
- checked_set (_still_duration, _film->still_duration ());
- break;
case Film::WITH_SUBTITLES:
checked_set (_with_subtitles, _film->with_subtitles ());
setup_subtitle_control_sensitivity ();
@@ -754,101 +644,155 @@ FilmEditor::film_changed (Film::Property p)
case Film::DCI_METADATA:
setup_dcp_name ();
break;
- case Film::CONTENT_AUDIO_STREAM:
- if (_film->content_audio_stream()) {
- checked_set (_audio_stream, _film->content_audio_stream()->to_string());
- }
- setup_dcp_name ();
- setup_audio_details ();
- setup_audio_control_sensitivity ();
- setup_show_audio_sensitivity ();
- setup_frame_rate_description ();
- break;
- case Film::USE_CONTENT_AUDIO:
- checked_set (_use_content_audio, _film->use_content_audio());
- checked_set (_use_external_audio, !_film->use_content_audio());
- setup_dcp_name ();
- setup_audio_details ();
- setup_audio_control_sensitivity ();
- setup_show_audio_sensitivity ();
- setup_frame_rate_description ();
- break;
- case Film::SUBTITLE_STREAM:
- if (_film->subtitle_stream()) {
- checked_set (_subtitle_stream, _film->subtitle_stream()->to_string());
- }
- break;
- case Film::EXTERNAL_AUDIO:
+ case Film::DCP_VIDEO_FRAME_RATE:
{
- vector<string> a = _film->external_audio ();
- for (size_t i = 0; i < a.size() && i < MAX_AUDIO_CHANNELS; ++i) {
- checked_set (_external_audio[i], a[i]);
- }
- setup_audio_details ();
- setup_show_audio_sensitivity ();
- setup_frame_rate_description ();
- break;
- }
- case Film::DCP_FRAME_RATE:
+ bool done = false;
for (unsigned int i = 0; i < _dcp_frame_rate->GetCount(); ++i) {
- if (wx_to_std (_dcp_frame_rate->GetString(i)) == boost::lexical_cast<string> (_film->dcp_frame_rate())) {
- if (_dcp_frame_rate->GetSelection() != int(i)) {
- _dcp_frame_rate->SetSelection (i);
- break;
- }
+ if (wx_to_std (_dcp_frame_rate->GetString(i)) == boost::lexical_cast<string> (_film->dcp_video_frame_rate())) {
+ checked_set (_dcp_frame_rate, i);
+ done = true;
+ break;
}
}
- if (_film->source_frame_rate()) {
- _best_dcp_frame_rate->Enable (best_dcp_frame_rate (_film->source_frame_rate ()) != _film->dcp_frame_rate ());
- } else {
- _best_dcp_frame_rate->Disable ();
+ if (!done) {
+ checked_set (_dcp_frame_rate, -1);
}
- setup_frame_rate_description ();
+ _best_dcp_frame_rate->Enable (_film->best_dcp_video_frame_rate () != _film->dcp_video_frame_rate ());
+ break;
+ }
}
}
void
-FilmEditor::setup_frame_rate_description ()
+FilmEditor::film_content_changed (weak_ptr<Content> weak_content, int property)
{
- wxString d;
- int lines = 0;
-
- if (_film->source_frame_rate()) {
- d << std_to_wx (FrameRateConversion (_film->source_frame_rate(), _film->dcp_frame_rate()).description);
- ++lines;
-#ifdef HAVE_SWRESAMPLE
- if (_film->audio_stream() && _film->audio_stream()->sample_rate() != _film->target_audio_sample_rate ()) {
- d << wxString::Format (
- _("Audio will be resampled from %dHz to %dHz\n"),
- _film->audio_stream()->sample_rate(),
- _film->target_audio_sample_rate()
- );
- ++lines;
- }
-#endif
+ if (!_film) {
+ /* We call this method ourselves (as well as using it as a signal handler)
+ so _film can be 0.
+ */
+ return;
}
- for (int i = lines; i < 2; ++i) {
- d << wxT ("\n ");
+ shared_ptr<Content> content = weak_content.lock ();
+ shared_ptr<VideoContent> video_content;
+ shared_ptr<AudioContent> audio_content;
+ shared_ptr<FFmpegContent> ffmpeg_content;
+ if (content) {
+ video_content = dynamic_pointer_cast<VideoContent> (content);
+ audio_content = dynamic_pointer_cast<AudioContent> (content);
+ ffmpeg_content = dynamic_pointer_cast<FFmpegContent> (content);
}
- _frame_rate_description->SetLabel (d);
+ /* We can't use case {} here */
+
+ if (property == ContentProperty::START) {
+ if (content) {
+ _start->set (content->start (), _film->dcp_video_frame_rate ());
+ } else {
+ _start->set (0, 24);
+ }
+ } else if (property == ContentProperty::LENGTH) {
+ if (content) {
+ _length->set (content->length (), _film->dcp_video_frame_rate ());
+ } else {
+ _length->set (0, 24);
+ }
+ } else if (property == VideoContentProperty::VIDEO_CROP) {
+ checked_set (_left_crop, video_content ? video_content->crop().left : 0);
+ checked_set (_right_crop, video_content ? video_content->crop().right : 0);
+ checked_set (_top_crop, video_content ? video_content->crop().top : 0);
+ checked_set (_bottom_crop, video_content ? video_content->crop().bottom : 0);
+ setup_scaling_description ();
+ } else if (property == AudioContentProperty::AUDIO_GAIN) {
+ checked_set (_audio_gain, audio_content ? audio_content->audio_gain() : 0);
+ } else if (property == AudioContentProperty::AUDIO_DELAY) {
+ checked_set (_audio_delay, audio_content ? audio_content->audio_delay() : 0);
+ } else if (property == AudioContentProperty::AUDIO_MAPPING) {
+ _audio_mapping->set (audio_content ? audio_content->audio_mapping () : AudioMapping ());
+ } else if (property == FFmpegContentProperty::SUBTITLE_STREAMS) {
+ _subtitle_stream->Clear ();
+ if (ffmpeg_content) {
+ vector<shared_ptr<FFmpegSubtitleStream> > s = ffmpeg_content->subtitle_streams ();
+ if (s.empty ()) {
+ _subtitle_stream->Enable (false);
+ }
+ for (vector<shared_ptr<FFmpegSubtitleStream> >::iterator i = s.begin(); i != s.end(); ++i) {
+ _subtitle_stream->Append (std_to_wx ((*i)->name), new wxStringClientData (std_to_wx (lexical_cast<string> ((*i)->id))));
+ }
+
+ if (ffmpeg_content->subtitle_stream()) {
+ checked_set (_subtitle_stream, lexical_cast<string> (ffmpeg_content->subtitle_stream()->id));
+ } else {
+ _subtitle_stream->SetSelection (wxNOT_FOUND);
+ }
+ }
+ setup_subtitle_control_sensitivity ();
+ } else if (property == FFmpegContentProperty::AUDIO_STREAMS) {
+ _audio_stream->Clear ();
+ if (ffmpeg_content) {
+ vector<shared_ptr<FFmpegAudioStream> > a = ffmpeg_content->audio_streams ();
+ for (vector<shared_ptr<FFmpegAudioStream> >::iterator i = a.begin(); i != a.end(); ++i) {
+ _audio_stream->Append (std_to_wx ((*i)->name), new wxStringClientData (std_to_wx (lexical_cast<string> ((*i)->id))));
+ }
+
+ if (ffmpeg_content->audio_stream()) {
+ checked_set (_audio_stream, lexical_cast<string> (ffmpeg_content->audio_stream()->id));
+ }
+ }
+ setup_show_audio_sensitivity ();
+ } else if (property == FFmpegContentProperty::AUDIO_STREAM) {
+ setup_dcp_name ();
+ setup_show_audio_sensitivity ();
+ } else if (property == FFmpegContentProperty::FILTERS) {
+ if (ffmpeg_content) {
+ pair<string, string> p = Filter::ffmpeg_strings (ffmpeg_content->filters ());
+ if (p.first.empty () && p.second.empty ()) {
+ _filters->SetLabel (_("None"));
+ } else {
+ string const b = p.first + " " + p.second;
+ _filters->SetLabel (std_to_wx (b));
+ }
+ _dcp_sizer->Layout ();
+ }
+ }
}
-/** Called when the format widget has been changed */
void
-FilmEditor::format_changed (wxCommandEvent &)
+FilmEditor::setup_container ()
+{
+ int n = 0;
+ vector<Ratio const *> ratios = Ratio::all ();
+ vector<Ratio const *>::iterator i = ratios.begin ();
+ while (i != ratios.end() && *i != _film->container ()) {
+ ++i;
+ ++n;
+ }
+
+ if (i == ratios.end()) {
+ checked_set (_container, -1);
+ } else {
+ checked_set (_container, n);
+ }
+
+ setup_dcp_name ();
+ setup_scaling_description ();
+}
+
+/** Called when the container widget has been changed */
+void
+FilmEditor::container_changed (wxCommandEvent &)
{
if (!_film) {
return;
}
- int const n = _format->GetSelection ();
+ int const n = _container->GetSelection ();
if (n >= 0) {
- assert (n < int (_formats.size()));
- _film->set_format (_formats[n]);
+ vector<Ratio const *> ratios = Ratio::all ();
+ assert (n < int (ratios.size()));
+ _film->set_container (ratios[n]);
}
}
@@ -870,12 +814,17 @@ FilmEditor::dcp_content_type_changed (wxCommandEvent &)
void
FilmEditor::set_film (shared_ptr<Film> f)
{
- _film = f;
+ set_things_sensitive (f != 0);
- set_things_sensitive (_film != 0);
+ if (_film == f) {
+ return;
+ }
+
+ _film = f;
if (_film) {
_film->Changed.connect (bind (&FilmEditor::film_changed, this, _1));
+ _film->ContentChanged.connect (bind (&FilmEditor::film_content_changed, this, _1, _2));
}
if (_film) {
@@ -891,34 +840,29 @@ FilmEditor::set_film (shared_ptr<Film> f)
film_changed (Film::NAME);
film_changed (Film::USE_DCI_NAME);
film_changed (Film::CONTENT);
- film_changed (Film::TRUST_CONTENT_HEADER);
+ film_changed (Film::LOOP);
film_changed (Film::DCP_CONTENT_TYPE);
- film_changed (Film::FORMAT);
- film_changed (Film::CROP);
- film_changed (Film::FILTERS);
+ film_changed (Film::CONTAINER);
film_changed (Film::SCALER);
- film_changed (Film::TRIM_START);
- film_changed (Film::TRIM_END);
- film_changed (Film::TRIM_TYPE);
- film_changed (Film::DCP_AB);
- film_changed (Film::CONTENT_AUDIO_STREAM);
- film_changed (Film::EXTERNAL_AUDIO);
- film_changed (Film::USE_CONTENT_AUDIO);
- film_changed (Film::AUDIO_GAIN);
- film_changed (Film::AUDIO_DELAY);
- film_changed (Film::STILL_DURATION);
film_changed (Film::WITH_SUBTITLES);
film_changed (Film::SUBTITLE_OFFSET);
film_changed (Film::SUBTITLE_SCALE);
film_changed (Film::COLOUR_LUT);
film_changed (Film::J2K_BANDWIDTH);
film_changed (Film::DCI_METADATA);
- film_changed (Film::SIZE);
- film_changed (Film::LENGTH);
- film_changed (Film::CONTENT_AUDIO_STREAMS);
- film_changed (Film::SUBTITLE_STREAMS);
- film_changed (Film::SOURCE_FRAME_RATE);
- film_changed (Film::DCP_FRAME_RATE);
+ film_changed (Film::DCP_VIDEO_FRAME_RATE);
+
+ film_content_changed (boost::shared_ptr<Content> (), ContentProperty::START);
+ film_content_changed (boost::shared_ptr<Content> (), ContentProperty::LENGTH);
+ film_content_changed (boost::shared_ptr<Content> (), VideoContentProperty::VIDEO_CROP);
+ film_content_changed (boost::shared_ptr<Content> (), AudioContentProperty::AUDIO_GAIN);
+ film_content_changed (boost::shared_ptr<Content> (), AudioContentProperty::AUDIO_DELAY);
+ film_content_changed (boost::shared_ptr<Content> (), AudioContentProperty::AUDIO_MAPPING);
+ film_content_changed (boost::shared_ptr<Content> (), FFmpegContentProperty::SUBTITLE_STREAMS);
+ film_content_changed (boost::shared_ptr<Content> (), FFmpegContentProperty::SUBTITLE_STREAM);
+ film_content_changed (boost::shared_ptr<Content> (), FFmpegContentProperty::AUDIO_STREAMS);
+ film_content_changed (boost::shared_ptr<Content> (), FFmpegContentProperty::AUDIO_STREAM);
+ film_content_changed (boost::shared_ptr<Content> (), FFmpegContentProperty::FILTERS);
}
/** Updates the sensitivity of lots of widgets to a given value.
@@ -932,41 +876,45 @@ FilmEditor::set_things_sensitive (bool s)
_name->Enable (s);
_use_dci_name->Enable (s);
_edit_dci_button->Enable (s);
- _format->Enable (s);
+ _ratio->Enable (s);
_content->Enable (s);
- _trust_content_header->Enable (s);
_left_crop->Enable (s);
_right_crop->Enable (s);
_top_crop->Enable (s);
_bottom_crop->Enable (s);
_filters_button->Enable (s);
_scaler->Enable (s);
- _audio_stream->Enable (s);
_dcp_content_type->Enable (s);
+ _best_dcp_frame_rate->Enable (s);
_dcp_frame_rate->Enable (s);
- _trim_start->Enable (s);
- _trim_end->Enable (s);
- _trim_type->Enable (s);
- _dcp_ab->Enable (s);
_colour_lut->Enable (s);
_j2k_bandwidth->Enable (s);
_audio_gain->Enable (s);
_audio_gain_calculate_button->Enable (s);
_show_audio->Enable (s);
_audio_delay->Enable (s);
- _still_duration->Enable (s);
setup_subtitle_control_sensitivity ();
- setup_audio_control_sensitivity ();
setup_show_audio_sensitivity ();
+ setup_content_sensitivity ();
}
/** Called when the `Edit filters' button has been clicked */
void
FilmEditor::edit_filters_clicked (wxCommandEvent &)
{
- FilterDialog* d = new FilterDialog (this, _film->filters());
- d->ActiveChanged.connect (bind (&Film::set_filters, _film, _1));
+ shared_ptr<Content> c = selected_content ();
+ if (!c) {
+ return;
+ }
+
+ shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (c);
+ if (!fc) {
+ return;
+ }
+
+ FilterDialog* d = new FilterDialog (this, fc->filters());
+ d->ActiveChanged.connect (bind (&FFmpegContent::set_filters, fc, _1));
d->ShowModal ();
d->Destroy ();
}
@@ -988,106 +936,40 @@ FilmEditor::scaler_changed (wxCommandEvent &)
void
FilmEditor::audio_gain_changed (wxCommandEvent &)
{
- if (!_film) {
+ shared_ptr<AudioContent> ac = selected_audio_content ();
+ if (!ac) {
return;
}
- _film->set_audio_gain (_audio_gain->GetValue ());
+ ac->set_audio_gain (_audio_gain->GetValue ());
}
void
FilmEditor::audio_delay_changed (wxCommandEvent &)
{
- if (!_film) {
+ shared_ptr<AudioContent> ac = selected_audio_content ();
+ if (!ac) {
return;
}
- _film->set_audio_delay (_audio_delay->GetValue ());
-}
-
-wxControl *
-FilmEditor::video_control (wxControl* c)
-{
- _video_controls.push_back (c);
- return c;
-}
-
-wxControl *
-FilmEditor::still_control (wxControl* c)
-{
- _still_controls.push_back (c);
- return c;
+ ac->set_audio_delay (_audio_delay->GetValue ());
}
void
-FilmEditor::setup_visibility ()
+FilmEditor::setup_main_notebook_size ()
{
- ContentType c = VIDEO;
+ _main_notebook->InvalidateBestSize ();
- if (_film) {
- c = _film->content_type ();
- }
+ _content_sizer->Layout ();
+ _content_sizer->SetSizeHints (_content_panel);
+ _dcp_sizer->Layout ();
+ _dcp_sizer->SetSizeHints (_dcp_panel);
- for (list<wxControl*>::iterator i = _video_controls.begin(); i != _video_controls.end(); ++i) {
- (*i)->Show (c == VIDEO);
- }
-
- for (list<wxControl*>::iterator i = _still_controls.begin(); i != _still_controls.end(); ++i) {
- (*i)->Show (c == STILL);
- }
-
- setup_notebook_size ();
-}
-
-void
-FilmEditor::setup_notebook_size ()
-{
- _notebook->InvalidateBestSize ();
-
- _film_sizer->Layout ();
- _film_sizer->SetSizeHints (_film_panel);
- _video_sizer->Layout ();
- _video_sizer->SetSizeHints (_video_panel);
- _audio_sizer->Layout ();
- _audio_sizer->SetSizeHints (_audio_panel);
- _subtitle_sizer->Layout ();
- _subtitle_sizer->SetSizeHints (_subtitle_panel);
-
- _notebook->Fit ();
+ _main_notebook->Fit ();
Fit ();
}
void
-FilmEditor::still_duration_changed (wxCommandEvent &)
-{
- if (!_film) {
- return;
- }
-
- _film->set_still_duration (_still_duration->GetValue ());
-}
-
-void
-FilmEditor::trim_start_changed (wxCommandEvent &)
-{
- if (!_film) {
- return;
- }
-
- _film->set_trim_start (_trim_start->GetValue ());
-}
-
-void
-FilmEditor::trim_end_changed (wxCommandEvent &)
-{
- if (!_film) {
- return;
- }
-
- _film->set_trim_end (_trim_end->GetValue ());
-}
-
-void
FilmEditor::audio_gain_calculate_button_clicked (wxCommandEvent &)
{
GainCalculatorDialog* d = new GainCalculatorDialog (this);
@@ -1115,29 +997,16 @@ FilmEditor::audio_gain_calculate_button_clicked (wxCommandEvent &)
}
void
-FilmEditor::setup_formats ()
+FilmEditor::setup_ratios ()
{
- ContentType c = VIDEO;
-
- if (_film) {
- c = _film->content_type ();
- }
-
- _formats.clear ();
-
- vector<Format const *> fmt = Format::all ();
- for (vector<Format const *>::iterator i = fmt.begin(); i != fmt.end(); ++i) {
- if (c == VIDEO || (c == STILL && dynamic_cast<VariableFormat const *> (*i))) {
- _formats.push_back (*i);
- }
- }
+ _ratios = Ratio::all ();
- _format->Clear ();
- for (vector<Format const *>::iterator i = _formats.begin(); i != _formats.end(); ++i) {
- _format->Append (std_to_wx ((*i)->name ()));
+ _ratio->Clear ();
+ for (vector<Ratio const *>::iterator i = _ratios.begin(); i != _ratios.end(); ++i) {
+ _ratio->Append (std_to_wx ((*i)->nickname ()));
}
- _film_sizer->Layout ();
+ _dcp_sizer->Layout ();
}
void
@@ -1155,7 +1024,7 @@ FilmEditor::setup_subtitle_control_sensitivity ()
{
bool h = false;
if (_generally_sensitive && _film) {
- h = !_film->subtitle_streams().empty();
+ h = _film->has_subtitles ();
}
_with_subtitles->Enable (h);
@@ -1165,27 +1034,11 @@ FilmEditor::setup_subtitle_control_sensitivity ()
j = _film->with_subtitles ();
}
- _subtitle_stream->Enable (j);
_subtitle_offset->Enable (j);
_subtitle_scale->Enable (j);
}
void
-FilmEditor::setup_audio_control_sensitivity ()
-{
- _use_content_audio->Enable (_generally_sensitive && _film && !_film->content_audio_streams().empty());
- _use_external_audio->Enable (_generally_sensitive);
-
- bool const source = _generally_sensitive && _use_content_audio->GetValue();
- bool const external = _generally_sensitive && _use_external_audio->GetValue();
-
- _audio_stream->Enable (source);
- for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
- _external_audio[i]->Enable (external);
- }
-}
-
-void
FilmEditor::use_dci_name_toggled (wxCommandEvent &)
{
if (!_film) {
@@ -1209,143 +1062,185 @@ FilmEditor::edit_dci_button_clicked (wxCommandEvent &)
}
void
-FilmEditor::setup_streams ()
+FilmEditor::active_jobs_changed (bool a)
{
- _audio_stream->Clear ();
- vector<shared_ptr<AudioStream> > a = _film->content_audio_streams ();
- for (vector<shared_ptr<AudioStream> >::iterator i = a.begin(); i != a.end(); ++i) {
- shared_ptr<FFmpegAudioStream> ffa = dynamic_pointer_cast<FFmpegAudioStream> (*i);
- assert (ffa);
- _audio_stream->Append (std_to_wx (ffa->name()), new wxStringClientData (std_to_wx (ffa->to_string ())));
- }
-
- if (_film->use_content_audio() && _film->audio_stream()) {
- checked_set (_audio_stream, _film->audio_stream()->to_string());
- }
+ set_things_sensitive (!a);
+}
- _subtitle_stream->Clear ();
- vector<shared_ptr<SubtitleStream> > s = _film->subtitle_streams ();
- for (vector<shared_ptr<SubtitleStream> >::iterator i = s.begin(); i != s.end(); ++i) {
- _subtitle_stream->Append (std_to_wx ((*i)->name()), new wxStringClientData (std_to_wx ((*i)->to_string ())));
- }
- if (_film->subtitle_stream()) {
- checked_set (_subtitle_stream, _film->subtitle_stream()->to_string());
+void
+FilmEditor::setup_dcp_name ()
+{
+ string s = _film->dcp_name (true);
+ if (s.length() > 28) {
+ _dcp_name->SetLabel (std_to_wx (s.substr (0, 28)) + N_("..."));
+ _dcp_name->SetToolTip (std_to_wx (s));
} else {
- _subtitle_stream->SetSelection (wxNOT_FOUND);
+ _dcp_name->SetLabel (std_to_wx (s));
}
}
void
-FilmEditor::audio_stream_changed (wxCommandEvent &)
+FilmEditor::show_audio_clicked (wxCommandEvent &)
{
- if (!_film) {
- return;
+ if (_audio_dialog) {
+ _audio_dialog->Destroy ();
+ _audio_dialog = 0;
}
-
- _film->set_content_audio_stream (
- audio_stream_factory (
- string_client_data (_audio_stream->GetClientObject (_audio_stream->GetSelection ())),
- Film::state_version
- )
- );
+
+ _audio_dialog = new AudioDialog (this);
+ _audio_dialog->Show ();
+ _audio_dialog->set_film (_film);
}
void
-FilmEditor::subtitle_stream_changed (wxCommandEvent &)
+FilmEditor::best_dcp_frame_rate_clicked (wxCommandEvent &)
{
if (!_film) {
return;
}
+
+ _film->set_dcp_video_frame_rate (_film->best_dcp_video_frame_rate ());
+}
- _film->set_subtitle_stream (
- subtitle_stream_factory (
- string_client_data (_subtitle_stream->GetClientObject (_subtitle_stream->GetSelection ())),
- Film::state_version
- )
- );
+void
+FilmEditor::setup_show_audio_sensitivity ()
+{
+ _show_audio->Enable (_film);
}
void
-FilmEditor::setup_audio_details ()
+FilmEditor::setup_content ()
{
- if (!_film->content_audio_stream()) {
- _audio->SetLabel (wxT (""));
- } else {
- wxString s;
- if (_film->audio_stream()->channels() == 1) {
- s << _("1 channel");
- } else {
- s << _film->audio_stream()->channels () << wxT (" ") << _("channels");
+ string selected_summary;
+ int const s = _content->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+ if (s != -1) {
+ selected_summary = wx_to_std (_content->GetItemText (s));
+ }
+
+ _content->DeleteAllItems ();
+
+ Playlist::ContentList content = _film->content ();
+ for (Playlist::ContentList::iterator i = content.begin(); i != content.end(); ++i) {
+ int const t = _content->GetItemCount ();
+ _content->InsertItem (t, std_to_wx ((*i)->summary ()));
+ if ((*i)->summary() == selected_summary) {
+ _content->SetItemState (t, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
}
- s << wxT (", ") << _film->audio_stream()->sample_rate() << _("Hz");
- _audio->SetLabel (s);
}
- setup_notebook_size ();
+ if (selected_summary.empty () && !content.empty ()) {
+ /* Select the item of content if non was selected before */
+ _content->SetItemState (0, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
+ }
}
void
-FilmEditor::active_jobs_changed (bool a)
+FilmEditor::content_add_clicked (wxCommandEvent &)
{
- set_things_sensitive (!a);
+ wxFileDialog* d = new wxFileDialog (this, _("Choose a file or files"), wxT (""), wxT (""), wxT ("*.*"), wxFD_MULTIPLE);
+ int const r = d->ShowModal ();
+ d->Destroy ();
+
+ if (r != wxID_OK) {
+ return;
+ }
+
+ wxArrayString paths;
+ d->GetPaths (paths);
+
+ for (unsigned int i = 0; i < paths.GetCount(); ++i) {
+ boost::filesystem::path p (wx_to_std (paths[i]));
+
+ shared_ptr<Content> c;
+
+ if (ImageMagickContent::valid_file (p)) {
+ c.reset (new ImageMagickContent (_film, p));
+ } else if (SndfileContent::valid_file (p)) {
+ c.reset (new SndfileContent (_film, p));
+ } else {
+ c.reset (new FFmpegContent (_film, p));
+ }
+
+ _film->examine_and_add_content (c);
+ }
}
void
-FilmEditor::use_audio_changed (wxCommandEvent &)
+FilmEditor::content_remove_clicked (wxCommandEvent &)
{
- _film->set_use_content_audio (_use_content_audio->GetValue());
+ shared_ptr<Content> c = selected_content ();
+ if (c) {
+ _film->remove_content (c);
+ }
}
void
-FilmEditor::external_audio_changed (wxCommandEvent &)
+FilmEditor::content_selection_changed (wxListEvent &)
{
- vector<string> a;
- for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
- a.push_back (wx_to_std (_external_audio[i]->GetPath()));
- }
-
- _film->set_external_audio (a);
+ setup_content_sensitivity ();
+ shared_ptr<Content> s = selected_content ();
+ film_content_changed (s, ContentProperty::START);
+ film_content_changed (s, ContentProperty::LENGTH);
+ film_content_changed (s, VideoContentProperty::VIDEO_CROP);
+ film_content_changed (s, AudioContentProperty::AUDIO_GAIN);
+ film_content_changed (s, AudioContentProperty::AUDIO_DELAY);
+ film_content_changed (s, AudioContentProperty::AUDIO_MAPPING);
+ film_content_changed (s, FFmpegContentProperty::AUDIO_STREAM);
+ film_content_changed (s, FFmpegContentProperty::AUDIO_STREAMS);
+ film_content_changed (s, FFmpegContentProperty::SUBTITLE_STREAM);
}
void
-FilmEditor::setup_dcp_name ()
+FilmEditor::setup_content_sensitivity ()
{
- string s = _film->dcp_name (true);
- if (s.length() > 28) {
- _dcp_name->SetLabel (std_to_wx (s.substr (0, 28)) + N_("..."));
- _dcp_name->SetToolTip (std_to_wx (s));
- } else {
- _dcp_name->SetLabel (std_to_wx (s));
- }
+ _content_add->Enable (_generally_sensitive);
+
+ shared_ptr<Content> selection = selected_content ();
+
+ _content_remove->Enable (selection && _generally_sensitive);
+ _content_timeline->Enable (_generally_sensitive);
+
+ _video_panel->Enable (selection && dynamic_pointer_cast<VideoContent> (selection) && _generally_sensitive);
+ _audio_panel->Enable (selection && dynamic_pointer_cast<AudioContent> (selection) && _generally_sensitive);
+ _subtitle_panel->Enable (selection && dynamic_pointer_cast<FFmpegContent> (selection) && _generally_sensitive);
}
-void
-FilmEditor::show_audio_clicked (wxCommandEvent &)
+shared_ptr<Content>
+FilmEditor::selected_content ()
{
- if (_audio_dialog) {
- _audio_dialog->Destroy ();
- _audio_dialog = 0;
+ int const s = _content->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+ if (s == -1) {
+ return shared_ptr<Content> ();
+ }
+
+ Playlist::ContentList c = _film->content ();
+ if (s < 0 || size_t (s) >= c.size ()) {
+ return shared_ptr<Content> ();
}
- _audio_dialog = new AudioDialog (this);
- _audio_dialog->Show ();
- _audio_dialog->set_film (_film);
+ return c[s];
}
-void
-FilmEditor::best_dcp_frame_rate_clicked (wxCommandEvent &)
+shared_ptr<VideoContent>
+FilmEditor::selected_video_content ()
{
- if (!_film) {
- return;
+ shared_ptr<Content> c = selected_content ();
+ if (!c) {
+ return shared_ptr<VideoContent> ();
}
-
- _film->set_dcp_frame_rate (best_dcp_frame_rate (_film->source_frame_rate ()));
+
+ return dynamic_pointer_cast<VideoContent> (c);
}
-void
-FilmEditor::setup_show_audio_sensitivity ()
+shared_ptr<AudioContent>
+FilmEditor::selected_audio_content ()
{
- _show_audio->Enable (_film && _film->has_audio ());
+ shared_ptr<Content> c = selected_content ();
+ if (!c) {
+ return shared_ptr<AudioContent> ();
+ }
+
+ return dynamic_pointer_cast<AudioContent> (c);
}
void
@@ -1353,20 +1248,22 @@ FilmEditor::setup_scaling_description ()
{
wxString d;
+#if 0
+XXX
int lines = 0;
- if (_film->size().width && _film->size().height) {
+ if (_film->video_size().width && _film->video_size().height) {
d << wxString::Format (
_("Original video is %dx%d (%.2f:1)\n"),
- _film->size().width, _film->size().height,
- float (_film->size().width) / _film->size().height
+ _film->video_size().width, _film->video_size().height,
+ float (_film->video_size().width) / _film->video_size().height
);
++lines;
}
Crop const crop = _film->crop ();
if (crop.left || crop.right || crop.top || crop.bottom) {
- libdcp::Size const cropped = _film->cropped_size (_film->size ());
+ libdcp::Size const cropped = _film->cropped_size (_film->video_size ());
d << wxString::Format (
_("Cropped to %dx%d (%.2f:1)\n"),
cropped.width, cropped.height,
@@ -1401,11 +1298,161 @@ FilmEditor::setup_scaling_description ()
d << wxT ("\n ");
}
+#endif
_scaling_description->SetLabel (d);
}
void
-FilmEditor::trim_type_changed (wxCommandEvent &)
+FilmEditor::loop_content_toggled (wxCommandEvent &)
+{
+ if (_loop_content->GetValue ()) {
+ _film->set_loop (_loop_count->GetValue ());
+ } else {
+ _film->set_loop (1);
+ }
+
+ setup_loop_sensitivity ();
+}
+
+void
+FilmEditor::loop_count_changed (wxCommandEvent &)
+{
+ _film->set_loop (_loop_count->GetValue ());
+}
+
+void
+FilmEditor::setup_loop_sensitivity ()
+{
+ _loop_count->Enable (_loop_content->GetValue ());
+}
+
+void
+FilmEditor::content_timeline_clicked (wxCommandEvent &)
+{
+ if (_timeline_dialog) {
+ _timeline_dialog->Destroy ();
+ _timeline_dialog = 0;
+ }
+
+ _timeline_dialog = new TimelineDialog (this, _film);
+ _timeline_dialog->Show ();
+}
+
+void
+FilmEditor::audio_stream_changed (wxCommandEvent &)
{
- _film->set_trim_type (_trim_type->GetSelection () == 0 ? Film::CPL : Film::ENCODE);
+ shared_ptr<Content> c = selected_content ();
+ if (!c) {
+ return;
+ }
+
+ shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (c);
+ if (!fc) {
+ return;
+ }
+
+ vector<shared_ptr<FFmpegAudioStream> > a = fc->audio_streams ();
+ vector<shared_ptr<FFmpegAudioStream> >::iterator i = a.begin ();
+ string const s = string_client_data (_audio_stream->GetClientObject (_audio_stream->GetSelection ()));
+ while (i != a.end() && lexical_cast<string> ((*i)->id) != s) {
+ ++i;
+ }
+
+ if (i != a.end ()) {
+ fc->set_audio_stream (*i);
+ }
+
+ if (!fc->audio_stream ()) {
+ _audio_description->SetLabel (wxT (""));
+ } else {
+ wxString s;
+ if (fc->audio_channels() == 1) {
+ s << _("1 channel");
+ } else {
+ s << fc->audio_channels() << wxT (" ") << _("channels");
+ }
+ s << wxT (", ") << fc->content_audio_frame_rate() << _("Hz");
+ _audio_description->SetLabel (s);
+ }
+}
+
+
+
+void
+FilmEditor::subtitle_stream_changed (wxCommandEvent &)
+{
+ shared_ptr<Content> c = selected_content ();
+ if (!c) {
+ return;
+ }
+
+ shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (c);
+ if (!fc) {
+ return;
+ }
+
+ vector<shared_ptr<FFmpegSubtitleStream> > a = fc->subtitle_streams ();
+ vector<shared_ptr<FFmpegSubtitleStream> >::iterator i = a.begin ();
+ string const s = string_client_data (_subtitle_stream->GetClientObject (_subtitle_stream->GetSelection ()));
+ while (i != a.end() && lexical_cast<string> ((*i)->id) != s) {
+ ++i;
+ }
+
+ if (i != a.end ()) {
+ fc->set_subtitle_stream (*i);
+ }
+}
+
+void
+FilmEditor::audio_mapping_changed (AudioMapping m)
+{
+ shared_ptr<Content> c = selected_content ();
+ if (!c) {
+ return;
+ }
+
+ shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> (c);
+ if (!ac) {
+ return;
+ }
+
+ ac->set_audio_mapping (m);
+}
+
+void
+FilmEditor::start_changed ()
+{
+ shared_ptr<Content> c = selected_content ();
+ if (!c) {
+ return;
+ }
+
+ c->set_start (_start->get (_film->dcp_video_frame_rate ()));
+}
+
+void
+FilmEditor::length_changed ()
+{
+ shared_ptr<Content> c = selected_content ();
+ if (!c) {
+ return;
+ }
+
+ shared_ptr<ImageMagickContent> ic = dynamic_pointer_cast<ImageMagickContent> (c);
+ if (ic) {
+ ic->set_video_length (_length->get(_film->dcp_video_frame_rate()) * ic->video_frame_rate() / TIME_HZ);
+ }
+}
+
+void
+FilmEditor::set_selection (weak_ptr<Content> wc)
+{
+ Playlist::ContentList content = _film->content ();
+ for (size_t i = 0; i < content.size(); ++i) {
+ if (content[i] == wc.lock ()) {
+ _content->SetItemState (i, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
+ } else {
+ _content->SetItemState (i, 0, wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
+ }
+ }
}
diff --git a/src/wx/film_editor.h b/src/wx/film_editor.h
index e2a4d5836..be1bf7c36 100644
--- a/src/wx/film_editor.h
+++ b/src/wx/film_editor.h
@@ -16,7 +16,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
+
/** @file src/film_editor.h
* @brief A wx widget to edit a film's metadata, and perform various functions.
*/
@@ -29,8 +29,14 @@
#include "lib/film.h"
class wxNotebook;
+class wxListCtrl;
+class wxListEvent;
class Film;
class AudioDialog;
+class TimelineDialog;
+class AudioMappingView;
+class Ratio;
+class Timecode;
/** @class FilmEditor
* @brief A wx widget to edit a film's metadata, and perform various functions.
@@ -41,15 +47,17 @@ public:
FilmEditor (boost::shared_ptr<Film>, wxWindow *);
void set_film (boost::shared_ptr<Film>);
- void setup_visibility ();
+ void set_selection (boost::weak_ptr<Content>);
boost::signals2::signal<void (std::string)> FileChanged;
private:
- void make_film_panel ();
+ void make_dcp_panel ();
+ void make_content_panel ();
void make_video_panel ();
void make_audio_panel ();
void make_subtitle_panel ();
+ void make_timing_panel ();
void connect_to_widgets ();
/* Handle changes to the view */
@@ -60,14 +68,13 @@ private:
void right_crop_changed (wxCommandEvent &);
void top_crop_changed (wxCommandEvent &);
void bottom_crop_changed (wxCommandEvent &);
- void content_changed (wxCommandEvent &);
- void trust_content_header_changed (wxCommandEvent &);
- void format_changed (wxCommandEvent &);
- void trim_start_changed (wxCommandEvent &);
- void trim_end_changed (wxCommandEvent &);
- void trim_type_changed (wxCommandEvent &);
+ void trust_content_headers_changed (wxCommandEvent &);
+ void content_selection_changed (wxListEvent &);
+ void content_add_clicked (wxCommandEvent &);
+ void content_remove_clicked (wxCommandEvent &);
+ void imagemagick_video_length_changed (wxCommandEvent &);
+ void container_changed (wxCommandEvent &);
void dcp_content_type_changed (wxCommandEvent &);
- void dcp_ab_toggled (wxCommandEvent &);
void scaler_changed (wxCommandEvent &);
void audio_gain_changed (wxCommandEvent &);
void audio_gain_calculate_button_clicked (wxCommandEvent &);
@@ -78,116 +85,97 @@ private:
void subtitle_scale_changed (wxCommandEvent &);
void colour_lut_changed (wxCommandEvent &);
void j2k_bandwidth_changed (wxCommandEvent &);
- void still_duration_changed (wxCommandEvent &);
- void audio_stream_changed (wxCommandEvent &);
- void subtitle_stream_changed (wxCommandEvent &);
- void use_audio_changed (wxCommandEvent &);
- void external_audio_changed (wxCommandEvent &);
void dcp_frame_rate_changed (wxCommandEvent &);
void best_dcp_frame_rate_clicked (wxCommandEvent &);
+ void edit_filters_clicked (wxCommandEvent &);
+ void loop_content_toggled (wxCommandEvent &);
+ void loop_count_changed (wxCommandEvent &);
+ void content_timeline_clicked (wxCommandEvent &);
+ void audio_stream_changed (wxCommandEvent &);
+ void subtitle_stream_changed (wxCommandEvent &);
+ void audio_mapping_changed (AudioMapping);
+ void start_changed ();
+ void length_changed ();
/* Handle changes to the model */
void film_changed (Film::Property);
-
- /* Button clicks */
- void edit_filters_clicked (wxCommandEvent &);
+ void film_content_changed (boost::weak_ptr<Content>, int);
void set_things_sensitive (bool);
- void setup_formats ();
+ void setup_ratios ();
void setup_subtitle_control_sensitivity ();
- void setup_audio_control_sensitivity ();
- void setup_streams ();
- void setup_audio_details ();
void setup_dcp_name ();
void setup_show_audio_sensitivity ();
void setup_scaling_description ();
- void setup_notebook_size ();
- void setup_frame_rate_description ();
+ void setup_main_notebook_size ();
+ void setup_content ();
+ void setup_container ();
+ void setup_content_sensitivity ();
+ void setup_loop_sensitivity ();
- wxControl* video_control (wxControl *);
- wxControl* still_control (wxControl *);
-
void active_jobs_changed (bool);
-
- wxNotebook* _notebook;
- wxPanel* _film_panel;
- wxSizer* _film_sizer;
+ boost::shared_ptr<Content> selected_content ();
+ boost::shared_ptr<VideoContent> selected_video_content ();
+ boost::shared_ptr<AudioContent> selected_audio_content ();
+
+ wxNotebook* _main_notebook;
+ wxNotebook* _content_notebook;
+ wxPanel* _dcp_panel;
+ wxSizer* _dcp_sizer;
+ wxPanel* _content_panel;
+ wxSizer* _content_sizer;
wxPanel* _video_panel;
- wxSizer* _video_sizer;
wxPanel* _audio_panel;
- wxSizer* _audio_sizer;
wxPanel* _subtitle_panel;
- wxSizer* _subtitle_sizer;
+ wxPanel* _timing_panel;
/** The film we are editing */
boost::shared_ptr<Film> _film;
- /** The Film's name */
wxTextCtrl* _name;
wxStaticText* _dcp_name;
wxCheckBox* _use_dci_name;
+ wxChoice* _container;
+ wxListCtrl* _content;
+ wxButton* _content_add;
+ wxButton* _content_remove;
+ wxButton* _content_earlier;
+ wxButton* _content_later;
+ wxButton* _content_timeline;
+ wxCheckBox* _loop_content;
+ wxSpinCtrl* _loop_count;
wxButton* _edit_dci_button;
- /** The Film's format */
- wxChoice* _format;
+ wxChoice* _ratio;
+ wxStaticText* _ratio_description;
wxStaticText* _scaling_description;
- /** The Film's content file */
- wxFilePickerCtrl* _content;
- wxCheckBox* _trust_content_header;
- /** The Film's left crop */
wxSpinCtrl* _left_crop;
- /** The Film's right crop */
wxSpinCtrl* _right_crop;
- /** The Film's top crop */
wxSpinCtrl* _top_crop;
- /** The Film's bottom crop */
wxSpinCtrl* _bottom_crop;
- /** Currently-applied filters */
wxStaticText* _filters;
- /** Button to open the filters dialogue */
wxButton* _filters_button;
- /** The Film's scaler */
wxChoice* _scaler;
- wxRadioButton* _use_content_audio;
- wxChoice* _audio_stream;
- wxRadioButton* _use_external_audio;
- wxFilePickerCtrl* _external_audio[MAX_AUDIO_CHANNELS];
- /** The Film's audio gain */
wxSpinCtrl* _audio_gain;
- /** A button to open the gain calculation dialogue */
wxButton* _audio_gain_calculate_button;
wxButton* _show_audio;
- /** The Film's audio delay */
wxSpinCtrl* _audio_delay;
wxCheckBox* _with_subtitles;
- wxChoice* _subtitle_stream;
wxSpinCtrl* _subtitle_offset;
wxSpinCtrl* _subtitle_scale;
wxChoice* _colour_lut;
wxSpinCtrl* _j2k_bandwidth;
- /** The Film's DCP content type */
wxChoice* _dcp_content_type;
- /** The Film's source frame rate */
- wxStaticText* _source_frame_rate;
wxChoice* _dcp_frame_rate;
wxButton* _best_dcp_frame_rate;
- wxStaticText* _frame_rate_description;
- /** The Film's length */
- wxStaticText* _length;
- /** The Film's audio details */
- wxStaticText* _audio;
- /** The Film's duration for still sources */
- wxSpinCtrl* _still_duration;
-
- wxSpinCtrl* _trim_start;
- wxSpinCtrl* _trim_end;
- wxChoice* _trim_type;
- /** Selector to generate an A/B comparison DCP */
- wxCheckBox* _dcp_ab;
-
- std::list<wxControl*> _video_controls;
- std::list<wxControl*> _still_controls;
+ wxChoice* _audio_stream;
+ wxStaticText* _audio_description;
+ wxChoice* _subtitle_stream;
+ AudioMappingView* _audio_mapping;
+ Timecode* _start;
+ Timecode* _length;
- std::vector<Format const *> _formats;
+ std::vector<Ratio const *> _ratios;
bool _generally_sensitive;
AudioDialog* _audio_dialog;
+ TimelineDialog* _timeline_dialog;
};
diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc
index 6845031cf..e1471d94e 100644
--- a/src/wx/film_viewer.cc
+++ b/src/wx/film_viewer.cc
@@ -25,16 +25,18 @@
#include <iomanip>
#include <wx/tglbtn.h>
#include "lib/film.h"
-#include "lib/format.h"
+#include "lib/ratio.h"
#include "lib/util.h"
#include "lib/job_manager.h"
-#include "lib/options.h"
-#include "lib/subtitle.h"
#include "lib/image.h"
#include "lib/scaler.h"
#include "lib/exceptions.h"
#include "lib/examine_content_job.h"
#include "lib/filter.h"
+#include "lib/player.h"
+#include "lib/video_content.h"
+#include "lib/ffmpeg_content.h"
+#include "lib/imagemagick_content.h"
#include "film_viewer.h"
#include "wx_util.h"
#include "video_decoder.h"
@@ -45,6 +47,8 @@ using std::max;
using std::cout;
using std::list;
using boost::shared_ptr;
+using boost::dynamic_pointer_cast;
+using boost::weak_ptr;
using libdcp::Size;
FilmViewer::FilmViewer (shared_ptr<Film> f, wxWindow* p)
@@ -111,49 +115,26 @@ void
FilmViewer::film_changed (Film::Property p)
{
switch (p) {
- case Film::FORMAT:
+ case Film::CONTAINER:
calculate_sizes ();
update_from_raw ();
break;
case Film::CONTENT:
{
- DecodeOptions o;
- o.decode_audio = false;
- o.decode_subtitles = true;
- o.video_sync = false;
-
- try {
- _decoders = decoder_factory (_film, o);
- } catch (StringError& e) {
- error_dialog (this, wxString::Format (_("Could not open content file (%s)"), std_to_wx(e.what()).data()));
- return;
- }
-
- if (_decoders.video == 0) {
- break;
- }
- _decoders.video->set_subtitle_stream (_film->subtitle_stream());
- _decoders.video->Video.connect (bind (&FilmViewer::process_video, this, _1, _2, _3, _4));
- _decoders.video->OutputChanged.connect (boost::bind (&FilmViewer::decoder_changed, this));
calculate_sizes ();
- get_frame ();
- _panel->Refresh ();
- _slider->Show (_film->content_type() == VIDEO);
- _play_button->Show (_film->content_type() == VIDEO);
- _v_sizer->Layout ();
+ wxScrollEvent ev;
+ slider_moved (ev);
break;
}
case Film::WITH_SUBTITLES:
case Film::SUBTITLE_OFFSET:
case Film::SUBTITLE_SCALE:
- case Film::SCALER:
- case Film::FILTERS:
- update_from_raw ();
+ raw_to_display ();
+ _panel->Refresh ();
+ _panel->Update ();
break;
- case Film::SUBTITLE_STREAM:
- if (_decoders.video) {
- _decoders.video->set_subtitle_stream (_film->subtitle_stream ());
- }
+ case Film::SCALER:
+ update_from_decoder ();
break;
default:
break;
@@ -166,7 +147,7 @@ FilmViewer::set_film (shared_ptr<Film> f)
if (_film == f) {
return;
}
-
+
_film = f;
_raw_frame.reset ();
@@ -178,23 +159,32 @@ FilmViewer::set_film (shared_ptr<Film> f)
return;
}
+ _player = f->player ();
+ _player->disable_audio ();
+ /* Don't disable subtitles here as we may need them, and it's nice to be able to turn them
+ on and off without needing obtain a new Player.
+ */
+
+ _player->Video.connect (bind (&FilmViewer::process_video, this, _1, _2, _3));
+
_film->Changed.connect (boost::bind (&FilmViewer::film_changed, this, _1));
+ _film->ContentChanged.connect (boost::bind (&FilmViewer::film_content_changed, this, _1, _2));
film_changed (Film::CONTENT);
- film_changed (Film::FORMAT);
+ film_changed (Film::CONTAINER);
film_changed (Film::WITH_SUBTITLES);
film_changed (Film::SUBTITLE_OFFSET);
film_changed (Film::SUBTITLE_SCALE);
- film_changed (Film::SUBTITLE_STREAM);
}
void
-FilmViewer::decoder_changed ()
+FilmViewer::update_from_decoder ()
{
- if (_decoders.video == 0 || _decoders.video->seek_to_last ()) {
+ if (!_player) {
return;
}
+ _player->seek (_player->position ());
get_frame ();
_panel->Refresh ();
_panel->Update ();
@@ -203,14 +193,14 @@ FilmViewer::decoder_changed ()
void
FilmViewer::timer (wxTimerEvent &)
{
- if (!_film || !_decoders.video) {
+ if (!_player) {
return;
}
get_frame ();
if (_film->length()) {
- int const new_slider_position = 4096 * _decoders.video->last_source_time() / (_film->length().get() / _film->source_frame_rate());
+ int const new_slider_position = 4096 * _player->position() / _film->length();
if (new_slider_position != _slider->GetValue()) {
_slider->SetValue (new_slider_position);
}
@@ -242,12 +232,6 @@ FilmViewer::paint_panel (wxPaintEvent &)
wxBitmap frame_bitmap (frame);
dc.DrawBitmap (frame_bitmap, _display_frame_x, 0);
- if (_film->with_subtitles() && _display_sub) {
- wxImage sub (_display_sub->size().width, _display_sub->size().height, _display_sub->data()[0], _display_sub->alpha(), true);
- wxBitmap sub_bitmap (sub);
- dc.DrawBitmap (sub_bitmap, _display_sub_position.x, _display_sub_position.y);
- }
-
if (_out_size.width < _panel_size.width) {
wxPen p (GetBackgroundColour ());
wxBrush b (GetBackgroundColour ());
@@ -269,12 +253,10 @@ FilmViewer::paint_panel (wxPaintEvent &)
void
FilmViewer::slider_moved (wxScrollEvent &)
{
- if (!_film || !_film->length() || !_decoders.video) {
- return;
- }
+ cout << "slider " << _slider->GetValue() << " " << _film->length() << "\n";
- if (_decoders.video->seek (_slider->GetValue() * _film->length().get() / (4096 * _film->source_frame_rate()))) {
- return;
+ if (_film && _player) {
+ _player->seek (_slider->GetValue() * _film->length() / 4096);
}
get_frame ();
@@ -311,49 +293,21 @@ FilmViewer::raw_to_display ()
return;
}
- boost::shared_ptr<const Image> input = _raw_frame;
-
- pair<string, string> const s = Filter::ffmpeg_strings (_film->filters());
- if (!s.second.empty ()) {
- input = input->post_process (s.second, true);
- }
-
/* Get a compacted image as we have to feed it to wxWidgets */
- _display_frame = input->scale_and_convert_to_rgb (_film_size, 0, _film->scaler(), false);
-
- if (_raw_sub) {
-
- /* Our output is already cropped by the decoder, so we need to account for that
- when working out the scale that we are applying.
- */
-
- Size const cropped_size = _film->cropped_size (_film->size ());
-
- dvdomatic::Rect tx = subtitle_transformed_area (
- float (_film_size.width) / cropped_size.width,
- float (_film_size.height) / cropped_size.height,
- _raw_sub->area(), _film->subtitle_offset(), _film->subtitle_scale()
- );
-
- _display_sub.reset (new RGBPlusAlphaImage (_raw_sub->image()->scale (tx.size(), _film->scaler(), false)));
- _display_sub_position = tx.position();
- _display_sub_position.x += _display_frame_x;
- } else {
- _display_sub.reset ();
- }
+ _display_frame = _raw_frame->scale_and_convert_to_rgb (_film_size, _film->scaler(), false);
}
void
FilmViewer::calculate_sizes ()
{
- if (!_film) {
+ if (!_film || !_player) {
return;
}
- Format const * format = _film->format ();
+ Ratio const * container = _film->container ();
float const panel_ratio = static_cast<float> (_panel_size.width) / _panel_size.height;
- float const film_ratio = format ? format->container_ratio () : 1.78;
+ float const film_ratio = container ? container->ratio () : 1.78;
if (panel_ratio < film_ratio) {
/* panel is less widscreen than the film; clamp width */
@@ -369,9 +323,9 @@ FilmViewer::calculate_sizes ()
of our _display_frame.
*/
_display_frame_x = 0;
- if (format) {
- _display_frame_x = static_cast<float> (format->dcp_padding (_film)) * _out_size.width / format->dcp_size().width;
- }
+// if (format) {
+// _display_frame_x = static_cast<float> (format->dcp_padding (_film)) * _out_size.width / format->dcp_size().width;
+// }
_film_size = _out_size;
_film_size.width -= _display_frame_x * 2;
@@ -391,32 +345,31 @@ FilmViewer::play_clicked (wxCommandEvent &)
void
FilmViewer::check_play_state ()
{
- if (!_film) {
+ if (!_film || _film->dcp_video_frame_rate() == 0) {
return;
}
if (_play_button->GetValue()) {
- _timer.Start (1000 / _film->source_frame_rate());
+ _timer.Start (1000 / _film->dcp_video_frame_rate());
} else {
_timer.Stop ();
}
}
void
-FilmViewer::process_video (shared_ptr<const Image> image, bool, shared_ptr<Subtitle> sub, double t)
+FilmViewer::process_video (shared_ptr<const Image> image, bool, Time t)
{
_raw_frame = image;
- _raw_sub = sub;
raw_to_display ();
_got_frame = true;
- double const fps = _decoders.video->frames_per_second ();
+ double const fps = _film->dcp_video_frame_rate ();
/* Count frame number from 1 ... not sure if this is the best idea */
- _frame->SetLabel (wxString::Format (wxT("%d"), int (rint (t * fps)) + 1));
+ _frame->SetLabel (wxString::Format (wxT("%d"), int (rint (t * fps / TIME_HZ)) + 1));
- double w = t;
+ double w = static_cast<double>(t) / TIME_HZ;
int const h = (w / 3600);
w -= h * 3600;
int const m = (w / 60);
@@ -427,13 +380,16 @@ FilmViewer::process_video (shared_ptr<const Image> image, bool, shared_ptr<Subti
_timecode->SetLabel (wxString::Format (wxT("%02d:%02d:%02d:%02d"), h, m, s, f));
}
+/** Get a new _raw_frame from the decoder and then do
+ * raw_to_display ().
+ */
void
FilmViewer::get_frame ()
{
/* Clear our raw frame in case we don't get a new one */
_raw_frame.reset ();
- if (_decoders.video == 0) {
+ if (!_player) {
_display_frame.reset ();
return;
}
@@ -441,7 +397,7 @@ FilmViewer::get_frame ()
try {
_got_frame = false;
while (!_got_frame) {
- if (_decoders.video->pass ()) {
+ if (_player->pass ()) {
/* We didn't get a frame before the decoder gave up,
so clear our display frame.
*/
@@ -477,13 +433,25 @@ FilmViewer::active_jobs_changed (bool a)
}
void
+FilmViewer::film_content_changed (weak_ptr<Content>, int p)
+{
+ if (p == ContentProperty::LENGTH) {
+ /* Force an update to our frame */
+ wxScrollEvent ev;
+ slider_moved (ev);
+ } else if (p == VideoContentProperty::VIDEO_CROP) {
+ update_from_decoder ();
+ }
+}
+
+void
FilmViewer::back_clicked (wxCommandEvent &)
{
- if (!_decoders.video) {
+ if (!_player) {
return;
}
- _decoders.video->seek_back ();
+ _player->seek_back ();
get_frame ();
_panel->Refresh ();
_panel->Update ();
@@ -492,11 +460,11 @@ FilmViewer::back_clicked (wxCommandEvent &)
void
FilmViewer::forward_clicked (wxCommandEvent &)
{
- if (!_decoders.video) {
+ if (!_player) {
return;
}
- _decoders.video->seek_forward ();
+ _player->seek_forward ();
get_frame ();
_panel->Refresh ();
_panel->Update ();
diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h
index ed5874fbc..39755ed35 100644
--- a/src/wx/film_viewer.h
+++ b/src/wx/film_viewer.h
@@ -23,16 +23,31 @@
#include <wx/wx.h>
#include "lib/film.h"
-#include "lib/decoder_factory.h"
class wxToggleButton;
class FFmpegPlayer;
class Image;
class RGBPlusAlphaImage;
-class Subtitle;
/** @class FilmViewer
* @brief A wx widget to view a preview of a Film.
+ *
+ * The film takes the following path through the viewer:
+ *
+ * 1. get_frame() asks our _player to decode some data. If it does, process_video()
+ * will be called.
+ *
+ * 2. process_video() takes the image from the decoder (_raw_frame) and calls raw_to_display().
+ *
+ * 3. raw_to_display() copies _raw_frame to _display_frame, processing it and scaling it.
+ *
+ * 4. calling _panel->Refresh() and _panel->Update() results in paint_panel() being called;
+ * this creates frame_bitmap from _display_frame and blits it to the display.
+ *
+ * update_from_decoder() asks the player to re-emit its current frame on the next pass(), and then
+ * starts from step #1.
+ *
+ * update_from_raw() starts at step #3, then calls _panel->Refresh and _panel->Update.
*/
class FilmViewer : public wxPanel
{
@@ -43,16 +58,17 @@ public:
private:
void film_changed (Film::Property);
+ void film_content_changed (boost::weak_ptr<Content>, int);
void paint_panel (wxPaintEvent &);
void panel_sized (wxSizeEvent &);
void slider_moved (wxScrollEvent &);
void play_clicked (wxCommandEvent &);
void timer (wxTimerEvent &);
- void process_video (boost::shared_ptr<const Image>, bool, boost::shared_ptr<Subtitle>, double);
+ void process_video (boost::shared_ptr<const Image>, bool, Time);
void calculate_sizes ();
void check_play_state ();
void update_from_raw ();
- void decoder_changed ();
+ void update_from_decoder ();
void raw_to_display ();
void get_frame ();
void active_jobs_changed (bool);
@@ -60,6 +76,7 @@ private:
void forward_clicked (wxCommandEvent &);
boost::shared_ptr<Film> _film;
+ boost::shared_ptr<Player> _player;
wxSizer* _v_sizer;
wxPanel* _panel;
@@ -71,16 +88,12 @@ private:
wxToggleButton* _play_button;
wxTimer _timer;
- Decoders _decoders;
boost::shared_ptr<const Image> _raw_frame;
- boost::shared_ptr<Subtitle> _raw_sub;
boost::shared_ptr<const Image> _display_frame;
/* The x offset at which we display the actual film content; this corresponds
to the film's padding converted to our coordinates.
*/
int _display_frame_x;
- boost::shared_ptr<RGBPlusAlphaImage> _display_sub;
- Position _display_sub_position;
bool _got_frame;
/** Size of our output (including padding if we have any) */
diff --git a/src/wx/imagemagick_content_dialog.cc b/src/wx/imagemagick_content_dialog.cc
new file mode 100644
index 000000000..52f3cf1a7
--- /dev/null
+++ b/src/wx/imagemagick_content_dialog.cc
@@ -0,0 +1,72 @@
+/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */
+
+/*
+ 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/spinctrl.h>
+#include "lib/imagemagick_content.h"
+#include "imagemagick_content_dialog.h"
+#include "wx_util.h"
+
+using boost::shared_ptr;
+using boost::dynamic_pointer_cast;
+
+ImageMagickContentDialog::ImageMagickContentDialog (wxWindow* parent, shared_ptr<ImageMagickContent> content)
+ : wxDialog (parent, wxID_ANY, _("Image"))
+ , _content (content)
+{
+ wxFlexGridSizer* grid = new wxFlexGridSizer (3, 6, 6);
+ grid->AddGrowableCol (1, 1);
+
+ {
+ add_label_to_sizer (grid, this, (_("Duration")));
+ wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
+ _video_length = new wxSpinCtrl (this);
+ s->Add (_video_length);
+ /// TRANSLATORS: this is an abbreviation for seconds, the unit of time
+ add_label_to_sizer (s, this, _("s"));
+ grid->Add (s);
+ }
+
+ wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL);
+ overall_sizer->Add (grid, 1, wxEXPAND | wxALL, 6);
+
+ wxSizer* buttons = CreateSeparatedButtonSizer (wxOK);
+ if (buttons) {
+ overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
+ }
+
+ SetSizer (overall_sizer);
+ overall_sizer->Layout ();
+ overall_sizer->SetSizeHints (this);
+
+ checked_set (_video_length, content->video_length () / 24);
+ _video_length->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (ImageMagickContentDialog::video_length_changed), 0, this);
+}
+
+void
+ImageMagickContentDialog::video_length_changed (wxCommandEvent &)
+{
+ shared_ptr<ImageMagickContent> c = _content.lock ();
+ if (!c) {
+ return;
+ }
+
+ c->set_video_length (_video_length->GetValue() * 24);
+}
diff --git a/src/wx/imagemagick_content_dialog.h b/src/wx/imagemagick_content_dialog.h
new file mode 100644
index 000000000..9a4ea2694
--- /dev/null
+++ b/src/wx/imagemagick_content_dialog.h
@@ -0,0 +1,38 @@
+/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */
+
+/*
+ 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 wxSpinCtrl;
+class ImageMagickContent;
+class Region;
+
+class ImageMagickContentDialog : public wxDialog
+{
+public:
+ ImageMagickContentDialog (wxWindow *, boost::shared_ptr<ImageMagickContent>);
+
+private:
+ void video_length_changed (wxCommandEvent &);
+
+ boost::weak_ptr<ImageMagickContent> _content;
+ wxSpinCtrl* _video_length;
+};
diff --git a/src/wx/job_manager_view.cc b/src/wx/job_manager_view.cc
index 5cd9f2e15..1594dfc91 100644
--- a/src/wx/job_manager_view.cc
+++ b/src/wx/job_manager_view.cc
@@ -86,6 +86,7 @@ JobManagerView::update ()
JobRecord r;
int n = 1;
r.finalised = false;
+ r.scroll_nudged = false;
r.gauge = new wxGauge (_panel, wxID_ANY, 100);
_table->Insert (index + n, r.gauge, 1, wxEXPAND | wxLEFT | wxRIGHT);
++n;
@@ -113,6 +114,7 @@ JobManagerView::update ()
++n;
_job_records[*i] = r;
+
}
string const st = (*i)->status ();
@@ -126,8 +128,25 @@ JobManagerView::update ()
checked_set (_job_records[*i].message, wx_to_std (_("Running")));
_job_records[*i].gauge->Pulse ();
}
+
}
+ if (!_job_records[*i].scroll_nudged && ((*i)->running () || (*i)->finished())) {
+ int x, y;
+ _job_records[*i].gauge->GetPosition (&x, &y);
+ int px, py;
+ GetScrollPixelsPerUnit (&px, &py);
+ int vx, vy;
+ GetViewStart (&vx, &vy);
+ int sx, sy;
+ GetClientSize (&sx, &sy);
+
+ if (y > (vy * py + sy / 2)) {
+ Scroll (-1, y / py);
+ _job_records[*i].scroll_nudged = true;
+ }
+ }
+
if ((*i)->finished() && !_job_records[*i].finalised) {
checked_set (_job_records[*i].message, st);
if (!(*i)->finished_cancelled()) {
@@ -156,7 +175,7 @@ JobManagerView::details_clicked (wxCommandEvent& ev)
{
wxObject* o = ev.GetEventObject ();
- for (map<boost::shared_ptr<Job>, JobRecord>::iterator i = _job_records.begin(); i != _job_records.end(); ++i) {
+ for (map<shared_ptr<Job>, JobRecord>::iterator i = _job_records.begin(); i != _job_records.end(); ++i) {
if (i->second.details == o) {
string s = i->first->error_summary();
s[0] = toupper (s[0]);
@@ -170,7 +189,7 @@ JobManagerView::cancel_clicked (wxCommandEvent& ev)
{
wxObject* o = ev.GetEventObject ();
- for (map<boost::shared_ptr<Job>, JobRecord>::iterator i = _job_records.begin(); i != _job_records.end(); ++i) {
+ for (map<shared_ptr<Job>, JobRecord>::iterator i = _job_records.begin(); i != _job_records.end(); ++i) {
if (i->second.cancel == o) {
i->first->cancel ();
}
diff --git a/src/wx/job_manager_view.h b/src/wx/job_manager_view.h
index fc29eadb4..3d1ad30c0 100644
--- a/src/wx/job_manager_view.h
+++ b/src/wx/job_manager_view.h
@@ -57,6 +57,7 @@ private:
wxButton* pause;
wxButton* details;
bool finalised;
+ bool scroll_nudged;
};
std::map<boost::shared_ptr<Job>, JobRecord> _job_records;
diff --git a/src/wx/po/es_ES.po b/src/wx/po/es_ES.po
index efc8436c5..bf5dce4b0 100644
--- a/src/wx/po/es_ES.po
+++ b/src/wx/po/es_ES.po
@@ -5,7 +5,7 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: libdvdomatic-wx\n"
+"Project-Id-Version: libdcpomatic-wx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-05-09 09:51+0100\n"
"PO-Revision-Date: 2013-04-02 19:08-0500\n"
@@ -21,7 +21,6 @@ msgstr ""
msgid "%"
msgstr "%"
-#: src/wx/config_dialog.cc:98
msgid "(restart DCP-o-matic to see language changes)"
msgstr ""
@@ -149,19 +148,18 @@ msgstr "Velocidad DCP"
msgid "DCP Name"
msgstr "Nombre DCP"
-#: src/wx/config_dialog.cc:46
-#, fuzzy
-msgid "DCP-o-matic Preferences"
-msgstr "Preferencias DVD-o-matic"
+#: src/wx/wx_util.cc:61
+msgid "DCP-o-matic"
+msgstr "DCP-o-matic"
-#: src/wx/wx_util.cc:63 src/wx/wx_util.cc:71
-msgid "DVD-o-matic"
-msgstr "DVD-o-matic"
+#: src/wx/config_dialog.cc:44
+msgid "DCP-o-matic Preferences"
+msgstr "Preferencias DCP-o-matic"
#: src/wx/audio_dialog.cc:101
#, fuzzy, c-format
-msgid "DVD-o-matic audio - %s"
-msgstr "Audio DVD-o-matic - %1"
+msgid "DCP-o-matic audio - %s"
+msgstr "Audio DCP-o-matic - %1"
#: src/wx/config_dialog.cc:120
msgid "Default DCI name details"
diff --git a/src/wx/po/fr_FR.po b/src/wx/po/fr_FR.po
index ad138d45a..aee97956f 100644
--- a/src/wx/po/fr_FR.po
+++ b/src/wx/po/fr_FR.po
@@ -5,7 +5,7 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: DVD-o-matic FRENCH\n"
+"Project-Id-Version: DCP-o-matic FRENCH\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-05-09 09:51+0100\n"
"PO-Revision-Date: 2013-05-10 14:19+0100\n"
@@ -148,19 +148,18 @@ msgstr "Cadence image du DCP"
msgid "DCP Name"
msgstr "Nom du DCP"
-#: src/wx/config_dialog.cc:46
-msgid "DCP-o-matic Preferences"
-msgstr "Préférences de DCP-o-matic"
+#: src/wx/wx_util.cc:61
+msgid "DCP-o-matic"
+msgstr "DCP-o-matic"
-#: src/wx/wx_util.cc:63
-#: src/wx/wx_util.cc:71
-msgid "DVD-o-matic"
-msgstr "DVD-o-matic"
+#: src/wx/config_dialog.cc:44
+msgid "DCP-o-matic Preferences"
+msgstr "Préférences DCP-o-matic"
#: src/wx/audio_dialog.cc:101
#, c-format
-msgid "DVD-o-matic audio - %s"
-msgstr "Son DVD-o-matic - %s"
+msgid "DCP-o-matic audio - %s"
+msgstr "Son DCP-o-matic - %s"
#: src/wx/config_dialog.cc:120
msgid "Default DCI name details"
diff --git a/src/wx/po/it_IT.po b/src/wx/po/it_IT.po
index 37ee492fe..f667a6f21 100644
--- a/src/wx/po/it_IT.po
+++ b/src/wx/po/it_IT.po
@@ -21,10 +21,9 @@ msgstr ""
msgid "%"
msgstr "%"
-#: src/wx/config_dialog.cc:98
-#, fuzzy
+#: src/wx/config_dialog.cc:61
msgid "(restart DCP-o-matic to see language changes)"
-msgstr "(riavviare DVD-o-matic per vedere i cambiamenti di lingua)"
+msgstr "(riavviare DCP-o-matic per vedere i cambiamenti di lingua)"
#: src/wx/film_editor.cc:1276
msgid "1 channel"
@@ -150,19 +149,18 @@ msgstr "Frequenza fotogrammi del DCP"
msgid "DCP Name"
msgstr "Nome del DCP"
-#: src/wx/config_dialog.cc:46
-#, fuzzy
-msgid "DCP-o-matic Preferences"
-msgstr "Preferenze DVD-o-matic"
+#: src/wx/wx_util.cc:61
+msgid "DCP-o-matic"
+msgstr "DCP-o-matic"
-#: src/wx/wx_util.cc:63 src/wx/wx_util.cc:71
-msgid "DVD-o-matic"
-msgstr "DVD-o-matic"
+#: src/wx/config_dialog.cc:44
+msgid "DCP-o-matic Preferences"
+msgstr "Preferenze DCP-o-matic"
#: src/wx/audio_dialog.cc:101
#, c-format
-msgid "DVD-o-matic audio - %s"
-msgstr "Audio DVD-o-matic - %s"
+msgid "DCP-o-matic audio - %s"
+msgstr "Audio DCP-o-matic - %s"
#: src/wx/config_dialog.cc:120
msgid "Default DCI name details"
diff --git a/src/wx/po/sv_SE.po b/src/wx/po/sv_SE.po
index 7c10aebcb..f31d98c38 100644
--- a/src/wx/po/sv_SE.po
+++ b/src/wx/po/sv_SE.po
@@ -5,7 +5,7 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: DVD-o-matic\n"
+"Project-Id-Version: DCP-o-matic\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-05-09 09:51+0100\n"
"PO-Revision-Date: 2013-04-09 10:13+0100\n"
@@ -21,10 +21,9 @@ msgstr ""
msgid "%"
msgstr "%"
-#: src/wx/config_dialog.cc:98
-#, fuzzy
+#: src/wx/config_dialog.cc:61
msgid "(restart DCP-o-matic to see language changes)"
-msgstr "(starta om DVD-o-matic för att se språkändringar)"
+msgstr "(starta om DCP-o-matic för att se språkändringar)"
#: src/wx/film_editor.cc:1276
msgid "1 channel"
@@ -150,19 +149,18 @@ msgstr "DCP bildhastighet"
msgid "DCP Name"
msgstr "DCP Namn"
-#: src/wx/config_dialog.cc:46
-#, fuzzy
-msgid "DCP-o-matic Preferences"
-msgstr "DVD-o-matic Inställningar"
+#: src/wx/wx_util.cc:61
+msgid "DCP-o-matic"
+msgstr "DCP-o-matic"
-#: src/wx/wx_util.cc:63 src/wx/wx_util.cc:71
-msgid "DVD-o-matic"
-msgstr "DVD-o-matic"
+#: src/wx/config_dialog.cc:44
+msgid "DCP-o-matic Preferences"
+msgstr "DCP-o-matic Inställningar"
#: src/wx/audio_dialog.cc:101
#, c-format
-msgid "DVD-o-matic audio - %s"
-msgstr "DVD-o-matic audio - %s"
+msgid "DCP-o-matic audio - %s"
+msgstr "DCP-o-matic audio - %s"
#: src/wx/config_dialog.cc:120
msgid "Default DCI name details"
diff --git a/src/wx/properties_dialog.cc b/src/wx/properties_dialog.cc
index 44a713dc3..1e0641ac4 100644
--- a/src/wx/properties_dialog.cc
+++ b/src/wx/properties_dialog.cc
@@ -1,3 +1,5 @@
+/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */
+
/*
Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
@@ -50,18 +52,11 @@ PropertiesDialog::PropertiesDialog (wxWindow* parent, shared_ptr<Film> film)
_encoded = new ThreadedStaticText (this, _("counting..."), boost::bind (&PropertiesDialog::frames_already_encoded, this));
table->Add (_encoded, 1, wxALIGN_CENTER_VERTICAL);
- if (_film->length()) {
- _frames->SetLabel (std_to_wx (lexical_cast<string> (_film->length().get())));
- FrameRateConversion frc (_film->source_frame_rate(), _film->dcp_frame_rate());
- int const dcp_length = _film->length().get() * frc.factor();
- double const disk = ((double) _film->j2k_bandwidth() / 8) * dcp_length / (_film->dcp_frame_rate() * 1073741824.0f);
- stringstream s;
- s << fixed << setprecision (1) << disk << wx_to_std (_("Gb"));
- _disk->SetLabel (std_to_wx (s.str ()));
- } else {
- _frames->SetLabel (_("unknown"));
- _disk->SetLabel (_("unknown"));
- }
+ _frames->SetLabel (std_to_wx (lexical_cast<string> (_film->time_to_video_frames (_film->length()))));
+ double const disk = ((double) _film->j2k_bandwidth() / 8) * _film->length() / (TIME_HZ * 1073741824.0f);
+ stringstream s;
+ s << fixed << setprecision (1) << disk << wx_to_std (_("Gb"));
+ _disk->SetLabel (std_to_wx (s.str ()));
wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL);
overall_sizer->Add (table, 0, wxALL, 6);
@@ -87,7 +82,7 @@ PropertiesDialog::frames_already_encoded () const
if (_film->length()) {
/* XXX: encoded_frames() should check which frames have been encoded */
- u << " (" << (_film->encoded_frames() * 100 / _film->length().get()) << "%)";
+ u << " (" << (_film->encoded_frames() * 100 / _film->time_to_video_frames (_film->length())) << "%)";
}
return u.str ();
}
diff --git a/src/wx/timecode.cc b/src/wx/timecode.cc
new file mode 100644
index 000000000..9072fb99e
--- /dev/null
+++ b/src/wx/timecode.cc
@@ -0,0 +1,115 @@
+/*
+ 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 "timecode.h"
+#include "wx_util.h"
+
+using std::string;
+using std::cout;
+using boost::lexical_cast;
+
+Timecode::Timecode (wxWindow* parent)
+ : wxPanel (parent)
+ , _in_set (false)
+{
+ wxClientDC dc (parent);
+ wxSize size = dc.GetTextExtent (wxT ("9999"));
+ 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);
+
+ wxBoxSizer* sizer = new wxBoxSizer (wxHORIZONTAL);
+ _hours = new wxTextCtrl (this, wxID_ANY, wxT(""), wxDefaultPosition, size, 0, validator);
+ _hours->SetMaxLength (2);
+ sizer->Add (_hours);
+ add_label_to_sizer (sizer, this, wxT (":"));
+ _minutes = new wxTextCtrl (this, wxID_ANY, wxT(""), wxDefaultPosition, size);
+ _minutes->SetMaxLength (2);
+ sizer->Add (_minutes);
+ add_label_to_sizer (sizer, this, wxT (":"));
+ _seconds = new wxTextCtrl (this, wxID_ANY, wxT(""), wxDefaultPosition, size);
+ _seconds->SetMaxLength (2);
+ sizer->Add (_seconds);
+ add_label_to_sizer (sizer, this, wxT ("."));
+ _frames = new wxTextCtrl (this, wxID_ANY, wxT(""), wxDefaultPosition, size);
+ _frames->SetMaxLength (2);
+ sizer->Add (_frames);
+
+ _hours->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (Timecode::changed), 0, this);
+ _minutes->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (Timecode::changed), 0, this);
+ _seconds->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (Timecode::changed), 0, this);
+ _frames->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (Timecode::changed), 0, this);
+
+ SetSizerAndFit (sizer);
+}
+
+void
+Timecode::set (Time t, int fps)
+{
+ _in_set = true;
+
+ int const h = t / (3600 * TIME_HZ);
+ t -= h * 3600 * TIME_HZ;
+ int const m = t / (60 * TIME_HZ);
+ t -= m * 60 * TIME_HZ;
+ int const s = t / TIME_HZ;
+ t -= s * TIME_HZ;
+ int const f = t * fps / TIME_HZ;
+
+ _hours->SetValue (wxString::Format (wxT ("%d"), h));
+ _minutes->SetValue (wxString::Format (wxT ("%d"), m));
+ _seconds->SetValue (wxString::Format (wxT ("%d"), s));
+ _frames->SetValue (wxString::Format (wxT ("%d"), f));
+
+ _in_set = false;
+}
+
+Time
+Timecode::get (int fps) const
+{
+ Time t = 0;
+ string const h = wx_to_std (_hours->GetValue ());
+ t += lexical_cast<int> (h.empty() ? "0" : h) * 3600 * TIME_HZ;
+ string const m = wx_to_std (_minutes->GetValue());
+ t += lexical_cast<int> (m.empty() ? "0" : m) * 60 * TIME_HZ;
+ string const s = wx_to_std (_seconds->GetValue());
+ t += lexical_cast<int> (s.empty() ? "0" : s) * TIME_HZ;
+ string const f = wx_to_std (_frames->GetValue());
+ t += lexical_cast<int> (f.empty() ? "0" : f) * TIME_HZ / fps;
+ return t;
+}
+
+void
+Timecode::changed (wxCommandEvent &)
+{
+ if (_in_set) {
+ return;
+ }
+
+ Changed ();
+}
diff --git a/src/wx/timecode.h b/src/wx/timecode.h
new file mode 100644
index 000000000..9b6fe6654
--- /dev/null
+++ b/src/wx/timecode.h
@@ -0,0 +1,43 @@
+/*
+ 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/signals2.hpp>
+#include <wx/wx.h>
+#include "lib/types.h"
+
+class Timecode : public wxPanel
+{
+public:
+ Timecode (wxWindow *);
+
+ void set (Time, int);
+ Time get (int) const;
+
+ boost::signals2::signal<void ()> Changed;
+
+private:
+ void changed (wxCommandEvent &);
+
+ wxTextCtrl* _hours;
+ wxTextCtrl* _minutes;
+ wxTextCtrl* _seconds;
+ wxTextCtrl* _frames;
+
+ bool _in_set;
+};
diff --git a/src/wx/timeline.cc b/src/wx/timeline.cc
new file mode 100644
index 000000000..902788bc9
--- /dev/null
+++ b/src/wx/timeline.cc
@@ -0,0 +1,561 @@
+/*
+ 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 <list>
+#include <wx/graphics.h>
+#include <boost/weak_ptr.hpp>
+#include "film.h"
+#include "film_editor.h"
+#include "timeline.h"
+#include "wx_util.h"
+#include "lib/playlist.h"
+
+using std::list;
+using std::cout;
+using std::max;
+using boost::shared_ptr;
+using boost::weak_ptr;
+using boost::dynamic_pointer_cast;
+using boost::bind;
+
+class View
+{
+public:
+ View (Timeline& t)
+ : _timeline (t)
+ {
+
+ }
+
+ void paint (wxGraphicsContext* g)
+ {
+ _last_paint_bbox = bbox ();
+ do_paint (g);
+ }
+
+ void force_redraw ()
+ {
+ _timeline.force_redraw (_last_paint_bbox);
+ _timeline.force_redraw (bbox ());
+ }
+
+ virtual Rect bbox () const = 0;
+
+protected:
+ virtual void do_paint (wxGraphicsContext *) = 0;
+
+ int time_x (Time t) const
+ {
+ return _timeline.tracks_position().x + t * _timeline.pixels_per_time_unit();
+ }
+
+ Timeline& _timeline;
+
+private:
+ Rect _last_paint_bbox;
+};
+
+class ContentView : public View
+{
+public:
+ ContentView (Timeline& tl, shared_ptr<Content> c, int t)
+ : View (tl)
+ , _content (c)
+ , _track (t)
+ , _selected (false)
+ {
+ _content_connection = c->Changed.connect (bind (&ContentView::content_changed, this, _2));
+ }
+
+ Rect bbox () const
+ {
+ shared_ptr<const Film> film = _timeline.film ();
+ shared_ptr<const Content> content = _content.lock ();
+ if (!film || !content) {
+ return Rect ();
+ }
+
+ return Rect (
+ time_x (content->start ()) - 8,
+ y_pos (_track) - 8,
+ content->length () * _timeline.pixels_per_time_unit() + 16,
+ _timeline.track_height() + 16
+ );
+ }
+
+ void set_selected (bool s) {
+ _selected = s;
+ force_redraw ();
+ }
+
+ bool selected () const {
+ return _selected;
+ }
+
+ weak_ptr<Content> content () const {
+ return _content;
+ }
+
+ void set_track (int t) {
+ _track = t;
+ }
+
+ int track () const {
+ return _track;
+ }
+
+ virtual wxString type () const = 0;
+ virtual wxColour colour () const = 0;
+
+private:
+
+ void do_paint (wxGraphicsContext* gc)
+ {
+ shared_ptr<const Film> film = _timeline.film ();
+ shared_ptr<const Content> content = _content.lock ();
+ if (!film || !content) {
+ return;
+ }
+
+ Time const start = content->start ();
+ Time const len = content->length ();
+
+ wxColour selected (colour().Red() / 2, colour().Green() / 2, colour().Blue() / 2);
+
+ gc->SetPen (*wxBLACK_PEN);
+
+#if wxMAJOR_VERSION == 2 && wxMINOR_VERSION >= 9
+ gc->SetPen (*wxThePenList->FindOrCreatePen (wxColour (0, 0, 0), 4, wxPENSTYLE_SOLID));
+ if (_selected) {
+ gc->SetBrush (*wxTheBrushList->FindOrCreateBrush (selected, wxBRUSHSTYLE_SOLID));
+ } else {
+ gc->SetBrush (*wxTheBrushList->FindOrCreateBrush (colour(), wxBRUSHSTYLE_SOLID));
+ }
+#else
+ gc->SetPen (*wxThePenList->FindOrCreatePen (wxColour (0, 0, 0), 4, wxSOLID));
+ if (_selected) {
+ gc->SetBrush (*wxTheBrushList->FindOrCreateBrush (selected, wxSOLID));
+ } else {
+ gc->SetBrush (*wxTheBrushList->FindOrCreateBrush (colour(), wxSOLID));
+ }
+#endif
+
+ wxGraphicsPath path = gc->CreatePath ();
+ path.MoveToPoint (time_x (start), y_pos (_track) + 4);
+ path.AddLineToPoint (time_x (start + len), y_pos (_track) + 4);
+ path.AddLineToPoint (time_x (start + len), y_pos (_track + 1) - 4);
+ path.AddLineToPoint (time_x (start), y_pos (_track + 1) - 4);
+ path.AddLineToPoint (time_x (start), y_pos (_track) + 4);
+ gc->StrokePath (path);
+ gc->FillPath (path);
+
+ wxString name = wxString::Format (wxT ("%s [%s]"), std_to_wx (content->file().filename().string()).data(), type().data());
+ wxDouble name_width;
+ wxDouble name_height;
+ wxDouble name_descent;
+ wxDouble name_leading;
+ gc->GetTextExtent (name, &name_width, &name_height, &name_descent, &name_leading);
+
+ gc->Clip (wxRegion (time_x (start), y_pos (_track), len * _timeline.pixels_per_time_unit(), _timeline.track_height()));
+ gc->DrawText (name, time_x (start) + 12, y_pos (_track + 1) - name_height - 4);
+ gc->ResetClip ();
+ }
+
+ int y_pos (int t) const
+ {
+ return _timeline.tracks_position().y + t * _timeline.track_height();
+ }
+
+ void content_changed (int p)
+ {
+ if (p == ContentProperty::START || p == ContentProperty::LENGTH) {
+ force_redraw ();
+ }
+ }
+
+ boost::weak_ptr<Content> _content;
+ int _track;
+ bool _selected;
+
+ boost::signals2::scoped_connection _content_connection;
+};
+
+class AudioContentView : public ContentView
+{
+public:
+ AudioContentView (Timeline& tl, shared_ptr<Content> c, int t)
+ : ContentView (tl, c, t)
+ {}
+
+private:
+ wxString type () const
+ {
+ return _("audio");
+ }
+
+ wxColour colour () const
+ {
+ return wxColour (149, 121, 232, 255);
+ }
+};
+
+class VideoContentView : public ContentView
+{
+public:
+ VideoContentView (Timeline& tl, shared_ptr<Content> c, int t)
+ : ContentView (tl, c, t)
+ {}
+
+private:
+
+ wxString type () const
+ {
+ return _("video");
+ }
+
+ wxColour colour () const
+ {
+ return wxColour (242, 92, 120, 255);
+ }
+};
+
+class TimeAxisView : public View
+{
+public:
+ TimeAxisView (Timeline& tl, int y)
+ : View (tl)
+ , _y (y)
+ {}
+
+ Rect bbox () const
+ {
+ return Rect (0, _y - 4, _timeline.width(), 24);
+ }
+
+ void set_y (int y)
+ {
+ _y = y;
+ force_redraw ();
+ }
+
+private:
+
+ void do_paint (wxGraphicsContext* gc)
+ {
+#if wxMAJOR_VERSION == 2 && wxMINOR_VERSION >= 9
+ gc->SetPen (*wxThePenList->FindOrCreatePen (wxColour (0, 0, 0), 1, wxPENSTYLE_SOLID));
+#else
+ gc->SetPen (*wxThePenList->FindOrCreatePen (wxColour (0, 0, 0), 1, wxSOLID));
+#endif
+
+ int mark_interval = rint (128 / (TIME_HZ * _timeline.pixels_per_time_unit ()));
+ if (mark_interval > 5) {
+ mark_interval -= mark_interval % 5;
+ }
+ if (mark_interval > 10) {
+ mark_interval -= mark_interval % 10;
+ }
+ if (mark_interval > 60) {
+ mark_interval -= mark_interval % 60;
+ }
+ if (mark_interval > 3600) {
+ mark_interval -= mark_interval % 3600;
+ }
+
+ if (mark_interval < 1) {
+ mark_interval = 1;
+ }
+
+ wxGraphicsPath path = gc->CreatePath ();
+ path.MoveToPoint (_timeline.x_offset(), _y);
+ path.AddLineToPoint (_timeline.width(), _y);
+ gc->StrokePath (path);
+
+ Time t = 0;
+ while ((t * _timeline.pixels_per_time_unit()) < _timeline.width()) {
+ wxGraphicsPath path = gc->CreatePath ();
+ path.MoveToPoint (time_x (t), _y - 4);
+ path.AddLineToPoint (time_x (t), _y + 4);
+ gc->StrokePath (path);
+
+ int tc = t / TIME_HZ;
+ int const h = tc / 3600;
+ tc -= h * 3600;
+ int const m = tc / 60;
+ tc -= m * 60;
+ int const s = tc;
+
+ wxString str = wxString::Format (wxT ("%02d:%02d:%02d"), h, m, s);
+ wxDouble str_width;
+ wxDouble str_height;
+ wxDouble str_descent;
+ wxDouble str_leading;
+ gc->GetTextExtent (str, &str_width, &str_height, &str_descent, &str_leading);
+
+ int const tx = _timeline.x_offset() + t * _timeline.pixels_per_time_unit();
+ if ((tx + str_width) < _timeline.width()) {
+ gc->DrawText (str, time_x (t), _y + 16);
+ }
+
+ t += mark_interval * TIME_HZ;
+ }
+ }
+
+private:
+ int _y;
+};
+
+Timeline::Timeline (wxWindow* parent, FilmEditor* ed, shared_ptr<Film> film)
+ : wxPanel (parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE)
+ , _film_editor (ed)
+ , _film (film)
+ , _time_axis_view (new TimeAxisView (*this, 32))
+ , _tracks (0)
+ , _pixels_per_time_unit (0)
+ , _left_down (false)
+ , _down_view_start (0)
+ , _first_move (false)
+{
+ SetDoubleBuffered (true);
+
+ setup_pixels_per_time_unit ();
+
+ Connect (wxID_ANY, wxEVT_PAINT, wxPaintEventHandler (Timeline::paint), 0, this);
+ Connect (wxID_ANY, wxEVT_LEFT_DOWN, wxMouseEventHandler (Timeline::left_down), 0, this);
+ Connect (wxID_ANY, wxEVT_LEFT_UP, wxMouseEventHandler (Timeline::left_up), 0, this);
+ Connect (wxID_ANY, wxEVT_MOTION, wxMouseEventHandler (Timeline::mouse_moved), 0, this);
+ Connect (wxID_ANY, wxEVT_SIZE, wxSizeEventHandler (Timeline::resized), 0, this);
+
+ playlist_changed ();
+
+ SetMinSize (wxSize (640, tracks() * track_height() + 96));
+
+ _playlist_connection = film->playlist()->Changed.connect (bind (&Timeline::playlist_changed, this));
+
+ _views.push_back (_time_axis_view);
+}
+
+void
+Timeline::paint (wxPaintEvent &)
+{
+ wxPaintDC dc (this);
+
+ wxGraphicsContext* gc = wxGraphicsContext::Create (dc);
+ if (!gc) {
+ return;
+ }
+
+ gc->SetFont (gc->CreateFont (*wxNORMAL_FONT));
+
+ for (list<shared_ptr<View> >::iterator i = _views.begin(); i != _views.end(); ++i) {
+ (*i)->paint (gc);
+ }
+
+ delete gc;
+}
+
+void
+Timeline::playlist_changed ()
+{
+ shared_ptr<const Film> fl = _film.lock ();
+ if (!fl) {
+ return;
+ }
+
+ _views.clear ();
+
+ Playlist::ContentList content = fl->playlist()->content ();
+
+ for (Playlist::ContentList::iterator i = content.begin(); i != content.end(); ++i) {
+ if (dynamic_pointer_cast<VideoContent> (*i)) {
+ _views.push_back (shared_ptr<View> (new VideoContentView (*this, *i, 0)));
+ }
+ if (dynamic_pointer_cast<AudioContent> (*i)) {
+ _views.push_back (shared_ptr<View> (new AudioContentView (*this, *i, 0)));
+ }
+ }
+
+ assign_tracks ();
+ Refresh ();
+}
+
+void
+Timeline::assign_tracks ()
+{
+ for (list<shared_ptr<View> >::iterator i = _views.begin(); i != _views.end(); ++i) {
+ shared_ptr<ContentView> cv = dynamic_pointer_cast<ContentView> (*i);
+ if (cv) {
+ cv->set_track (0);
+ _tracks = 1;
+ }
+ }
+
+ for (list<shared_ptr<View> >::iterator i = _views.begin(); i != _views.end(); ++i) {
+ shared_ptr<AudioContentView> acv = dynamic_pointer_cast<AudioContentView> (*i);
+ if (!acv) {
+ continue;
+ }
+
+ shared_ptr<Content> acv_content = acv->content().lock ();
+ assert (acv_content);
+
+ int t = 1;
+ while (1) {
+ list<shared_ptr<View> >::iterator j = _views.begin();
+ while (j != _views.end()) {
+ shared_ptr<AudioContentView> test = dynamic_pointer_cast<AudioContentView> (*j);
+ if (!test) {
+ ++j;
+ continue;
+ }
+
+ shared_ptr<Content> test_content = test->content().lock ();
+ assert (test_content);
+
+ if (test && test->track() == t) {
+ if ((acv_content->start() <= test_content->start() && test_content->start() <= acv_content->end()) ||
+ (acv_content->start() <= test_content->end() && test_content->end() <= acv_content->end())) {
+ /* we have an overlap on track `t' */
+ ++t;
+ break;
+ }
+ }
+
+ ++j;
+ }
+
+ if (j == _views.end ()) {
+ /* no overlap on `t' */
+ break;
+ }
+ }
+
+ acv->set_track (t);
+ _tracks = max (_tracks, t + 1);
+ }
+
+ _time_axis_view->set_y (tracks() * track_height() + 32);
+}
+
+int
+Timeline::tracks () const
+{
+ return _tracks;
+}
+
+void
+Timeline::setup_pixels_per_time_unit ()
+{
+ shared_ptr<const Film> film = _film.lock ();
+ if (!film) {
+ return;
+ }
+
+ _pixels_per_time_unit = static_cast<double>(width() - x_offset() * 2) / film->length();
+}
+
+void
+Timeline::left_down (wxMouseEvent& ev)
+{
+ list<shared_ptr<View> >::iterator i = _views.begin();
+ Position const p (ev.GetX(), ev.GetY());
+ while (i != _views.end() && !(*i)->bbox().contains (p)) {
+ ++i;
+ }
+
+ _down_view.reset ();
+
+ if (i != _views.end ()) {
+ shared_ptr<ContentView> cv = dynamic_pointer_cast<ContentView> (*i);
+ if (cv) {
+ _down_view = cv;
+ shared_ptr<Content> c = cv->content().lock();
+ assert (c);
+ _down_view_start = c->start ();
+ }
+ }
+
+ for (list<shared_ptr<View> >::iterator j = _views.begin(); j != _views.end(); ++j) {
+ shared_ptr<ContentView> cv = dynamic_pointer_cast<ContentView> (*j);
+ if (cv) {
+ cv->set_selected (i == j);
+ if (i == j) {
+ _film_editor->set_selection (cv->content ());
+ }
+ }
+ }
+
+ _left_down = true;
+ _down_point = ev.GetPosition ();
+ _first_move = false;
+}
+
+void
+Timeline::left_up (wxMouseEvent &)
+{
+ _left_down = false;
+}
+
+void
+Timeline::mouse_moved (wxMouseEvent& ev)
+{
+ if (!_left_down) {
+ return;
+ }
+
+ wxPoint const p = ev.GetPosition();
+
+ if (!_first_move) {
+ int const dist = sqrt (pow (p.x - _down_point.x, 2) + pow (p.y - _down_point.y, 2));
+ if (dist < 8) {
+ return;
+ }
+ _first_move = true;
+ }
+
+ Time const time_diff = (p.x - _down_point.x) / _pixels_per_time_unit;
+ if (_down_view) {
+ shared_ptr<Content> c = _down_view->content().lock();
+ if (c) {
+ c->set_start (max (static_cast<Time> (0), _down_view_start + time_diff));
+
+ shared_ptr<Film> film = _film.lock ();
+ assert (film);
+ film->set_sequence_video (false);
+ }
+ }
+}
+
+void
+Timeline::force_redraw (Rect const & r)
+{
+ RefreshRect (wxRect (r.x, r.y, r.width, r.height), false);
+}
+
+shared_ptr<const Film>
+Timeline::film () const
+{
+ return _film.lock ();
+}
+
+void
+Timeline::resized (wxSizeEvent &)
+{
+ setup_pixels_per_time_unit ();
+}
diff --git a/src/wx/timeline.h b/src/wx/timeline.h
new file mode 100644
index 000000000..a786e6a09
--- /dev/null
+++ b/src/wx/timeline.h
@@ -0,0 +1,86 @@
+/*
+ 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/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/signals2.hpp>
+#include <wx/wx.h>
+#include "util.h"
+
+class Film;
+class View;
+class ContentView;
+class FilmEditor;
+class TimeAxisView;
+
+class Timeline : public wxPanel
+{
+public:
+ Timeline (wxWindow *, FilmEditor *, boost::shared_ptr<Film>);
+
+ boost::shared_ptr<const Film> film () const;
+
+ void force_redraw (Rect const &);
+
+ int x_offset () const {
+ return 8;
+ }
+
+ int width () const {
+ return GetSize().GetWidth ();
+ }
+
+ int track_height () const {
+ return 48;
+ }
+
+ double pixels_per_time_unit () const {
+ return _pixels_per_time_unit;
+ }
+
+ Position tracks_position () const {
+ return Position (8, 8);
+ }
+
+ int tracks () const;
+
+private:
+ void paint (wxPaintEvent &);
+ void left_down (wxMouseEvent &);
+ void mouse_moved (wxMouseEvent &);
+ void left_up (wxMouseEvent &);
+ void playlist_changed ();
+ void setup_pixels_per_time_unit ();
+ void resized (wxSizeEvent &);
+ void assign_tracks ();
+
+ FilmEditor* _film_editor;
+ boost::weak_ptr<Film> _film;
+ std::list<boost::shared_ptr<View> > _views;
+ boost::shared_ptr<TimeAxisView> _time_axis_view;
+ int _tracks;
+ double _pixels_per_time_unit;
+ bool _left_down;
+ wxPoint _down_point;
+ boost::shared_ptr<ContentView> _down_view;
+ Time _down_view_start;
+ bool _first_move;
+
+ boost::signals2::scoped_connection _playlist_connection;
+};
diff --git a/src/wx/timeline_dialog.cc b/src/wx/timeline_dialog.cc
new file mode 100644
index 000000000..35d5eec21
--- /dev/null
+++ b/src/wx/timeline_dialog.cc
@@ -0,0 +1,42 @@
+/*
+ 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 <list>
+#include <wx/graphics.h>
+#include "film_editor.h"
+#include "timeline_dialog.h"
+#include "wx_util.h"
+#include "playlist.h"
+
+using std::list;
+using std::cout;
+using boost::shared_ptr;
+
+TimelineDialog::TimelineDialog (FilmEditor* ed, shared_ptr<Film> film)
+ : wxDialog (ed, wxID_ANY, _("Timeline"), wxDefaultPosition, wxSize (640, 512), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxFULL_REPAINT_ON_RESIZE)
+ , _timeline (this, ed, film)
+{
+ wxBoxSizer* sizer = new wxBoxSizer (wxVERTICAL);
+
+ sizer->Add (&_timeline, 1, wxEXPAND | wxALL, 12);
+
+ SetSizer (sizer);
+ sizer->Layout ();
+ sizer->SetSizeHints (this);
+}
diff --git a/src/wx/timeline_dialog.h b/src/wx/timeline_dialog.h
new file mode 100644
index 000000000..17ca22c49
--- /dev/null
+++ b/src/wx/timeline_dialog.h
@@ -0,0 +1,34 @@
+/*
+ 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/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <wx/wx.h>
+#include "timeline.h"
+
+class Playlist;
+
+class TimelineDialog : public wxDialog
+{
+public:
+ TimelineDialog (FilmEditor *, boost::shared_ptr<Film>);
+
+private:
+ Timeline _timeline;
+};
diff --git a/src/wx/wscript b/src/wx/wscript
index 42bb8ca88..d915f5899 100644
--- a/src/wx/wscript
+++ b/src/wx/wscript
@@ -5,6 +5,7 @@ import i18n
sources = """
audio_dialog.cc
+ audio_mapping_view.cc
audio_plot.cc
config_dialog.cc
dci_metadata_dialog.cc
@@ -14,11 +15,15 @@ sources = """
filter_dialog.cc
filter_view.cc
gain_calculator_dialog.cc
+ imagemagick_content_dialog.cc
job_manager_view.cc
job_wrapper.cc
new_film_dialog.cc
properties_dialog.cc
server_dialog.cc
+ timecode.cc
+ timeline.cc
+ timeline_dialog.cc
wx_util.cc
wx_ui_signaller.cc
"""
@@ -32,18 +37,18 @@ def build(bld):
else:
obj = bld(features = 'cxx cxxshlib')
- obj.name = 'libdvdomatic-wx'
+ obj.name = 'libdcpomatic-wx'
obj.includes = [ '..' ]
obj.export_includes = ['.']
obj.uselib = 'WXWIDGETS'
- obj.use = 'libdvdomatic'
+ obj.use = 'libdcpomatic'
obj.source = sources
- obj.target = 'dvdomatic-wx'
+ obj.target = 'dcpomatic-wx'
- i18n.po_to_mo(os.path.join('src', 'wx'), 'libdvdomatic-wx', bld)
+ i18n.po_to_mo(os.path.join('src', 'wx'), 'libdcpomatic-wx', bld)
def pot(bld):
- i18n.pot(os.path.join('src', 'wx'), sources, 'libdvdomatic-wx')
+ i18n.pot(os.path.join('src', 'wx'), sources, 'libdcpomatic-wx')
def pot_merge(bld):
- i18n.pot_merge(os.path.join('src', 'wx'), 'libdvdomatic-wx')
+ i18n.pot_merge(os.path.join('src', 'wx'), 'libdcpomatic-wx')
diff --git a/src/wx/wx_util.cc b/src/wx/wx_util.cc
index 1a7b73faf..5691d341a 100644
--- a/src/wx/wx_util.cc
+++ b/src/wx/wx_util.cc
@@ -60,7 +60,7 @@ add_label_to_grid_bag_sizer (wxGridBagSizer* s, wxWindow* p, wxString t, wxGBPos
void
error_dialog (wxWindow* parent, wxString m)
{
- wxMessageDialog* d = new wxMessageDialog (parent, m, _("DVD-o-matic"), wxOK);
+ wxMessageDialog* d = new wxMessageDialog (parent, m, _("DCP-o-matic"), wxOK);
d->ShowModal ();
d->Destroy ();
}
@@ -68,7 +68,7 @@ error_dialog (wxWindow* parent, wxString m)
bool
confirm_dialog (wxWindow* parent, wxString m)
{
- wxMessageDialog* d = new wxMessageDialog (parent, m, _("DVD-o-matic"), wxYES_NO | wxICON_QUESTION);
+ wxMessageDialog* d = new wxMessageDialog (parent, m, _("DCP-o-matic"), wxYES_NO | wxICON_QUESTION);
int const r = d->ShowModal ();
d->Destroy ();
return r == wxID_YES;
@@ -215,7 +215,7 @@ checked_set (wxRadioButton* widget, bool value)
}
void
-dvdomatic_setup_i18n ()
+dcpomatic_setup_i18n ()
{
int language = wxLANGUAGE_DEFAULT;
@@ -231,12 +231,12 @@ dvdomatic_setup_i18n ()
if (wxLocale::IsAvailable (language)) {
locale = new wxLocale (language, wxLOCALE_LOAD_DEFAULT);
-#ifdef DVDOMATIC_WINDOWS
+#ifdef DCPOMATIC_WINDOWS
locale->AddCatalogLookupPathPrefix (std_to_wx (mo_path().string()));
#endif
- locale->AddCatalog (wxT ("libdvdomatic-wx"));
- locale->AddCatalog (wxT ("dvdomatic"));
+ locale->AddCatalog (wxT ("libdcpomatic-wx"));
+ locale->AddCatalog (wxT ("dcpomatic"));
if (!locale->IsOk()) {
delete locale;
@@ -246,6 +246,6 @@ dvdomatic_setup_i18n ()
}
if (locale) {
- dvdomatic_setup_gettext_i18n (wx_to_std (locale->GetCanonicalName ()));
+ dcpomatic_setup_gettext_i18n (wx_to_std (locale->GetCanonicalName ()));
}
}
diff --git a/src/wx/wx_util.h b/src/wx/wx_util.h
index 00a625e1c..bff11647e 100644
--- a/src/wx/wx_util.h
+++ b/src/wx/wx_util.h
@@ -36,7 +36,7 @@ extern wxStaticText* add_label_to_sizer (wxSizer *, wxWindow *, wxString, int pr
extern wxStaticText* add_label_to_grid_bag_sizer (wxGridBagSizer *, wxWindow *, wxString, wxGBPosition, wxGBSpan span = wxDefaultSpan);
extern std::string wx_to_std (wxString);
extern wxString std_to_wx (std::string);
-extern void dvdomatic_setup_i18n ();
+extern void dcpomatic_setup_i18n ();
/** @class ThreadedStaticText
*