From df17bbd25da69fc38eb2dcd8b4a2531cf0bab0bc Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 23 Jul 2018 11:20:12 +0100 Subject: More automated renaming. ActiveCaptions -> ActiveText BitmapCaption -> BitmapText ContentCaption -> ContentText ContentTextCaption -> ContentStringText TextCaptionFileContent -> StringTextFileContent TextCaptionFileDecoder -> StringTextFileDecoder TextCaptionFile -> StringTextFile TextCaption -> StringText PlayerCaption -> PlayerText CaptionContent -> TextContent CaptionDecoder -> TextDecoder CaptionPanel -> TextPanel CaptionView -> TextView CaptionAppearanceDialog -> SubtitleAppearanceDialog CaptionType -> TextType --- src/wx/caption_appearance_dialog.cc | 283 -------------------- src/wx/caption_appearance_dialog.h | 71 ----- src/wx/caption_panel.cc | 506 ----------------------------------- src/wx/caption_panel.h | 73 ----- src/wx/caption_view.cc | 139 ---------- src/wx/caption_view.h | 48 ---- src/wx/closed_captions_dialog.cc | 14 +- src/wx/content_panel.cc | 16 +- src/wx/content_panel.h | 4 +- src/wx/dcp_panel.cc | 6 +- src/wx/film_viewer.h | 2 +- src/wx/fonts_dialog.cc | 8 +- src/wx/fonts_dialog.h | 6 +- src/wx/subtitle_appearance_dialog.cc | 283 ++++++++++++++++++++ src/wx/subtitle_appearance_dialog.h | 71 +++++ src/wx/text_panel.cc | 506 +++++++++++++++++++++++++++++++++++ src/wx/text_panel.h | 73 +++++ src/wx/text_view.cc | 139 ++++++++++ src/wx/text_view.h | 48 ++++ src/wx/timeline.cc | 4 +- src/wx/timeline_text_content_view.cc | 4 +- src/wx/timeline_text_content_view.h | 6 +- src/wx/timing_panel.cc | 4 +- src/wx/wscript | 6 +- 24 files changed, 1160 insertions(+), 1160 deletions(-) delete mode 100644 src/wx/caption_appearance_dialog.cc delete mode 100644 src/wx/caption_appearance_dialog.h delete mode 100644 src/wx/caption_panel.cc delete mode 100644 src/wx/caption_panel.h delete mode 100644 src/wx/caption_view.cc delete mode 100644 src/wx/caption_view.h create mode 100644 src/wx/subtitle_appearance_dialog.cc create mode 100644 src/wx/subtitle_appearance_dialog.h create mode 100644 src/wx/text_panel.cc create mode 100644 src/wx/text_panel.h create mode 100644 src/wx/text_view.cc create mode 100644 src/wx/text_view.h (limited to 'src/wx') diff --git a/src/wx/caption_appearance_dialog.cc b/src/wx/caption_appearance_dialog.cc deleted file mode 100644 index af01dcbe8..000000000 --- a/src/wx/caption_appearance_dialog.cc +++ /dev/null @@ -1,283 +0,0 @@ -/* - Copyright (C) 2015-2018 Carl Hetherington - - This file is part of DCP-o-matic. - - DCP-o-matic is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - DCP-o-matic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with DCP-o-matic. If not, see . - -*/ - -#include "caption_appearance_dialog.h" -#include "rgba_colour_picker.h" -#include "lib/text_caption_file_content.h" -#include "lib/caption_content.h" -#include "lib/ffmpeg_subtitle_stream.h" -#include "lib/ffmpeg_content.h" -#include -#include -#include -#include - -using std::map; -using boost::shared_ptr; -using boost::bind; -using boost::dynamic_pointer_cast; -using boost::optional; - -int const CaptionAppearanceDialog::NONE = 0; -int const CaptionAppearanceDialog::OUTLINE = 1; -int const CaptionAppearanceDialog::SHADOW = 2; - -CaptionAppearanceDialog::CaptionAppearanceDialog (wxWindow* parent, shared_ptr content, shared_ptr caption) - : wxDialog (parent, wxID_ANY, _("Caption appearance")) - , _content (content) - , _caption (caption) -{ - shared_ptr ff = dynamic_pointer_cast (content); - if (ff) { - _stream = ff->subtitle_stream (); - } - - wxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL); - SetSizer (overall_sizer); - - _table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP); - - overall_sizer->Add (_table, 1, wxEXPAND | wxALL, DCPOMATIC_DIALOG_BORDER); - - int r = 0; - - add_label_to_sizer (_table, this, _("Colour"), true, wxGBPosition (r, 0)); - _force_colour = set_to (_colour = new wxColourPickerCtrl (this, wxID_ANY), r); - - add_label_to_sizer (_table, this, _("Effect"), true, wxGBPosition (r, 0)); - _force_effect = set_to (_effect = new wxChoice (this, wxID_ANY), r); - - add_label_to_sizer (_table, this, _("Effect colour"), true, wxGBPosition (r, 0)); - _force_effect_colour = set_to (_effect_colour = new wxColourPickerCtrl (this, wxID_ANY), r); - - add_label_to_sizer (_table, this, _("Outline width"), true, wxGBPosition (r, 0)); - _outline_width = new wxSpinCtrl (this, wxID_ANY); - _table->Add (_outline_width, wxGBPosition (r, 1)); - ++r; - - add_label_to_sizer (_table, this, _("Fade in time"), true, wxGBPosition (r, 0)); - _force_fade_in = set_to (_fade_in = new Timecode (this), r); - - add_label_to_sizer (_table, this, _("Fade out time"), true, wxGBPosition (r, 0)); - _force_fade_out = set_to (_fade_out = new Timecode (this), r); - - if (_stream) { - wxScrolled* colours_panel = new wxScrolled (this); - colours_panel->EnableScrolling (false, true); - colours_panel->ShowScrollbars (wxSHOW_SB_NEVER, wxSHOW_SB_ALWAYS); - colours_panel->SetScrollRate (0, 16); - - wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP); - table->AddGrowableCol (1, 1); - - map colours = _stream->colours (); - - wxStaticText* t = new wxStaticText (colours_panel, wxID_ANY, ""); - t->SetLabelMarkup (_("Original colour")); - table->Add (t, 1, wxEXPAND); - t = new wxStaticText (colours_panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL); - t->SetLabelMarkup (_("New colour")); - table->Add (t, 1, wxALIGN_CENTER); - - for (map::const_iterator i = colours.begin(); i != colours.end(); ++i) { - wxPanel* from = new wxPanel (colours_panel, wxID_ANY); - from->SetBackgroundColour (wxColour (i->first.r, i->first.g, i->first.b, i->first.a)); - table->Add (from, 1, wxEXPAND); - RGBAColourPicker* to = new RGBAColourPicker (colours_panel, i->second); - table->Add (to, 1, wxEXPAND); - _pickers[i->first] = to; - } - - colours_panel->SetSizer (table); - - overall_sizer->Add (colours_panel, 1, wxEXPAND | wxALL, DCPOMATIC_DIALOG_BORDER); - - wxButton* restore = new wxButton (this, wxID_ANY, _("Restore to original colours")); - restore->Bind (wxEVT_BUTTON, bind (&CaptionAppearanceDialog::restore, this)); - overall_sizer->Add (restore, 0, wxALL, DCPOMATIC_SIZER_X_GAP); - } - - wxSizer* buttons = CreateSeparatedButtonSizer (wxOK); - if (buttons) { - overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder()); - } - - overall_sizer->Layout (); - overall_sizer->SetSizeHints (this); - - /* Keep these Appends() up to date with NONE/OUTLINE/SHADOW variables */ - _effect->Append (_("None")); - _effect->Append (_("Outline")); - _effect->Append (_("Shadow"));; - - optional colour = _caption->colour(); - _force_colour->SetValue (static_cast(colour)); - if (colour) { - _colour->SetColour (wxColour (colour->r, colour->g, colour->b)); - } else { - _colour->SetColour (wxColour (255, 255, 255)); - } - - optional effect = _caption->effect(); - _force_effect->SetValue (static_cast(effect)); - if (effect) { - switch (*effect) { - case dcp::NONE: - _effect->SetSelection (NONE); - break; - case dcp::BORDER: - _effect->SetSelection (OUTLINE); - break; - case dcp::SHADOW: - _effect->SetSelection (SHADOW); - break; - } - } else { - _effect->SetSelection (NONE); - } - - optional effect_colour = _caption->effect_colour(); - _force_effect_colour->SetValue (static_cast(effect_colour)); - if (effect_colour) { - _effect_colour->SetColour (wxColour (effect_colour->r, effect_colour->g, effect_colour->b)); - } else { - _effect_colour->SetColour (wxColour (0, 0, 0)); - } - - optional fade_in = _caption->fade_in(); - _force_fade_in->SetValue (static_cast(fade_in)); - if (fade_in) { - _fade_in->set (*fade_in, _content->active_video_frame_rate()); - } else { - _fade_in->set (ContentTime(), _content->active_video_frame_rate()); - } - - optional fade_out = _caption->fade_out(); - _force_fade_out->SetValue (static_cast(fade_out)); - if (fade_out) { - _fade_out->set (*fade_out, _content->active_video_frame_rate ()); - } else { - _fade_out->set (ContentTime(), _content->active_video_frame_rate ()); - } - - _outline_width->SetValue (_caption->outline_width ()); - - _force_colour->Bind (wxEVT_CHECKBOX, bind (&CaptionAppearanceDialog::setup_sensitivity, this)); - _force_effect_colour->Bind (wxEVT_CHECKBOX, bind (&CaptionAppearanceDialog::setup_sensitivity, this)); - _force_effect->Bind (wxEVT_CHECKBOX, bind (&CaptionAppearanceDialog::setup_sensitivity, this)); - _force_fade_in->Bind (wxEVT_CHECKBOX, bind (&CaptionAppearanceDialog::setup_sensitivity, this)); - _force_fade_out->Bind (wxEVT_CHECKBOX, bind (&CaptionAppearanceDialog::setup_sensitivity, this)); - _effect->Bind (wxEVT_CHOICE, bind (&CaptionAppearanceDialog::setup_sensitivity, this)); - _content_connection = _content->Changed.connect (bind (&CaptionAppearanceDialog::setup_sensitivity, this)); - - setup_sensitivity (); -} - -wxCheckBox* -CaptionAppearanceDialog::set_to (wxWindow* w, int& r) -{ - wxSizer* s = new wxBoxSizer (wxHORIZONTAL); - wxCheckBox* set_to = new wxCheckBox (this, wxID_ANY, _("Set to")); - s->Add (set_to, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 8); - s->Add (w, 0, wxALIGN_CENTER_VERTICAL); - _table->Add (s, wxGBPosition (r, 1)); - ++r; - return set_to; -} - -void -CaptionAppearanceDialog::apply () -{ - if (_force_colour->GetValue ()) { - wxColour const c = _colour->GetColour (); - _caption->set_colour (dcp::Colour (c.Red(), c.Green(), c.Blue())); - } else { - _caption->unset_colour (); - } - if (_force_effect->GetValue()) { - switch (_effect->GetSelection()) { - case NONE: - _caption->set_effect (dcp::NONE); - break; - case OUTLINE: - _caption->set_effect (dcp::BORDER); - break; - case SHADOW: - _caption->set_effect (dcp::SHADOW); - break; - } - } else { - _caption->unset_effect (); - } - if (_force_effect_colour->GetValue ()) { - wxColour const ec = _effect_colour->GetColour (); - _caption->set_effect_colour (dcp::Colour (ec.Red(), ec.Green(), ec.Blue())); - } else { - _caption->unset_effect_colour (); - } - if (_force_fade_in->GetValue ()) { - _caption->set_fade_in (_fade_in->get (_content->active_video_frame_rate ())); - } else { - _caption->unset_fade_in (); - } - if (_force_fade_out->GetValue ()) { - _caption->set_fade_out (_fade_out->get (_content->active_video_frame_rate ())); - } else { - _caption->unset_fade_out (); - } - _caption->set_outline_width (_outline_width->GetValue ()); - - if (_stream) { - for (map::const_iterator i = _pickers.begin(); i != _pickers.end(); ++i) { - _stream->set_colour (i->first, i->second->colour ()); - } - } - - shared_ptr fc = dynamic_pointer_cast (_content); - if (fc) { - fc->signal_subtitle_stream_changed (); - } -} - -void -CaptionAppearanceDialog::restore () -{ - for (map::const_iterator i = _pickers.begin(); i != _pickers.end(); ++i) { - i->second->set (i->first); - } -} - -void -CaptionAppearanceDialog::setup_sensitivity () -{ - _colour->Enable (_force_colour->GetValue ()); - _effect_colour->Enable (_force_effect_colour->GetValue ()); - _effect->Enable (_force_effect->GetValue ()); - _fade_in->Enable (_force_fade_in->GetValue ()); - _fade_out->Enable (_force_fade_out->GetValue ()); - - bool const can_outline_width = _effect->GetSelection() == OUTLINE && _caption->burn (); - _outline_width->Enable (can_outline_width); - if (can_outline_width) { - _outline_width->UnsetToolTip (); - } else { - _outline_width->SetToolTip (_("Outline width cannot be set unless you are burning in captions")); - } -} diff --git a/src/wx/caption_appearance_dialog.h b/src/wx/caption_appearance_dialog.h deleted file mode 100644 index 3fb993099..000000000 --- a/src/wx/caption_appearance_dialog.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - Copyright (C) 2015-2018 Carl Hetherington - - This file is part of DCP-o-matic. - - DCP-o-matic is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - DCP-o-matic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with DCP-o-matic. If not, see . - -*/ - -#include "timecode.h" -#include "lib/rgba.h" -#include -#include -#include - -class wxRadioButton; -class wxColourPickerCtrl; -class wxGridBagSizer; -class Content; -class RGBAColourPicker; -class FFmpegSubtitleStream; -class wxCheckBox; -class wxWidget; - -class CaptionAppearanceDialog : public wxDialog -{ -public: - CaptionAppearanceDialog (wxWindow* parent, boost::shared_ptr content, boost::shared_ptr caption); - - void apply (); - -private: - void setup_sensitivity (); - void restore (); - wxCheckBox* set_to (wxWindow* w, int& r); - - wxCheckBox* _force_colour; - wxColourPickerCtrl* _colour; - wxCheckBox* _force_effect; - wxChoice* _effect; - wxCheckBox* _force_effect_colour; - wxColourPickerCtrl* _effect_colour; - wxCheckBox* _force_fade_in; - Timecode* _fade_in; - wxCheckBox* _force_fade_out; - Timecode* _fade_out; - wxSpinCtrl* _outline_width; - wxGridBagSizer* _table; - std::map _pickers; - - boost::shared_ptr _content; - boost::shared_ptr _caption; - boost::shared_ptr _stream; - - boost::signals2::scoped_connection _content_connection; - - static int const NONE; - static int const OUTLINE; - static int const SHADOW; -}; diff --git a/src/wx/caption_panel.cc b/src/wx/caption_panel.cc deleted file mode 100644 index 1d2f59258..000000000 --- a/src/wx/caption_panel.cc +++ /dev/null @@ -1,506 +0,0 @@ -/* - Copyright (C) 2012-2018 Carl Hetherington - - This file is part of DCP-o-matic. - - DCP-o-matic is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - DCP-o-matic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with DCP-o-matic. If not, see . - -*/ - -#include "caption_panel.h" -#include "film_editor.h" -#include "wx_util.h" -#include "caption_view.h" -#include "content_panel.h" -#include "fonts_dialog.h" -#include "caption_appearance_dialog.h" -#include "lib/ffmpeg_content.h" -#include "lib/text_caption_file_content.h" -#include "lib/ffmpeg_subtitle_stream.h" -#include "lib/dcp_subtitle_content.h" -#include "lib/text_caption_file_decoder.h" -#include "lib/dcp_subtitle_decoder.h" -#include "lib/dcp_content.h" -#include "lib/caption_content.h" -#include "lib/decoder_factory.h" -#include -#include - -using std::vector; -using std::string; -using std::list; -using std::cout; -using boost::shared_ptr; -using boost::dynamic_pointer_cast; - -CaptionPanel::CaptionPanel (ContentPanel* p, CaptionType t) - : ContentSubPanel (p, std_to_wx(caption_type_to_name(t))) - , _caption_view (0) - , _fonts_dialog (0) - , _original_type (t) -{ - wxBoxSizer* reference_sizer = new wxBoxSizer (wxVERTICAL); - - _reference = new wxCheckBox (this, wxID_ANY, _("Use this DCP's subtitle as OV and make VF")); - reference_sizer->Add (_reference, 0, wxLEFT | wxRIGHT | wxTOP, DCPOMATIC_SIZER_GAP); - - _reference_note = new wxStaticText (this, wxID_ANY, _("")); - _reference_note->Wrap (200); - reference_sizer->Add (_reference_note, 0, wxLEFT | wxRIGHT, DCPOMATIC_SIZER_GAP); - wxFont font = _reference_note->GetFont(); - font.SetStyle(wxFONTSTYLE_ITALIC); - font.SetPointSize(font.GetPointSize() - 1); - _reference_note->SetFont(font); - - _sizer->Add (reference_sizer); - - wxGridBagSizer* grid = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP); - _sizer->Add (grid, 0, wxALL, 8); - int r = 0; - - wxBoxSizer* use = new wxBoxSizer (wxHORIZONTAL); - _use = new wxCheckBox (this, wxID_ANY, _("Use as")); - use->Add (_use, 0, wxEXPAND | wxRIGHT, DCPOMATIC_SIZER_GAP); - _type = new wxChoice (this, wxID_ANY); - _type->Append (_("subtitles (open captions)")); - _type->Append (_("closed captions")); - use->Add (_type, 1, wxEXPAND, 0); - grid->Add (use, wxGBPosition (r, 0), wxGBSpan (1, 2)); - ++r; - - _burn = new wxCheckBox (this, wxID_ANY, _("Burn subtitles into image")); - grid->Add (_burn, wxGBPosition (r, 0), wxGBSpan (1, 2)); - ++r; - - { - add_label_to_sizer (grid, this, _("X Offset"), true, wxGBPosition (r, 0)); - wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); - _x_offset = new wxSpinCtrl (this); - s->Add (_x_offset); - add_label_to_sizer (s, this, _("%"), false); - grid->Add (s, wxGBPosition (r, 1)); - ++r; - } - - { - add_label_to_sizer (grid, this, _("Y Offset"), true, wxGBPosition (r, 0)); - wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); - _y_offset = new wxSpinCtrl (this); - s->Add (_y_offset); - add_label_to_sizer (s, this, _("%"), false); - grid->Add (s, wxGBPosition (r, 1)); - ++r; - } - - { - add_label_to_sizer (grid, this, _("X Scale"), true, wxGBPosition (r, 0)); - wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); - _x_scale = new wxSpinCtrl (this); - s->Add (_x_scale); - add_label_to_sizer (s, this, _("%"), false); - grid->Add (s, wxGBPosition (r, 1)); - ++r; - } - - { - add_label_to_sizer (grid, this, _("Y Scale"), true, wxGBPosition (r, 0)); - wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); - _y_scale = new wxSpinCtrl (this); - s->Add (_y_scale); - add_label_to_sizer (s, this, _("%"), false); - grid->Add (s, wxGBPosition (r, 1)); - ++r; - } - - { - add_label_to_sizer (grid, this, _("Line spacing"), true, wxGBPosition (r, 0)); - wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); - _line_spacing = new wxSpinCtrl (this); - s->Add (_line_spacing); - add_label_to_sizer (s, this, _("%"), false); - grid->Add (s, wxGBPosition (r, 1)); - ++r; - } - - add_label_to_sizer (grid, this, _("Language"), true, wxGBPosition (r, 0)); - _language = new wxTextCtrl (this, wxID_ANY); - grid->Add (_language, wxGBPosition (r, 1)); - ++r; - - add_label_to_sizer (grid, this, _("Stream"), true, wxGBPosition (r, 0)); - _stream = new wxChoice (this, wxID_ANY); - grid->Add (_stream, wxGBPosition (r, 1)); - ++r; - - { - wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); - - _caption_view_button = new wxButton (this, wxID_ANY, _("View...")); - s->Add (_caption_view_button, 1, wxALL, DCPOMATIC_SIZER_GAP); - _fonts_dialog_button = new wxButton (this, wxID_ANY, _("Fonts...")); - s->Add (_fonts_dialog_button, 1, wxALL, DCPOMATIC_SIZER_GAP); - _appearance_dialog_button = new wxButton (this, wxID_ANY, _("Appearance...")); - s->Add (_appearance_dialog_button, 1, wxALL, DCPOMATIC_SIZER_GAP); - - grid->Add (s, wxGBPosition (r, 0), wxGBSpan (1, 2)); - ++r; - } - - _x_offset->SetRange (-100, 100); - _y_offset->SetRange (-100, 100); - _x_scale->SetRange (10, 1000); - _y_scale->SetRange (10, 1000); - _line_spacing->SetRange (10, 1000); - - _reference->Bind (wxEVT_CHECKBOX, boost::bind (&CaptionPanel::reference_clicked, this)); - _use->Bind (wxEVT_CHECKBOX, boost::bind (&CaptionPanel::use_toggled, this)); - _type->Bind (wxEVT_CHOICE, boost::bind (&CaptionPanel::type_changed, this)); - _burn->Bind (wxEVT_CHECKBOX, boost::bind (&CaptionPanel::burn_toggled, this)); - _x_offset->Bind (wxEVT_SPINCTRL, boost::bind (&CaptionPanel::x_offset_changed, this)); - _y_offset->Bind (wxEVT_SPINCTRL, boost::bind (&CaptionPanel::y_offset_changed, this)); - _x_scale->Bind (wxEVT_SPINCTRL, boost::bind (&CaptionPanel::x_scale_changed, this)); - _y_scale->Bind (wxEVT_SPINCTRL, boost::bind (&CaptionPanel::y_scale_changed, this)); - _line_spacing->Bind (wxEVT_SPINCTRL, boost::bind (&CaptionPanel::line_spacing_changed, this)); - _language->Bind (wxEVT_TEXT, boost::bind (&CaptionPanel::language_changed, this)); - _stream->Bind (wxEVT_CHOICE, boost::bind (&CaptionPanel::stream_changed, this)); - _caption_view_button->Bind (wxEVT_BUTTON, boost::bind (&CaptionPanel::caption_view_clicked, this)); - _fonts_dialog_button->Bind (wxEVT_BUTTON, boost::bind (&CaptionPanel::fonts_dialog_clicked, this)); - _appearance_dialog_button->Bind (wxEVT_BUTTON, boost::bind (&CaptionPanel::appearance_dialog_clicked, this)); -} - -void -CaptionPanel::film_changed (Film::Property property) -{ - if (property == Film::CONTENT || property == Film::REEL_TYPE) { - setup_sensitivity (); - } -} - -void -CaptionPanel::film_content_changed (int property) -{ - FFmpegContentList fc = _parent->selected_ffmpeg (); - ContentList sc = _parent->selected_caption (); - - shared_ptr fcs; - if (fc.size() == 1) { - fcs = fc.front (); - } - - shared_ptr scs; - if (sc.size() == 1) { - scs = sc.front (); - } - - shared_ptr caption; - if (scs) { - caption = scs->caption_of_original_type(_original_type); - } - - if (property == FFmpegContentProperty::SUBTITLE_STREAMS) { - _stream->Clear (); - if (fcs) { - vector > s = fcs->subtitle_streams (); - for (vector >::iterator i = s.begin(); i != s.end(); ++i) { - _stream->Append (std_to_wx ((*i)->name), new wxStringClientData (std_to_wx ((*i)->identifier ()))); - } - - if (fcs->subtitle_stream()) { - checked_set (_stream, fcs->subtitle_stream()->identifier ()); - } else { - _stream->SetSelection (wxNOT_FOUND); - } - } - setup_sensitivity (); - } else if (property == CaptionContentProperty::USE) { - checked_set (_use, caption ? caption->use() : false); - setup_sensitivity (); - } else if (property == CaptionContentProperty::TYPE) { - if (caption) { - switch (caption->type()) { - case CAPTION_OPEN: - _type->SetSelection (0); - break; - case CAPTION_CLOSED: - _type->SetSelection (1); - break; - default: - DCPOMATIC_ASSERT (false); - } - } else { - _type->SetSelection (0); - } - setup_sensitivity (); - } else if (property == CaptionContentProperty::BURN) { - checked_set (_burn, caption ? caption->burn() : false); - } else if (property == CaptionContentProperty::X_OFFSET) { - checked_set (_x_offset, caption ? lrint (caption->x_offset() * 100) : 0); - } else if (property == CaptionContentProperty::Y_OFFSET) { - checked_set (_y_offset, caption ? lrint (caption->y_offset() * 100) : 0); - } else if (property == CaptionContentProperty::X_SCALE) { - checked_set (_x_scale, caption ? lrint (caption->x_scale() * 100) : 100); - } else if (property == CaptionContentProperty::Y_SCALE) { - checked_set (_y_scale, caption ? lrint (caption->y_scale() * 100) : 100); - } else if (property == CaptionContentProperty::LINE_SPACING) { - checked_set (_line_spacing, caption ? lrint (caption->line_spacing() * 100) : 100); - } else if (property == CaptionContentProperty::LANGUAGE) { - checked_set (_language, caption ? caption->language() : ""); - } else if (property == DCPContentProperty::REFERENCE_CAPTION) { - if (scs) { - shared_ptr dcp = dynamic_pointer_cast (scs); - checked_set (_reference, dcp ? dcp->reference_caption(_original_type) : false); - } else { - checked_set (_reference, false); - } - - setup_sensitivity (); - } else if (property == DCPContentProperty::CAPTIONS) { - setup_sensitivity (); - } -} - -void -CaptionPanel::use_toggled () -{ - BOOST_FOREACH (shared_ptr i, _parent->selected_caption()) { - i->caption_of_original_type(_original_type)->set_use (_use->GetValue()); - } -} - -void -CaptionPanel::type_changed () -{ - BOOST_FOREACH (shared_ptr i, _parent->selected_caption()) { - switch (_type->GetSelection()) { - case 0: - i->caption_of_original_type(_original_type)->set_type (CAPTION_OPEN); - break; - case 1: - i->caption_of_original_type(_original_type)->set_type (CAPTION_CLOSED); - break; - } - } -} - -void -CaptionPanel::burn_toggled () -{ - BOOST_FOREACH (shared_ptr i, _parent->selected_caption ()) { - i->caption_of_original_type(_original_type)->set_burn (_burn->GetValue()); - } -} - -void -CaptionPanel::setup_sensitivity () -{ - int any_subs = 0; - int ffmpeg_subs = 0; - ContentList sel = _parent->selected_caption (); - BOOST_FOREACH (shared_ptr i, sel) { - /* These are the content types that could include subtitles */ - shared_ptr fc = boost::dynamic_pointer_cast (i); - shared_ptr sc = boost::dynamic_pointer_cast (i); - shared_ptr dc = boost::dynamic_pointer_cast (i); - shared_ptr dsc = boost::dynamic_pointer_cast (i); - if (fc) { - if (!fc->caption.empty()) { - ++ffmpeg_subs; - ++any_subs; - } - } else if (sc || dc || dsc) { - /* XXX: in the future there could be bitmap subs from DCPs */ - ++any_subs; - } - } - - /* Decide whether we can reference these subs */ - - shared_ptr dcp; - if (sel.size() == 1) { - dcp = dynamic_pointer_cast (sel.front ()); - } - - string why_not; - bool const can_reference = dcp && dcp->can_reference_caption (_original_type, why_not); - setup_refer_button (_reference, _reference_note, dcp, can_reference, why_not); - - bool const reference = _reference->GetValue (); - - /* Set up sensitivity */ - _use->Enable (!reference && any_subs > 0); - bool const use = _use->GetValue (); - _type->Enable (!reference && any_subs > 0 && use); - _burn->Enable (!reference && any_subs > 0 && use && _type->GetSelection() == 0); - _x_offset->Enable (!reference && any_subs > 0 && use); - _y_offset->Enable (!reference && any_subs > 0 && use); - _x_scale->Enable (!reference && any_subs > 0 && use); - _y_scale->Enable (!reference && any_subs > 0 && use); - _line_spacing->Enable (!reference && use); - _language->Enable (!reference && any_subs > 0 && use); - _stream->Enable (!reference && ffmpeg_subs == 1); - _caption_view_button->Enable (!reference); - _fonts_dialog_button->Enable (!reference); - _appearance_dialog_button->Enable (!reference && any_subs > 0 && use); -} - -void -CaptionPanel::stream_changed () -{ - FFmpegContentList fc = _parent->selected_ffmpeg (); - if (fc.size() != 1) { - return; - } - - shared_ptr fcs = fc.front (); - - vector > a = fcs->subtitle_streams (); - vector >::iterator i = a.begin (); - string const s = string_client_data (_stream->GetClientObject (_stream->GetSelection ())); - while (i != a.end() && (*i)->identifier () != s) { - ++i; - } - - if (i != a.end ()) { - fcs->set_subtitle_stream (*i); - } -} - -void -CaptionPanel::x_offset_changed () -{ - BOOST_FOREACH (shared_ptr i, _parent->selected_caption ()) { - i->caption_of_original_type(_original_type)->set_x_offset (_x_offset->GetValue() / 100.0); - } -} - -void -CaptionPanel::y_offset_changed () -{ - BOOST_FOREACH (shared_ptr i, _parent->selected_caption ()) { - i->caption_of_original_type(_original_type)->set_y_offset (_y_offset->GetValue() / 100.0); - } -} - -void -CaptionPanel::x_scale_changed () -{ - ContentList c = _parent->selected_caption (); - if (c.size() == 1) { - c.front()->caption_of_original_type(_original_type)->set_x_scale (_x_scale->GetValue() / 100.0); - } -} - -void -CaptionPanel::y_scale_changed () -{ - BOOST_FOREACH (shared_ptr i, _parent->selected_caption ()) { - i->caption_of_original_type(_original_type)->set_y_scale (_y_scale->GetValue() / 100.0); - } -} - -void -CaptionPanel::line_spacing_changed () -{ - BOOST_FOREACH (shared_ptr i, _parent->selected_caption ()) { - i->caption_of_original_type(_original_type)->set_line_spacing (_line_spacing->GetValue() / 100.0); - } -} - -void -CaptionPanel::language_changed () -{ - BOOST_FOREACH (shared_ptr i, _parent->selected_caption ()) { - i->caption_of_original_type(_original_type)->set_language (wx_to_std (_language->GetValue())); - } -} - -void -CaptionPanel::content_selection_changed () -{ - film_content_changed (FFmpegContentProperty::SUBTITLE_STREAMS); - film_content_changed (CaptionContentProperty::USE); - film_content_changed (CaptionContentProperty::BURN); - film_content_changed (CaptionContentProperty::X_OFFSET); - film_content_changed (CaptionContentProperty::Y_OFFSET); - film_content_changed (CaptionContentProperty::X_SCALE); - film_content_changed (CaptionContentProperty::Y_SCALE); - film_content_changed (CaptionContentProperty::LINE_SPACING); - film_content_changed (CaptionContentProperty::LANGUAGE); - film_content_changed (CaptionContentProperty::FONTS); - film_content_changed (CaptionContentProperty::TYPE); - film_content_changed (DCPContentProperty::REFERENCE_CAPTION); -} - -void -CaptionPanel::caption_view_clicked () -{ - if (_caption_view) { - _caption_view->Destroy (); - _caption_view = 0; - } - - ContentList c = _parent->selected_caption (); - DCPOMATIC_ASSERT (c.size() == 1); - - shared_ptr decoder = decoder_factory (c.front(), _parent->film()->log(), false); - - if (decoder) { - _caption_view = new CaptionView (this, _parent->film(), c.front(), c.front()->caption_of_original_type(_original_type), decoder, _parent->film_viewer()); - _caption_view->Show (); - } -} - -void -CaptionPanel::fonts_dialog_clicked () -{ - if (_fonts_dialog) { - _fonts_dialog->Destroy (); - _fonts_dialog = 0; - } - - ContentList c = _parent->selected_caption (); - DCPOMATIC_ASSERT (c.size() == 1); - - _fonts_dialog = new FontsDialog (this, c.front(), c.front()->caption_of_original_type(_original_type)); - _fonts_dialog->Show (); -} - -void -CaptionPanel::reference_clicked () -{ - ContentList c = _parent->selected (); - if (c.size() != 1) { - return; - } - - shared_ptr d = dynamic_pointer_cast (c.front ()); - if (!d) { - return; - } - - d->set_reference_caption (_original_type, _reference->GetValue ()); -} - -void -CaptionPanel::appearance_dialog_clicked () -{ - ContentList c = _parent->selected_caption (); - DCPOMATIC_ASSERT (c.size() == 1); - - CaptionAppearanceDialog* d = new CaptionAppearanceDialog (this, c.front(), c.front()->caption_of_original_type(_original_type)); - if (d->ShowModal () == wxID_OK) { - d->apply (); - } - d->Destroy (); -} diff --git a/src/wx/caption_panel.h b/src/wx/caption_panel.h deleted file mode 100644 index 20af29d7e..000000000 --- a/src/wx/caption_panel.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - Copyright (C) 2012-2018 Carl Hetherington - - This file is part of DCP-o-matic. - - DCP-o-matic is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - DCP-o-matic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with DCP-o-matic. If not, see . - -*/ - -#include "content_sub_panel.h" - -class wxCheckBox; -class wxSpinCtrl; -class CaptionView; -class FontsDialog; - -class CaptionPanel : public ContentSubPanel -{ -public: - CaptionPanel (ContentPanel *, CaptionType t); - - void film_changed (Film::Property); - void film_content_changed (int); - void content_selection_changed (); - -private: - void use_toggled (); - void type_changed (); - void burn_toggled (); - void x_offset_changed (); - void y_offset_changed (); - void x_scale_changed (); - void y_scale_changed (); - void line_spacing_changed (); - void language_changed (); - void stream_changed (); - void caption_view_clicked (); - void fonts_dialog_clicked (); - void reference_clicked (); - void appearance_dialog_clicked (); - - void setup_sensitivity (); - - wxCheckBox* _reference; - wxStaticText* _reference_note; - wxCheckBox* _use; - wxChoice* _type; - wxCheckBox* _burn; - wxSpinCtrl* _x_offset; - wxSpinCtrl* _y_offset; - wxSpinCtrl* _x_scale; - wxSpinCtrl* _y_scale; - wxSpinCtrl* _line_spacing; - wxTextCtrl* _language; - wxChoice* _stream; - wxButton* _caption_view_button; - CaptionView* _caption_view; - wxButton* _fonts_dialog_button; - FontsDialog* _fonts_dialog; - wxButton* _appearance_dialog_button; - CaptionType _original_type; -}; diff --git a/src/wx/caption_view.cc b/src/wx/caption_view.cc deleted file mode 100644 index e6e63efff..000000000 --- a/src/wx/caption_view.cc +++ /dev/null @@ -1,139 +0,0 @@ -/* - Copyright (C) 2014-2018 Carl Hetherington - - This file is part of DCP-o-matic. - - DCP-o-matic is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - DCP-o-matic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with DCP-o-matic. If not, see . - -*/ - -#include "lib/text_caption_file_decoder.h" -#include "lib/content_caption.h" -#include "lib/video_decoder.h" -#include "lib/audio_decoder.h" -#include "lib/film.h" -#include "lib/config.h" -#include "lib/text_caption_file_content.h" -#include "lib/caption_decoder.h" -#include "caption_view.h" -#include "film_viewer.h" -#include "wx_util.h" - -using std::list; -using boost::shared_ptr; -using boost::bind; -using boost::dynamic_pointer_cast; - -CaptionView::CaptionView (wxWindow* parent, shared_ptr film, shared_ptr content, shared_ptr caption, shared_ptr decoder, FilmViewer* viewer) - : wxDialog (parent, wxID_ANY, _("Captions"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) - , _content (content) - , _film_viewer (viewer) -{ - _list = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_SINGLE_SEL); - - { - wxListItem ip; - ip.SetId (0); - ip.SetText (_("Start")); - ip.SetWidth (100); - _list->InsertColumn (0, ip); - } - - { - wxListItem ip; - ip.SetId (1); - ip.SetText (_("End")); - ip.SetWidth (100); - _list->InsertColumn (1, ip); - } - - { - wxListItem ip; - ip.SetId (2); - ip.SetText (_("Caption")); - ip.SetWidth (640); - _list->InsertColumn (2, ip); - } - - wxBoxSizer* sizer = new wxBoxSizer (wxVERTICAL); - sizer->Add (_list, 1, wxEXPAND | wxALL, DCPOMATIC_SIZER_X_GAP); - - _list->Bind (wxEVT_LIST_ITEM_SELECTED, boost::bind (&CaptionView::subtitle_selected, this, _1)); - - wxSizer* buttons = CreateSeparatedButtonSizer (wxOK); - if (buttons) { - sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder()); - } - - if (decoder->video) { - decoder->video->set_ignore (true); - } - if (decoder->audio) { - decoder->audio->set_ignore (true); - } - - _subs = 0; - _frc = film->active_frame_rate_change (content->position()); - - /* Find the decoder that is being used for our CaptionContent and attach to it */ - BOOST_FOREACH (shared_ptr i, decoder->caption) { - if (i->content() == caption) { - i->PlainStart.connect (bind (&CaptionView::data_start, this, _1)); - i->Stop.connect (bind (&CaptionView::data_stop, this, _1)); - } - } - while (!decoder->pass ()) {} - SetSizerAndFit (sizer); -} - -void -CaptionView::data_start (ContentTextCaption cts) -{ - BOOST_FOREACH (dcp::SubtitleString const & i, cts.subs) { - wxListItem list_item; - list_item.SetId (_subs); - _list->InsertItem (list_item); - _list->SetItem (_subs, 0, std_to_wx (cts.from().timecode (_frc->source))); - _list->SetItem (_subs, 2, std_to_wx (i.text ())); - _start_times.push_back (cts.from ()); - ++_subs; - } - - _last_count = cts.subs.size (); -} - -void -CaptionView::data_stop (ContentTime time) -{ - if (!_last_count) { - return; - } - - for (int i = _subs - *_last_count; i < _subs; ++i) { - _list->SetItem (i, 1, std_to_wx (time.timecode (_frc->source))); - } -} - -void -CaptionView::subtitle_selected (wxListEvent& ev) -{ - if (!Config::instance()->jump_to_selected ()) { - return; - } - - DCPOMATIC_ASSERT (ev.GetIndex() < int(_start_times.size())); - shared_ptr locked = _content.lock (); - DCPOMATIC_ASSERT (locked); - _film_viewer->set_position (locked, _start_times[ev.GetIndex()]); -} diff --git a/src/wx/caption_view.h b/src/wx/caption_view.h deleted file mode 100644 index 71c492ad6..000000000 --- a/src/wx/caption_view.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - Copyright (C) 2014-2018 Carl Hetherington - - This file is part of DCP-o-matic. - - DCP-o-matic is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - DCP-o-matic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with DCP-o-matic. If not, see . - -*/ - -#include "lib/content_caption.h" -#include -#include -#include - -class Decoder; -class FilmViewer; - -class CaptionView : public wxDialog -{ -public: - CaptionView ( - wxWindow *, boost::shared_ptr, boost::shared_ptr content, boost::shared_ptr caption, boost::shared_ptr, FilmViewer* viewer - ); - -private: - void data_start (ContentTextCaption cts); - void data_stop (ContentTime time); - void subtitle_selected (wxListEvent &); - - wxListCtrl* _list; - int _subs; - boost::optional _frc; - boost::optional _last_count; - std::vector _start_times; - boost::weak_ptr _content; - FilmViewer* _film_viewer; -}; diff --git a/src/wx/closed_captions_dialog.cc b/src/wx/closed_captions_dialog.cc index 0b2e63035..3e240c6e8 100644 --- a/src/wx/closed_captions_dialog.cc +++ b/src/wx/closed_captions_dialog.cc @@ -19,7 +19,7 @@ */ #include "closed_captions_dialog.h" -#include "lib/text_caption.h" +#include "lib/string_text.h" #include using std::list; @@ -70,13 +70,13 @@ ClosedCaptionsDialog::paint () class ClosedCaptionSorter { public: - bool operator() (TextCaption const & a, TextCaption const & b) + bool operator() (StringText const & a, StringText const & b) { return from_top(a) < from_top(b); } private: - float from_top (TextCaption const & c) const + float from_top (StringText const & c) const { switch (c.v_align()) { case dcp::VALIGN_TOP: @@ -96,9 +96,9 @@ ClosedCaptionsDialog::update (DCPTime time) { shared_ptr player = _player.lock (); DCPOMATIC_ASSERT (player); - list to_show; - BOOST_FOREACH (PlayerCaption i, player->closed_captions_for_frame(time)) { - BOOST_FOREACH (TextCaption j, i.text) { + list to_show; + BOOST_FOREACH (PlayerText i, player->closed_captions_for_frame(time)) { + BOOST_FOREACH (StringText j, i.text) { to_show.push_back (j); } } @@ -109,7 +109,7 @@ ClosedCaptionsDialog::update (DCPTime time) to_show.sort (ClosedCaptionSorter()); - list::const_iterator j = to_show.begin(); + list::const_iterator j = to_show.begin(); int k = 0; while (j != to_show.end() && k < _num_lines) { _lines[k] = j->text(); diff --git a/src/wx/content_panel.cc b/src/wx/content_panel.cc index ce9c66a3e..a6338ecfd 100644 --- a/src/wx/content_panel.cc +++ b/src/wx/content_panel.cc @@ -22,13 +22,13 @@ #include "wx_util.h" #include "video_panel.h" #include "audio_panel.h" -#include "caption_panel.h" +#include "text_panel.h" #include "timing_panel.h" #include "timeline_dialog.h" #include "image_sequence_dialog.h" #include "film_viewer.h" #include "lib/audio_content.h" -#include "lib/caption_content.h" +#include "lib/text_content.h" #include "lib/video_content.h" #include "lib/ffmpeg_content.h" #include "lib/content_factory.h" @@ -39,8 +39,8 @@ #include "lib/config.h" #include "lib/log.h" #include "lib/compose.hpp" -#include "lib/text_caption_file_content.h" -#include "lib/text_caption_file.h" +#include "lib/string_text_file_content.h" +#include "lib/string_text_file.h" #include #include #include @@ -128,7 +128,7 @@ ContentPanel::ContentPanel (wxNotebook* n, boost::shared_ptr film, FilmVie _audio_panel = new AudioPanel (this); _panels.push_back (_audio_panel); for (int i = 0; i < CAPTION_COUNT; ++i) { - _caption_panel[i] = new CaptionPanel (this, static_cast(i)); + _caption_panel[i] = new TextPanel (this, static_cast(i)); _panels.push_back (_caption_panel[i]); } _timing_panel = new TimingPanel (this, _film_viewer); @@ -262,11 +262,11 @@ ContentPanel::selection_changed () BOOST_FOREACH (shared_ptr i, selected()) { DCPTime p; p = i->position(); - if (dynamic_pointer_cast(i) && i->paths_valid()) { + if (dynamic_pointer_cast(i) && i->paths_valid()) { /* Rather special case; if we select a text subtitle file jump to its first subtitle. */ - TextCaptionFile ts (dynamic_pointer_cast(i)); + StringTextFile ts (dynamic_pointer_cast(i)); if (ts.first()) { p += DCPTime(ts.first().get(), _film->active_frame_rate_change(i->position())); } @@ -306,7 +306,7 @@ ContentPanel::selection_changed () if (i->audio) { have_audio = true; } - BOOST_FOREACH (shared_ptr j, i->caption) { + BOOST_FOREACH (shared_ptr j, i->caption) { have_caption[j->original_type()] = true; } } diff --git a/src/wx/content_panel.h b/src/wx/content_panel.h index 3f0fb17a5..d31375c8e 100644 --- a/src/wx/content_panel.h +++ b/src/wx/content_panel.h @@ -32,7 +32,7 @@ class wxListEvent; class TimelineDialog; class FilmEditor; class ContentSubPanel; -class CaptionPanel; +class TextPanel; class AudioPanel; class Film; class FilmViewer; @@ -105,7 +105,7 @@ private: wxButton* _timeline; ContentSubPanel* _video_panel; AudioPanel* _audio_panel; - CaptionPanel* _caption_panel[CAPTION_COUNT]; + TextPanel* _caption_panel[CAPTION_COUNT]; ContentSubPanel* _timing_panel; std::list _panels; ContentMenu* _menu; diff --git a/src/wx/dcp_panel.cc b/src/wx/dcp_panel.cc index 51881030f..f1f82287d 100644 --- a/src/wx/dcp_panel.cc +++ b/src/wx/dcp_panel.cc @@ -32,7 +32,7 @@ #include "lib/ffmpeg_content.h" #include "lib/audio_processor.h" #include "lib/video_content.h" -#include "lib/caption_content.h" +#include "lib/text_content.h" #include "lib/dcp_content.h" #include "lib/audio_content.h" #include @@ -433,8 +433,8 @@ void DCPPanel::film_content_changed (int property) { if (property == AudioContentProperty::STREAMS || - property == CaptionContentProperty::USE || - property == CaptionContentProperty::BURN || + property == TextContentProperty::USE || + property == TextContentProperty::BURN || property == VideoContentProperty::SCALE || property == DCPContentProperty::REFERENCE_VIDEO || property == DCPContentProperty::REFERENCE_AUDIO || diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h index 266509a44..e4449fa2f 100644 --- a/src/wx/film_viewer.h +++ b/src/wx/film_viewer.h @@ -24,7 +24,7 @@ #include "lib/film.h" #include "lib/config.h" -#include "lib/player_caption.h" +#include "lib/player_text.h" #include #include diff --git a/src/wx/fonts_dialog.cc b/src/wx/fonts_dialog.cc index 269dad678..3619b7e0a 100644 --- a/src/wx/fonts_dialog.cc +++ b/src/wx/fonts_dialog.cc @@ -24,7 +24,7 @@ #include "font_files_dialog.h" #include "lib/font.h" #include "lib/content.h" -#include "lib/caption_content.h" +#include "lib/text_content.h" #include #include #include @@ -34,7 +34,7 @@ using std::string; using std::cout; using boost::shared_ptr; -FontsDialog::FontsDialog (wxWindow* parent, shared_ptr content, shared_ptr caption) +FontsDialog::FontsDialog (wxWindow* parent, shared_ptr content, shared_ptr caption) : wxDialog (parent, wxID_ANY, _("Fonts")) , _content (content) , _caption (caption) @@ -100,7 +100,7 @@ void FontsDialog::setup () { shared_ptr content = _content.lock (); - shared_ptr caption = _caption.lock (); + shared_ptr caption = _caption.lock (); if (!content || !caption) { return; } @@ -140,7 +140,7 @@ void FontsDialog::edit_clicked () { shared_ptr content = _content.lock (); - shared_ptr caption = _caption.lock (); + shared_ptr caption = _caption.lock (); if (!content || !caption) { return; } diff --git a/src/wx/fonts_dialog.h b/src/wx/fonts_dialog.h index 6c6873ea3..ba98e0963 100644 --- a/src/wx/fonts_dialog.h +++ b/src/wx/fonts_dialog.h @@ -25,12 +25,12 @@ #include class Content; -class CaptionContent; +class TextContent; class FontsDialog : public wxDialog { public: - FontsDialog (wxWindow* parent, boost::shared_ptr, boost::shared_ptr caption); + FontsDialog (wxWindow* parent, boost::shared_ptr, boost::shared_ptr caption); private: void setup (); @@ -39,7 +39,7 @@ private: void edit_clicked (); boost::weak_ptr _content; - boost::weak_ptr _caption; + boost::weak_ptr _caption; wxListCtrl* _fonts; wxButton* _edit; }; diff --git a/src/wx/subtitle_appearance_dialog.cc b/src/wx/subtitle_appearance_dialog.cc new file mode 100644 index 000000000..cab473c18 --- /dev/null +++ b/src/wx/subtitle_appearance_dialog.cc @@ -0,0 +1,283 @@ +/* + Copyright (C) 2015-2018 Carl Hetherington + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see . + +*/ + +#include "subtitle_appearance_dialog.h" +#include "rgba_colour_picker.h" +#include "lib/string_text_file_content.h" +#include "lib/text_content.h" +#include "lib/ffmpeg_subtitle_stream.h" +#include "lib/ffmpeg_content.h" +#include +#include +#include +#include + +using std::map; +using boost::shared_ptr; +using boost::bind; +using boost::dynamic_pointer_cast; +using boost::optional; + +int const SubtitleAppearanceDialog::NONE = 0; +int const SubtitleAppearanceDialog::OUTLINE = 1; +int const SubtitleAppearanceDialog::SHADOW = 2; + +SubtitleAppearanceDialog::SubtitleAppearanceDialog (wxWindow* parent, shared_ptr content, shared_ptr caption) + : wxDialog (parent, wxID_ANY, _("Caption appearance")) + , _content (content) + , _caption (caption) +{ + shared_ptr ff = dynamic_pointer_cast (content); + if (ff) { + _stream = ff->subtitle_stream (); + } + + wxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL); + SetSizer (overall_sizer); + + _table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP); + + overall_sizer->Add (_table, 1, wxEXPAND | wxALL, DCPOMATIC_DIALOG_BORDER); + + int r = 0; + + add_label_to_sizer (_table, this, _("Colour"), true, wxGBPosition (r, 0)); + _force_colour = set_to (_colour = new wxColourPickerCtrl (this, wxID_ANY), r); + + add_label_to_sizer (_table, this, _("Effect"), true, wxGBPosition (r, 0)); + _force_effect = set_to (_effect = new wxChoice (this, wxID_ANY), r); + + add_label_to_sizer (_table, this, _("Effect colour"), true, wxGBPosition (r, 0)); + _force_effect_colour = set_to (_effect_colour = new wxColourPickerCtrl (this, wxID_ANY), r); + + add_label_to_sizer (_table, this, _("Outline width"), true, wxGBPosition (r, 0)); + _outline_width = new wxSpinCtrl (this, wxID_ANY); + _table->Add (_outline_width, wxGBPosition (r, 1)); + ++r; + + add_label_to_sizer (_table, this, _("Fade in time"), true, wxGBPosition (r, 0)); + _force_fade_in = set_to (_fade_in = new Timecode (this), r); + + add_label_to_sizer (_table, this, _("Fade out time"), true, wxGBPosition (r, 0)); + _force_fade_out = set_to (_fade_out = new Timecode (this), r); + + if (_stream) { + wxScrolled* colours_panel = new wxScrolled (this); + colours_panel->EnableScrolling (false, true); + colours_panel->ShowScrollbars (wxSHOW_SB_NEVER, wxSHOW_SB_ALWAYS); + colours_panel->SetScrollRate (0, 16); + + wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP); + table->AddGrowableCol (1, 1); + + map colours = _stream->colours (); + + wxStaticText* t = new wxStaticText (colours_panel, wxID_ANY, ""); + t->SetLabelMarkup (_("Original colour")); + table->Add (t, 1, wxEXPAND); + t = new wxStaticText (colours_panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL); + t->SetLabelMarkup (_("New colour")); + table->Add (t, 1, wxALIGN_CENTER); + + for (map::const_iterator i = colours.begin(); i != colours.end(); ++i) { + wxPanel* from = new wxPanel (colours_panel, wxID_ANY); + from->SetBackgroundColour (wxColour (i->first.r, i->first.g, i->first.b, i->first.a)); + table->Add (from, 1, wxEXPAND); + RGBAColourPicker* to = new RGBAColourPicker (colours_panel, i->second); + table->Add (to, 1, wxEXPAND); + _pickers[i->first] = to; + } + + colours_panel->SetSizer (table); + + overall_sizer->Add (colours_panel, 1, wxEXPAND | wxALL, DCPOMATIC_DIALOG_BORDER); + + wxButton* restore = new wxButton (this, wxID_ANY, _("Restore to original colours")); + restore->Bind (wxEVT_BUTTON, bind (&SubtitleAppearanceDialog::restore, this)); + overall_sizer->Add (restore, 0, wxALL, DCPOMATIC_SIZER_X_GAP); + } + + wxSizer* buttons = CreateSeparatedButtonSizer (wxOK); + if (buttons) { + overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder()); + } + + overall_sizer->Layout (); + overall_sizer->SetSizeHints (this); + + /* Keep these Appends() up to date with NONE/OUTLINE/SHADOW variables */ + _effect->Append (_("None")); + _effect->Append (_("Outline")); + _effect->Append (_("Shadow"));; + + optional colour = _caption->colour(); + _force_colour->SetValue (static_cast(colour)); + if (colour) { + _colour->SetColour (wxColour (colour->r, colour->g, colour->b)); + } else { + _colour->SetColour (wxColour (255, 255, 255)); + } + + optional effect = _caption->effect(); + _force_effect->SetValue (static_cast(effect)); + if (effect) { + switch (*effect) { + case dcp::NONE: + _effect->SetSelection (NONE); + break; + case dcp::BORDER: + _effect->SetSelection (OUTLINE); + break; + case dcp::SHADOW: + _effect->SetSelection (SHADOW); + break; + } + } else { + _effect->SetSelection (NONE); + } + + optional effect_colour = _caption->effect_colour(); + _force_effect_colour->SetValue (static_cast(effect_colour)); + if (effect_colour) { + _effect_colour->SetColour (wxColour (effect_colour->r, effect_colour->g, effect_colour->b)); + } else { + _effect_colour->SetColour (wxColour (0, 0, 0)); + } + + optional fade_in = _caption->fade_in(); + _force_fade_in->SetValue (static_cast(fade_in)); + if (fade_in) { + _fade_in->set (*fade_in, _content->active_video_frame_rate()); + } else { + _fade_in->set (ContentTime(), _content->active_video_frame_rate()); + } + + optional fade_out = _caption->fade_out(); + _force_fade_out->SetValue (static_cast(fade_out)); + if (fade_out) { + _fade_out->set (*fade_out, _content->active_video_frame_rate ()); + } else { + _fade_out->set (ContentTime(), _content->active_video_frame_rate ()); + } + + _outline_width->SetValue (_caption->outline_width ()); + + _force_colour->Bind (wxEVT_CHECKBOX, bind (&SubtitleAppearanceDialog::setup_sensitivity, this)); + _force_effect_colour->Bind (wxEVT_CHECKBOX, bind (&SubtitleAppearanceDialog::setup_sensitivity, this)); + _force_effect->Bind (wxEVT_CHECKBOX, bind (&SubtitleAppearanceDialog::setup_sensitivity, this)); + _force_fade_in->Bind (wxEVT_CHECKBOX, bind (&SubtitleAppearanceDialog::setup_sensitivity, this)); + _force_fade_out->Bind (wxEVT_CHECKBOX, bind (&SubtitleAppearanceDialog::setup_sensitivity, this)); + _effect->Bind (wxEVT_CHOICE, bind (&SubtitleAppearanceDialog::setup_sensitivity, this)); + _content_connection = _content->Changed.connect (bind (&SubtitleAppearanceDialog::setup_sensitivity, this)); + + setup_sensitivity (); +} + +wxCheckBox* +SubtitleAppearanceDialog::set_to (wxWindow* w, int& r) +{ + wxSizer* s = new wxBoxSizer (wxHORIZONTAL); + wxCheckBox* set_to = new wxCheckBox (this, wxID_ANY, _("Set to")); + s->Add (set_to, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 8); + s->Add (w, 0, wxALIGN_CENTER_VERTICAL); + _table->Add (s, wxGBPosition (r, 1)); + ++r; + return set_to; +} + +void +SubtitleAppearanceDialog::apply () +{ + if (_force_colour->GetValue ()) { + wxColour const c = _colour->GetColour (); + _caption->set_colour (dcp::Colour (c.Red(), c.Green(), c.Blue())); + } else { + _caption->unset_colour (); + } + if (_force_effect->GetValue()) { + switch (_effect->GetSelection()) { + case NONE: + _caption->set_effect (dcp::NONE); + break; + case OUTLINE: + _caption->set_effect (dcp::BORDER); + break; + case SHADOW: + _caption->set_effect (dcp::SHADOW); + break; + } + } else { + _caption->unset_effect (); + } + if (_force_effect_colour->GetValue ()) { + wxColour const ec = _effect_colour->GetColour (); + _caption->set_effect_colour (dcp::Colour (ec.Red(), ec.Green(), ec.Blue())); + } else { + _caption->unset_effect_colour (); + } + if (_force_fade_in->GetValue ()) { + _caption->set_fade_in (_fade_in->get (_content->active_video_frame_rate ())); + } else { + _caption->unset_fade_in (); + } + if (_force_fade_out->GetValue ()) { + _caption->set_fade_out (_fade_out->get (_content->active_video_frame_rate ())); + } else { + _caption->unset_fade_out (); + } + _caption->set_outline_width (_outline_width->GetValue ()); + + if (_stream) { + for (map::const_iterator i = _pickers.begin(); i != _pickers.end(); ++i) { + _stream->set_colour (i->first, i->second->colour ()); + } + } + + shared_ptr fc = dynamic_pointer_cast (_content); + if (fc) { + fc->signal_subtitle_stream_changed (); + } +} + +void +SubtitleAppearanceDialog::restore () +{ + for (map::const_iterator i = _pickers.begin(); i != _pickers.end(); ++i) { + i->second->set (i->first); + } +} + +void +SubtitleAppearanceDialog::setup_sensitivity () +{ + _colour->Enable (_force_colour->GetValue ()); + _effect_colour->Enable (_force_effect_colour->GetValue ()); + _effect->Enable (_force_effect->GetValue ()); + _fade_in->Enable (_force_fade_in->GetValue ()); + _fade_out->Enable (_force_fade_out->GetValue ()); + + bool const can_outline_width = _effect->GetSelection() == OUTLINE && _caption->burn (); + _outline_width->Enable (can_outline_width); + if (can_outline_width) { + _outline_width->UnsetToolTip (); + } else { + _outline_width->SetToolTip (_("Outline width cannot be set unless you are burning in captions")); + } +} diff --git a/src/wx/subtitle_appearance_dialog.h b/src/wx/subtitle_appearance_dialog.h new file mode 100644 index 000000000..6cced717b --- /dev/null +++ b/src/wx/subtitle_appearance_dialog.h @@ -0,0 +1,71 @@ +/* + Copyright (C) 2015-2018 Carl Hetherington + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see . + +*/ + +#include "timecode.h" +#include "lib/rgba.h" +#include +#include +#include + +class wxRadioButton; +class wxColourPickerCtrl; +class wxGridBagSizer; +class Content; +class RGBAColourPicker; +class FFmpegSubtitleStream; +class wxCheckBox; +class wxWidget; + +class SubtitleAppearanceDialog : public wxDialog +{ +public: + SubtitleAppearanceDialog (wxWindow* parent, boost::shared_ptr content, boost::shared_ptr caption); + + void apply (); + +private: + void setup_sensitivity (); + void restore (); + wxCheckBox* set_to (wxWindow* w, int& r); + + wxCheckBox* _force_colour; + wxColourPickerCtrl* _colour; + wxCheckBox* _force_effect; + wxChoice* _effect; + wxCheckBox* _force_effect_colour; + wxColourPickerCtrl* _effect_colour; + wxCheckBox* _force_fade_in; + Timecode* _fade_in; + wxCheckBox* _force_fade_out; + Timecode* _fade_out; + wxSpinCtrl* _outline_width; + wxGridBagSizer* _table; + std::map _pickers; + + boost::shared_ptr _content; + boost::shared_ptr _caption; + boost::shared_ptr _stream; + + boost::signals2::scoped_connection _content_connection; + + static int const NONE; + static int const OUTLINE; + static int const SHADOW; +}; diff --git a/src/wx/text_panel.cc b/src/wx/text_panel.cc new file mode 100644 index 000000000..bc1183443 --- /dev/null +++ b/src/wx/text_panel.cc @@ -0,0 +1,506 @@ +/* + Copyright (C) 2012-2018 Carl Hetherington + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see . + +*/ + +#include "text_panel.h" +#include "film_editor.h" +#include "wx_util.h" +#include "text_view.h" +#include "content_panel.h" +#include "fonts_dialog.h" +#include "subtitle_appearance_dialog.h" +#include "lib/ffmpeg_content.h" +#include "lib/string_text_file_content.h" +#include "lib/ffmpeg_subtitle_stream.h" +#include "lib/dcp_subtitle_content.h" +#include "lib/string_text_file_decoder.h" +#include "lib/dcp_subtitle_decoder.h" +#include "lib/dcp_content.h" +#include "lib/text_content.h" +#include "lib/decoder_factory.h" +#include +#include + +using std::vector; +using std::string; +using std::list; +using std::cout; +using boost::shared_ptr; +using boost::dynamic_pointer_cast; + +TextPanel::TextPanel (ContentPanel* p, TextType t) + : ContentSubPanel (p, std_to_wx(caption_type_to_name(t))) + , _caption_view (0) + , _fonts_dialog (0) + , _original_type (t) +{ + wxBoxSizer* reference_sizer = new wxBoxSizer (wxVERTICAL); + + _reference = new wxCheckBox (this, wxID_ANY, _("Use this DCP's subtitle as OV and make VF")); + reference_sizer->Add (_reference, 0, wxLEFT | wxRIGHT | wxTOP, DCPOMATIC_SIZER_GAP); + + _reference_note = new wxStaticText (this, wxID_ANY, _("")); + _reference_note->Wrap (200); + reference_sizer->Add (_reference_note, 0, wxLEFT | wxRIGHT, DCPOMATIC_SIZER_GAP); + wxFont font = _reference_note->GetFont(); + font.SetStyle(wxFONTSTYLE_ITALIC); + font.SetPointSize(font.GetPointSize() - 1); + _reference_note->SetFont(font); + + _sizer->Add (reference_sizer); + + wxGridBagSizer* grid = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP); + _sizer->Add (grid, 0, wxALL, 8); + int r = 0; + + wxBoxSizer* use = new wxBoxSizer (wxHORIZONTAL); + _use = new wxCheckBox (this, wxID_ANY, _("Use as")); + use->Add (_use, 0, wxEXPAND | wxRIGHT, DCPOMATIC_SIZER_GAP); + _type = new wxChoice (this, wxID_ANY); + _type->Append (_("subtitles (open captions)")); + _type->Append (_("closed captions")); + use->Add (_type, 1, wxEXPAND, 0); + grid->Add (use, wxGBPosition (r, 0), wxGBSpan (1, 2)); + ++r; + + _burn = new wxCheckBox (this, wxID_ANY, _("Burn subtitles into image")); + grid->Add (_burn, wxGBPosition (r, 0), wxGBSpan (1, 2)); + ++r; + + { + add_label_to_sizer (grid, this, _("X Offset"), true, wxGBPosition (r, 0)); + wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); + _x_offset = new wxSpinCtrl (this); + s->Add (_x_offset); + add_label_to_sizer (s, this, _("%"), false); + grid->Add (s, wxGBPosition (r, 1)); + ++r; + } + + { + add_label_to_sizer (grid, this, _("Y Offset"), true, wxGBPosition (r, 0)); + wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); + _y_offset = new wxSpinCtrl (this); + s->Add (_y_offset); + add_label_to_sizer (s, this, _("%"), false); + grid->Add (s, wxGBPosition (r, 1)); + ++r; + } + + { + add_label_to_sizer (grid, this, _("X Scale"), true, wxGBPosition (r, 0)); + wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); + _x_scale = new wxSpinCtrl (this); + s->Add (_x_scale); + add_label_to_sizer (s, this, _("%"), false); + grid->Add (s, wxGBPosition (r, 1)); + ++r; + } + + { + add_label_to_sizer (grid, this, _("Y Scale"), true, wxGBPosition (r, 0)); + wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); + _y_scale = new wxSpinCtrl (this); + s->Add (_y_scale); + add_label_to_sizer (s, this, _("%"), false); + grid->Add (s, wxGBPosition (r, 1)); + ++r; + } + + { + add_label_to_sizer (grid, this, _("Line spacing"), true, wxGBPosition (r, 0)); + wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); + _line_spacing = new wxSpinCtrl (this); + s->Add (_line_spacing); + add_label_to_sizer (s, this, _("%"), false); + grid->Add (s, wxGBPosition (r, 1)); + ++r; + } + + add_label_to_sizer (grid, this, _("Language"), true, wxGBPosition (r, 0)); + _language = new wxTextCtrl (this, wxID_ANY); + grid->Add (_language, wxGBPosition (r, 1)); + ++r; + + add_label_to_sizer (grid, this, _("Stream"), true, wxGBPosition (r, 0)); + _stream = new wxChoice (this, wxID_ANY); + grid->Add (_stream, wxGBPosition (r, 1)); + ++r; + + { + wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); + + _caption_view_button = new wxButton (this, wxID_ANY, _("View...")); + s->Add (_caption_view_button, 1, wxALL, DCPOMATIC_SIZER_GAP); + _fonts_dialog_button = new wxButton (this, wxID_ANY, _("Fonts...")); + s->Add (_fonts_dialog_button, 1, wxALL, DCPOMATIC_SIZER_GAP); + _appearance_dialog_button = new wxButton (this, wxID_ANY, _("Appearance...")); + s->Add (_appearance_dialog_button, 1, wxALL, DCPOMATIC_SIZER_GAP); + + grid->Add (s, wxGBPosition (r, 0), wxGBSpan (1, 2)); + ++r; + } + + _x_offset->SetRange (-100, 100); + _y_offset->SetRange (-100, 100); + _x_scale->SetRange (10, 1000); + _y_scale->SetRange (10, 1000); + _line_spacing->SetRange (10, 1000); + + _reference->Bind (wxEVT_CHECKBOX, boost::bind (&TextPanel::reference_clicked, this)); + _use->Bind (wxEVT_CHECKBOX, boost::bind (&TextPanel::use_toggled, this)); + _type->Bind (wxEVT_CHOICE, boost::bind (&TextPanel::type_changed, this)); + _burn->Bind (wxEVT_CHECKBOX, boost::bind (&TextPanel::burn_toggled, this)); + _x_offset->Bind (wxEVT_SPINCTRL, boost::bind (&TextPanel::x_offset_changed, this)); + _y_offset->Bind (wxEVT_SPINCTRL, boost::bind (&TextPanel::y_offset_changed, this)); + _x_scale->Bind (wxEVT_SPINCTRL, boost::bind (&TextPanel::x_scale_changed, this)); + _y_scale->Bind (wxEVT_SPINCTRL, boost::bind (&TextPanel::y_scale_changed, this)); + _line_spacing->Bind (wxEVT_SPINCTRL, boost::bind (&TextPanel::line_spacing_changed, this)); + _language->Bind (wxEVT_TEXT, boost::bind (&TextPanel::language_changed, this)); + _stream->Bind (wxEVT_CHOICE, boost::bind (&TextPanel::stream_changed, this)); + _caption_view_button->Bind (wxEVT_BUTTON, boost::bind (&TextPanel::caption_view_clicked, this)); + _fonts_dialog_button->Bind (wxEVT_BUTTON, boost::bind (&TextPanel::fonts_dialog_clicked, this)); + _appearance_dialog_button->Bind (wxEVT_BUTTON, boost::bind (&TextPanel::appearance_dialog_clicked, this)); +} + +void +TextPanel::film_changed (Film::Property property) +{ + if (property == Film::CONTENT || property == Film::REEL_TYPE) { + setup_sensitivity (); + } +} + +void +TextPanel::film_content_changed (int property) +{ + FFmpegContentList fc = _parent->selected_ffmpeg (); + ContentList sc = _parent->selected_caption (); + + shared_ptr fcs; + if (fc.size() == 1) { + fcs = fc.front (); + } + + shared_ptr scs; + if (sc.size() == 1) { + scs = sc.front (); + } + + shared_ptr caption; + if (scs) { + caption = scs->caption_of_original_type(_original_type); + } + + if (property == FFmpegContentProperty::SUBTITLE_STREAMS) { + _stream->Clear (); + if (fcs) { + vector > s = fcs->subtitle_streams (); + for (vector >::iterator i = s.begin(); i != s.end(); ++i) { + _stream->Append (std_to_wx ((*i)->name), new wxStringClientData (std_to_wx ((*i)->identifier ()))); + } + + if (fcs->subtitle_stream()) { + checked_set (_stream, fcs->subtitle_stream()->identifier ()); + } else { + _stream->SetSelection (wxNOT_FOUND); + } + } + setup_sensitivity (); + } else if (property == TextContentProperty::USE) { + checked_set (_use, caption ? caption->use() : false); + setup_sensitivity (); + } else if (property == TextContentProperty::TYPE) { + if (caption) { + switch (caption->type()) { + case CAPTION_OPEN: + _type->SetSelection (0); + break; + case CAPTION_CLOSED: + _type->SetSelection (1); + break; + default: + DCPOMATIC_ASSERT (false); + } + } else { + _type->SetSelection (0); + } + setup_sensitivity (); + } else if (property == TextContentProperty::BURN) { + checked_set (_burn, caption ? caption->burn() : false); + } else if (property == TextContentProperty::X_OFFSET) { + checked_set (_x_offset, caption ? lrint (caption->x_offset() * 100) : 0); + } else if (property == TextContentProperty::Y_OFFSET) { + checked_set (_y_offset, caption ? lrint (caption->y_offset() * 100) : 0); + } else if (property == TextContentProperty::X_SCALE) { + checked_set (_x_scale, caption ? lrint (caption->x_scale() * 100) : 100); + } else if (property == TextContentProperty::Y_SCALE) { + checked_set (_y_scale, caption ? lrint (caption->y_scale() * 100) : 100); + } else if (property == TextContentProperty::LINE_SPACING) { + checked_set (_line_spacing, caption ? lrint (caption->line_spacing() * 100) : 100); + } else if (property == TextContentProperty::LANGUAGE) { + checked_set (_language, caption ? caption->language() : ""); + } else if (property == DCPContentProperty::REFERENCE_CAPTION) { + if (scs) { + shared_ptr dcp = dynamic_pointer_cast (scs); + checked_set (_reference, dcp ? dcp->reference_caption(_original_type) : false); + } else { + checked_set (_reference, false); + } + + setup_sensitivity (); + } else if (property == DCPContentProperty::CAPTIONS) { + setup_sensitivity (); + } +} + +void +TextPanel::use_toggled () +{ + BOOST_FOREACH (shared_ptr i, _parent->selected_caption()) { + i->caption_of_original_type(_original_type)->set_use (_use->GetValue()); + } +} + +void +TextPanel::type_changed () +{ + BOOST_FOREACH (shared_ptr i, _parent->selected_caption()) { + switch (_type->GetSelection()) { + case 0: + i->caption_of_original_type(_original_type)->set_type (CAPTION_OPEN); + break; + case 1: + i->caption_of_original_type(_original_type)->set_type (CAPTION_CLOSED); + break; + } + } +} + +void +TextPanel::burn_toggled () +{ + BOOST_FOREACH (shared_ptr i, _parent->selected_caption ()) { + i->caption_of_original_type(_original_type)->set_burn (_burn->GetValue()); + } +} + +void +TextPanel::setup_sensitivity () +{ + int any_subs = 0; + int ffmpeg_subs = 0; + ContentList sel = _parent->selected_caption (); + BOOST_FOREACH (shared_ptr i, sel) { + /* These are the content types that could include subtitles */ + shared_ptr fc = boost::dynamic_pointer_cast (i); + shared_ptr sc = boost::dynamic_pointer_cast (i); + shared_ptr dc = boost::dynamic_pointer_cast (i); + shared_ptr dsc = boost::dynamic_pointer_cast (i); + if (fc) { + if (!fc->caption.empty()) { + ++ffmpeg_subs; + ++any_subs; + } + } else if (sc || dc || dsc) { + /* XXX: in the future there could be bitmap subs from DCPs */ + ++any_subs; + } + } + + /* Decide whether we can reference these subs */ + + shared_ptr dcp; + if (sel.size() == 1) { + dcp = dynamic_pointer_cast (sel.front ()); + } + + string why_not; + bool const can_reference = dcp && dcp->can_reference_caption (_original_type, why_not); + setup_refer_button (_reference, _reference_note, dcp, can_reference, why_not); + + bool const reference = _reference->GetValue (); + + /* Set up sensitivity */ + _use->Enable (!reference && any_subs > 0); + bool const use = _use->GetValue (); + _type->Enable (!reference && any_subs > 0 && use); + _burn->Enable (!reference && any_subs > 0 && use && _type->GetSelection() == 0); + _x_offset->Enable (!reference && any_subs > 0 && use); + _y_offset->Enable (!reference && any_subs > 0 && use); + _x_scale->Enable (!reference && any_subs > 0 && use); + _y_scale->Enable (!reference && any_subs > 0 && use); + _line_spacing->Enable (!reference && use); + _language->Enable (!reference && any_subs > 0 && use); + _stream->Enable (!reference && ffmpeg_subs == 1); + _caption_view_button->Enable (!reference); + _fonts_dialog_button->Enable (!reference); + _appearance_dialog_button->Enable (!reference && any_subs > 0 && use); +} + +void +TextPanel::stream_changed () +{ + FFmpegContentList fc = _parent->selected_ffmpeg (); + if (fc.size() != 1) { + return; + } + + shared_ptr fcs = fc.front (); + + vector > a = fcs->subtitle_streams (); + vector >::iterator i = a.begin (); + string const s = string_client_data (_stream->GetClientObject (_stream->GetSelection ())); + while (i != a.end() && (*i)->identifier () != s) { + ++i; + } + + if (i != a.end ()) { + fcs->set_subtitle_stream (*i); + } +} + +void +TextPanel::x_offset_changed () +{ + BOOST_FOREACH (shared_ptr i, _parent->selected_caption ()) { + i->caption_of_original_type(_original_type)->set_x_offset (_x_offset->GetValue() / 100.0); + } +} + +void +TextPanel::y_offset_changed () +{ + BOOST_FOREACH (shared_ptr i, _parent->selected_caption ()) { + i->caption_of_original_type(_original_type)->set_y_offset (_y_offset->GetValue() / 100.0); + } +} + +void +TextPanel::x_scale_changed () +{ + ContentList c = _parent->selected_caption (); + if (c.size() == 1) { + c.front()->caption_of_original_type(_original_type)->set_x_scale (_x_scale->GetValue() / 100.0); + } +} + +void +TextPanel::y_scale_changed () +{ + BOOST_FOREACH (shared_ptr i, _parent->selected_caption ()) { + i->caption_of_original_type(_original_type)->set_y_scale (_y_scale->GetValue() / 100.0); + } +} + +void +TextPanel::line_spacing_changed () +{ + BOOST_FOREACH (shared_ptr i, _parent->selected_caption ()) { + i->caption_of_original_type(_original_type)->set_line_spacing (_line_spacing->GetValue() / 100.0); + } +} + +void +TextPanel::language_changed () +{ + BOOST_FOREACH (shared_ptr i, _parent->selected_caption ()) { + i->caption_of_original_type(_original_type)->set_language (wx_to_std (_language->GetValue())); + } +} + +void +TextPanel::content_selection_changed () +{ + film_content_changed (FFmpegContentProperty::SUBTITLE_STREAMS); + film_content_changed (TextContentProperty::USE); + film_content_changed (TextContentProperty::BURN); + film_content_changed (TextContentProperty::X_OFFSET); + film_content_changed (TextContentProperty::Y_OFFSET); + film_content_changed (TextContentProperty::X_SCALE); + film_content_changed (TextContentProperty::Y_SCALE); + film_content_changed (TextContentProperty::LINE_SPACING); + film_content_changed (TextContentProperty::LANGUAGE); + film_content_changed (TextContentProperty::FONTS); + film_content_changed (TextContentProperty::TYPE); + film_content_changed (DCPContentProperty::REFERENCE_CAPTION); +} + +void +TextPanel::caption_view_clicked () +{ + if (_caption_view) { + _caption_view->Destroy (); + _caption_view = 0; + } + + ContentList c = _parent->selected_caption (); + DCPOMATIC_ASSERT (c.size() == 1); + + shared_ptr decoder = decoder_factory (c.front(), _parent->film()->log(), false); + + if (decoder) { + _caption_view = new TextView (this, _parent->film(), c.front(), c.front()->caption_of_original_type(_original_type), decoder, _parent->film_viewer()); + _caption_view->Show (); + } +} + +void +TextPanel::fonts_dialog_clicked () +{ + if (_fonts_dialog) { + _fonts_dialog->Destroy (); + _fonts_dialog = 0; + } + + ContentList c = _parent->selected_caption (); + DCPOMATIC_ASSERT (c.size() == 1); + + _fonts_dialog = new FontsDialog (this, c.front(), c.front()->caption_of_original_type(_original_type)); + _fonts_dialog->Show (); +} + +void +TextPanel::reference_clicked () +{ + ContentList c = _parent->selected (); + if (c.size() != 1) { + return; + } + + shared_ptr d = dynamic_pointer_cast (c.front ()); + if (!d) { + return; + } + + d->set_reference_caption (_original_type, _reference->GetValue ()); +} + +void +TextPanel::appearance_dialog_clicked () +{ + ContentList c = _parent->selected_caption (); + DCPOMATIC_ASSERT (c.size() == 1); + + SubtitleAppearanceDialog* d = new SubtitleAppearanceDialog (this, c.front(), c.front()->caption_of_original_type(_original_type)); + if (d->ShowModal () == wxID_OK) { + d->apply (); + } + d->Destroy (); +} diff --git a/src/wx/text_panel.h b/src/wx/text_panel.h new file mode 100644 index 000000000..70d46dacd --- /dev/null +++ b/src/wx/text_panel.h @@ -0,0 +1,73 @@ +/* + Copyright (C) 2012-2018 Carl Hetherington + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see . + +*/ + +#include "content_sub_panel.h" + +class wxCheckBox; +class wxSpinCtrl; +class TextView; +class FontsDialog; + +class TextPanel : public ContentSubPanel +{ +public: + TextPanel (ContentPanel *, TextType t); + + void film_changed (Film::Property); + void film_content_changed (int); + void content_selection_changed (); + +private: + void use_toggled (); + void type_changed (); + void burn_toggled (); + void x_offset_changed (); + void y_offset_changed (); + void x_scale_changed (); + void y_scale_changed (); + void line_spacing_changed (); + void language_changed (); + void stream_changed (); + void caption_view_clicked (); + void fonts_dialog_clicked (); + void reference_clicked (); + void appearance_dialog_clicked (); + + void setup_sensitivity (); + + wxCheckBox* _reference; + wxStaticText* _reference_note; + wxCheckBox* _use; + wxChoice* _type; + wxCheckBox* _burn; + wxSpinCtrl* _x_offset; + wxSpinCtrl* _y_offset; + wxSpinCtrl* _x_scale; + wxSpinCtrl* _y_scale; + wxSpinCtrl* _line_spacing; + wxTextCtrl* _language; + wxChoice* _stream; + wxButton* _caption_view_button; + TextView* _caption_view; + wxButton* _fonts_dialog_button; + FontsDialog* _fonts_dialog; + wxButton* _appearance_dialog_button; + TextType _original_type; +}; diff --git a/src/wx/text_view.cc b/src/wx/text_view.cc new file mode 100644 index 000000000..583632dd0 --- /dev/null +++ b/src/wx/text_view.cc @@ -0,0 +1,139 @@ +/* + Copyright (C) 2014-2018 Carl Hetherington + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see . + +*/ + +#include "lib/string_text_file_decoder.h" +#include "lib/content_text.h" +#include "lib/video_decoder.h" +#include "lib/audio_decoder.h" +#include "lib/film.h" +#include "lib/config.h" +#include "lib/string_text_file_content.h" +#include "lib/text_decoder.h" +#include "text_view.h" +#include "film_viewer.h" +#include "wx_util.h" + +using std::list; +using boost::shared_ptr; +using boost::bind; +using boost::dynamic_pointer_cast; + +TextView::TextView (wxWindow* parent, shared_ptr film, shared_ptr content, shared_ptr caption, shared_ptr decoder, FilmViewer* viewer) + : wxDialog (parent, wxID_ANY, _("Captions"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) + , _content (content) + , _film_viewer (viewer) +{ + _list = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_SINGLE_SEL); + + { + wxListItem ip; + ip.SetId (0); + ip.SetText (_("Start")); + ip.SetWidth (100); + _list->InsertColumn (0, ip); + } + + { + wxListItem ip; + ip.SetId (1); + ip.SetText (_("End")); + ip.SetWidth (100); + _list->InsertColumn (1, ip); + } + + { + wxListItem ip; + ip.SetId (2); + ip.SetText (_("Caption")); + ip.SetWidth (640); + _list->InsertColumn (2, ip); + } + + wxBoxSizer* sizer = new wxBoxSizer (wxVERTICAL); + sizer->Add (_list, 1, wxEXPAND | wxALL, DCPOMATIC_SIZER_X_GAP); + + _list->Bind (wxEVT_LIST_ITEM_SELECTED, boost::bind (&TextView::subtitle_selected, this, _1)); + + wxSizer* buttons = CreateSeparatedButtonSizer (wxOK); + if (buttons) { + sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder()); + } + + if (decoder->video) { + decoder->video->set_ignore (true); + } + if (decoder->audio) { + decoder->audio->set_ignore (true); + } + + _subs = 0; + _frc = film->active_frame_rate_change (content->position()); + + /* Find the decoder that is being used for our TextContent and attach to it */ + BOOST_FOREACH (shared_ptr i, decoder->caption) { + if (i->content() == caption) { + i->PlainStart.connect (bind (&TextView::data_start, this, _1)); + i->Stop.connect (bind (&TextView::data_stop, this, _1)); + } + } + while (!decoder->pass ()) {} + SetSizerAndFit (sizer); +} + +void +TextView::data_start (ContentStringText cts) +{ + BOOST_FOREACH (dcp::SubtitleString const & i, cts.subs) { + wxListItem list_item; + list_item.SetId (_subs); + _list->InsertItem (list_item); + _list->SetItem (_subs, 0, std_to_wx (cts.from().timecode (_frc->source))); + _list->SetItem (_subs, 2, std_to_wx (i.text ())); + _start_times.push_back (cts.from ()); + ++_subs; + } + + _last_count = cts.subs.size (); +} + +void +TextView::data_stop (ContentTime time) +{ + if (!_last_count) { + return; + } + + for (int i = _subs - *_last_count; i < _subs; ++i) { + _list->SetItem (i, 1, std_to_wx (time.timecode (_frc->source))); + } +} + +void +TextView::subtitle_selected (wxListEvent& ev) +{ + if (!Config::instance()->jump_to_selected ()) { + return; + } + + DCPOMATIC_ASSERT (ev.GetIndex() < int(_start_times.size())); + shared_ptr locked = _content.lock (); + DCPOMATIC_ASSERT (locked); + _film_viewer->set_position (locked, _start_times[ev.GetIndex()]); +} diff --git a/src/wx/text_view.h b/src/wx/text_view.h new file mode 100644 index 000000000..8cec8d284 --- /dev/null +++ b/src/wx/text_view.h @@ -0,0 +1,48 @@ +/* + Copyright (C) 2014-2018 Carl Hetherington + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see . + +*/ + +#include "lib/content_text.h" +#include +#include +#include + +class Decoder; +class FilmViewer; + +class TextView : public wxDialog +{ +public: + TextView ( + wxWindow *, boost::shared_ptr, boost::shared_ptr content, boost::shared_ptr caption, boost::shared_ptr, FilmViewer* viewer + ); + +private: + void data_start (ContentStringText cts); + void data_stop (ContentTime time); + void subtitle_selected (wxListEvent &); + + wxListCtrl* _list; + int _subs; + boost::optional _frc; + boost::optional _last_count; + std::vector _start_times; + boost::weak_ptr _content; + FilmViewer* _film_viewer; +}; diff --git a/src/wx/timeline.cc b/src/wx/timeline.cc index f7a31117b..b0a3a7247 100644 --- a/src/wx/timeline.cc +++ b/src/wx/timeline.cc @@ -34,7 +34,7 @@ #include "lib/image_content.h" #include "lib/timer.h" #include "lib/audio_content.h" -#include "lib/caption_content.h" +#include "lib/text_content.h" #include "lib/video_content.h" #include "lib/atmos_mxf_content.h" #include @@ -228,7 +228,7 @@ Timeline::recreate_views () _views.push_back (shared_ptr (new TimelineAudioContentView (*this, i))); } - BOOST_FOREACH (shared_ptr j, i->caption) { + BOOST_FOREACH (shared_ptr j, i->caption) { _views.push_back (shared_ptr (new TimelineTextContentView (*this, i, j))); } diff --git a/src/wx/timeline_text_content_view.cc b/src/wx/timeline_text_content_view.cc index 30158941c..934bf1fc4 100644 --- a/src/wx/timeline_text_content_view.cc +++ b/src/wx/timeline_text_content_view.cc @@ -19,12 +19,12 @@ */ #include "timeline_text_content_view.h" -#include "lib/caption_content.h" +#include "lib/text_content.h" #include "lib/content.h" using boost::shared_ptr; -TimelineTextContentView::TimelineTextContentView (Timeline& tl, shared_ptr c, shared_ptr caption) +TimelineTextContentView::TimelineTextContentView (Timeline& tl, shared_ptr c, shared_ptr caption) : TimelineContentView (tl, c) , _caption (caption) { diff --git a/src/wx/timeline_text_content_view.h b/src/wx/timeline_text_content_view.h index 4f69f2aef..055c84143 100644 --- a/src/wx/timeline_text_content_view.h +++ b/src/wx/timeline_text_content_view.h @@ -21,7 +21,7 @@ #include "timeline_content_view.h" class TextContent; -class CaptionContent; +class TextContent; /** @class TimelineTextContentView * @brief Timeline view for TextContent. @@ -29,12 +29,12 @@ class CaptionContent; class TimelineTextContentView : public TimelineContentView { public: - TimelineTextContentView (Timeline& tl, boost::shared_ptr, boost::shared_ptr); + TimelineTextContentView (Timeline& tl, boost::shared_ptr, boost::shared_ptr); private: bool active () const; wxColour background_colour () const; wxColour foreground_colour () const; - boost::shared_ptr _caption; + boost::shared_ptr _caption; }; diff --git a/src/wx/timing_panel.cc b/src/wx/timing_panel.cc index 9bb608cb2..bf987e51e 100644 --- a/src/wx/timing_panel.cc +++ b/src/wx/timing_panel.cc @@ -26,10 +26,10 @@ #include "move_to_dialog.h" #include "lib/content.h" #include "lib/image_content.h" -#include "lib/caption_content.h" +#include "lib/text_content.h" #include "lib/dcp_subtitle_content.h" #include "lib/audio_content.h" -#include "lib/text_caption_file_content.h" +#include "lib/string_text_file_content.h" #include "lib/video_content.h" #include #include diff --git a/src/wx/wscript b/src/wx/wscript index 5668a7558..0a32d1dfe 100644 --- a/src/wx/wscript +++ b/src/wx/wscript @@ -32,9 +32,9 @@ sources = """ audio_panel.cc audio_plot.cc batch_job_view.cc - caption_appearance_dialog.cc - caption_panel.cc - caption_view.cc + subtitle_appearance_dialog.cc + text_panel.cc + text_view.cc cinema_dialog.cc colour_conversion_editor.cc config_dialog.cc -- cgit v1.2.3