in a piece of content can be overlaid onto the preview (#1233).
--- /dev/null
+/*
+ Copyright (C) 2020 Carl Hetherington <cth@carlh.net>
+
+ 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 <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "analyse_subtitles_job.h"
+#include "playlist.h"
+#include "player.h"
+#include "subtitle_analysis.h"
+#include "bitmap_text.h"
+#include "render_text.h"
+#include "text_content.h"
+#include "image.h"
+#include <iostream>
+
+#include "i18n.h"
+
+using std::string;
+using boost::shared_ptr;
+using boost::weak_ptr;
+
+AnalyseSubtitlesJob::AnalyseSubtitlesJob (shared_ptr<const Film> film, shared_ptr<Content> content)
+ : Job (film)
+ , _content (content)
+ , _path (_film->subtitle_analysis_path(content))
+{
+}
+
+
+string
+AnalyseSubtitlesJob::name () const
+{
+ return _("Analysing subtitles");
+}
+
+
+string
+AnalyseSubtitlesJob::json_name () const
+{
+ return N_("analyse_subtitles");
+}
+
+
+void
+AnalyseSubtitlesJob::run ()
+{
+ shared_ptr<Playlist> playlist (new Playlist());
+ shared_ptr<Content> content = _content.lock ();
+ DCPOMATIC_ASSERT (content);
+ playlist->add (_film, content);
+
+ shared_ptr<Player> player (new Player(_film, playlist));
+ player->set_ignore_audio ();
+ player->set_fast ();
+ player->set_play_referenced ();
+ player->Text.connect (bind(&AnalyseSubtitlesJob::analyse, this, _1, _2));
+
+ set_progress_unknown ();
+
+ if (!content->text.empty()) {
+ while (!player->pass ()) {}
+ }
+
+ SubtitleAnalysis analysis (_bounding_box, content->text.front()->x_offset(), content->text.front()->y_offset());
+ analysis.write (_path);
+
+ set_progress (1);
+ set_state (FINISHED_OK);
+}
+
+
+void
+AnalyseSubtitlesJob::analyse (PlayerText text, TextType type)
+{
+ if (type != TEXT_OPEN_SUBTITLE) {
+ return;
+ }
+
+ BOOST_FOREACH (BitmapText const& i, text.bitmap) {
+ if (!_bounding_box) {
+ _bounding_box = i.rectangle;
+ } else {
+ _bounding_box->extend (i.rectangle);
+ }
+ }
+
+ if (!text.string.empty()) {
+ /* We can provide dummy values for time and frame rate here as they are only used to calculate fades */
+ dcp::Size const frame = _film->frame_size();
+ BOOST_FOREACH (PositionImage i, render_text(text.string, text.fonts, frame, dcpomatic::DCPTime(), 24)) {
+ dcpomatic::Rect<double> rect (
+ double(i.position.x) / frame.width, double(i.position.y) / frame.height,
+ double(i.image->size().width) / frame.width, double(i.image->size().height) / frame.height
+ );
+ if (!_bounding_box) {
+ _bounding_box = rect;
+ } else {
+ _bounding_box->extend (rect);
+ }
+ }
+ }
+}
+
--- /dev/null
+/*
+ Copyright (C) 2020 Carl Hetherington <cth@carlh.net>
+
+ 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 <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "job.h"
+#include "types.h"
+#include "player_text.h"
+
+class Film;
+class Content;
+
+class AnalyseSubtitlesJob : public Job
+{
+public:
+ AnalyseSubtitlesJob (boost::shared_ptr<const Film> film, boost::shared_ptr<Content> content);
+
+ std::string name () const;
+ std::string json_name () const;
+ void run ();
+
+ boost::filesystem::path path () const {
+ return _path;
+ }
+
+private:
+ void analyse (PlayerText text, TextType type);
+
+ boost::weak_ptr<Content> _content;
+ boost::filesystem::path _path;
+ boost::optional<dcpomatic::Rect<double> > _bounding_box;
+};
+
#include "cinema.h"
#include "change_signaller.h"
#include "check_content_change_job.h"
+#include "ffmpeg_subtitle_stream.h"
+#include "font.h"
#include <libcxml/cxml.h>
#include <dcp/cpl.h>
#include <dcp/certificate_chain.h>
return p;
}
+
+boost::filesystem::path
+Film::subtitle_analysis_path (shared_ptr<const Content> content) const
+{
+ boost::filesystem::path p = dir ("analysis");
+
+ Digester digester;
+ digester.add (content->digest());
+
+ if (!content->text.empty()) {
+ shared_ptr<TextContent> tc = content->text.front();
+ digester.add (tc->x_scale());
+ digester.add (tc->y_scale());
+ BOOST_FOREACH (shared_ptr<dcpomatic::Font> i, tc->fonts()) {
+ digester.add (i->id());
+ }
+ if (tc->effect()) {
+ digester.add (tc->effect().get());
+ }
+ digester.add (tc->line_spacing());
+ digester.add (tc->outline_width());
+ }
+
+ shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent>(content);
+ if (fc) {
+ digester.add (fc->subtitle_stream()->identifier());
+ }
+
+ p /= digester.get ();
+ return p;
+}
+
+
/** Add suitable Jobs to the JobManager to create a DCP for this Film.
* @param gui true if this is being called from a GUI tool.
* @param check true to check the content in the project for changes before making the DCP.
boost::filesystem::path internal_video_asset_filename (dcpomatic::DCPTimePeriod p) const;
boost::filesystem::path audio_analysis_path (boost::shared_ptr<const Playlist>) const;
+ boost::filesystem::path subtitle_analysis_path (boost::shared_ptr<const Content>) const;
void send_dcp_to_tms ();
void make_dcp (bool gui = false, bool check = true);
/*
- Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
#include "job.h"
#include "cross.h"
#include "analyse_audio_job.h"
+#include "analyse_subtitles_job.h"
#include "film.h"
#include <boost/thread.hpp>
#include <boost/foreach.hpp>
emit (boost::bind (boost::ref (JobAdded), weak_ptr<Job> (job)));
}
+
+void
+JobManager::analyse_subtitles (
+ shared_ptr<const Film> film,
+ shared_ptr<Content> content,
+ boost::signals2::connection& connection,
+ function<void()> ready
+ )
+{
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+
+ BOOST_FOREACH (shared_ptr<Job> i, _jobs) {
+ shared_ptr<AnalyseSubtitlesJob> a = dynamic_pointer_cast<AnalyseSubtitlesJob> (i);
+ if (a && a->path() == film->subtitle_analysis_path(content)) {
+ i->when_finished (connection, ready);
+ return;
+ }
+ }
+ }
+
+ shared_ptr<AnalyseSubtitlesJob> job;
+
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+
+ job.reset (new AnalyseSubtitlesJob(film, content));
+ connection = job->Finished.connect (ready);
+ _jobs.push_back (job);
+ _empty_condition.notify_all ();
+ }
+
+ emit (boost::bind (boost::ref (JobAdded), weak_ptr<Job> (job)));
+}
+
+
void
JobManager::increase_priority (shared_ptr<Job> job)
{
/*
- Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
class Job;
class Film;
class Playlist;
+class Content;
struct threed_test7;
extern bool wait_for_jobs ();
boost::function<void()> ready
);
+ void analyse_subtitles (
+ boost::shared_ptr<const Film> film,
+ boost::shared_ptr<Content> content,
+ boost::signals2::connection& connection,
+ boost::function<void()> ready
+ );
+
boost::signals2::signal<void (boost::weak_ptr<Job>)> JobAdded;
boost::signals2::signal<void ()> JobsReordered;
boost::signals2::signal<void (boost::optional<std::string>, boost::optional<std::string>)> ActiveJobsChanged;
--- /dev/null
+/*
+ Copyright (C) 2020 Carl Hetherington <cth@carlh.net>
+
+ 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 <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "subtitle_analysis.h"
+#include "exceptions.h"
+#include <libcxml/cxml.h>
+#include <dcp/raw_convert.h>
+#include <libxml++/libxml++.h>
+
+using std::string;
+using dcp::raw_convert;
+using boost::shared_ptr;
+
+int const SubtitleAnalysis::_current_state_version = 1;
+
+
+SubtitleAnalysis::SubtitleAnalysis (boost::filesystem::path path)
+{
+ cxml::Document f ("SubtitleAnalysis");
+
+ f.read_file (path);
+
+ if (f.optional_number_child<int>("Version").get_value_or(1) < _current_state_version) {
+ /* Too old. Throw an exception so that this analysis is re-run. */
+ throw OldFormatError ("Audio analysis file is too old");
+ }
+
+ cxml::NodePtr bounding_box = f.optional_node_child("BoundingBox");
+ if (bounding_box) {
+ _bounding_box = dcpomatic::Rect<double> ();
+ _bounding_box->x = bounding_box->number_child<double>("X");
+ _bounding_box->y = bounding_box->number_child<double>("Y");
+ _bounding_box->width = bounding_box->number_child<double>("Width");
+ _bounding_box->height = bounding_box->number_child<double>("Height");
+ }
+}
+
+
+void
+SubtitleAnalysis::write (boost::filesystem::path path) const
+{
+ shared_ptr<xmlpp::Document> doc (new xmlpp::Document);
+ xmlpp::Element* root = doc->create_root_node ("SubtitleAnalysis");
+
+ root->add_child("Version")->add_child_text (raw_convert<string>(_current_state_version));
+
+ if (_bounding_box) {
+ xmlpp::Element* bounding_box = root->add_child("BoundingBox");
+ bounding_box->add_child("X")->add_child_text(raw_convert<string>(_bounding_box->x));
+ bounding_box->add_child("Y")->add_child_text(raw_convert<string>(_bounding_box->y));
+ bounding_box->add_child("Width")->add_child_text(raw_convert<string>(_bounding_box->width));
+ bounding_box->add_child("Height")->add_child_text(raw_convert<string>(_bounding_box->height));
+ }
+
+ doc->write_to_file_formatted (path.string());
+}
+
+
--- /dev/null
+/*
+ Copyright (C) 2020 Carl Hetherington <cth@carlh.net>
+
+ 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 <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "rect.h"
+#include <boost/noncopyable.hpp>
+#include <boost/filesystem.hpp>
+
+
+/** @class SubtitleAnalysis
+ * @brief Class to store the results of a SubtitleAnalysisJob.
+ */
+
+class SubtitleAnalysis : public boost::noncopyable
+{
+public:
+ explicit SubtitleAnalysis (boost::filesystem::path path);
+
+ SubtitleAnalysis (
+ boost::optional<dcpomatic::Rect<double> > bounding_box,
+ double analysis_x_offset_,
+ double analysis_y_offset_
+ )
+ : _bounding_box (bounding_box)
+ , _analysis_x_offset (analysis_x_offset_)
+ , _analysis_y_offset (analysis_y_offset_)
+ {}
+
+ void write (boost::filesystem::path path) const;
+
+ boost::optional<dcpomatic::Rect<double> > bounding_box () const {
+ return _bounding_box;
+ }
+
+ double analysis_x_offset () const {
+ return _analysis_x_offset;
+ }
+
+ double analysis_y_offset () const {
+ return _analysis_x_offset;
+ }
+
+private:
+ /** Smallest box which surrounds all subtitles in our content,
+ * expressed as a proportion of screen size (i.e. 0 is left hand side/top,
+ * 1 is right hand side/bottom), or empty if no subtitles were found.
+ */
+ boost::optional<dcpomatic::Rect<double> > _bounding_box;
+ double _analysis_x_offset;
+ double _analysis_y_offset;
+
+ static int const _current_state_version;
+};
sources = """
active_text.cc
analyse_audio_job.cc
+ analyse_subtitles_job.cc
analytics.cc
atmos_mxf_content.cc
atomicity_checker.cc
string_text_file.cc
string_text_file_content.cc
string_text_file_decoder.cc
+ subtitle_analysis.cc
subtitle_encoder.cc
text_ring_buffers.cc
timer.cc
_video_view->update ();
}
+
+void
+FilmViewer::set_outline_subtitles (optional<dcpomatic::Rect<double> > rect)
+{
+ _outline_subtitles = rect;
+ _video_view->update ();
+}
+
+
void
FilmViewer::set_eyes (Eyes e)
{
void set_dcp_decode_reduction (boost::optional<int> reduction);
boost::optional<int> dcp_decode_reduction () const;
void set_outline_content (bool o);
+ void set_outline_subtitles (boost::optional<dcpomatic::Rect<double> >);
void set_eyes (Eyes e);
void set_pad_black (bool p);
bool outline_content () const {
return _outline_content;
}
+ boost::optional<dcpomatic::Rect<double> > outline_subtitles () const {
+ return _outline_subtitles;
+ }
bool pad_black () const {
return _pad_black;
}
ClosedCaptionsDialog* _closed_captions_dialog;
bool _outline_content;
+ boost::optional<dcpomatic::Rect<double> > _outline_subtitles;
/** true to pad the viewer panel with black, false to use
the normal window background colour.
*/
dc.SetBrush (*wxTRANSPARENT_BRUSH);
dc.DrawRectangle (_inter_position.x, _inter_position.y + (panel_size.GetHeight() - out_size.height) / 2, _inter_size.width, _inter_size.height);
}
+
+ optional<dcpomatic::Rect<double> > subs = _viewer->outline_subtitles();
+ if (subs) {
+ wxPen p (wxColour(0, 255, 0), 2);
+ dc.SetPen (p);
+ dc.SetBrush (*wxTRANSPARENT_BRUSH);
+ dc.DrawRectangle (subs->x * out_size.width, subs->y * out_size.height, subs->width * out_size.width, subs->height * out_size.height);
+ }
+
_state_timer.unset();
}
/*
- Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
#include "static_text.h"
#include "check_box.h"
#include "dcpomatic_button.h"
+#include "film_viewer.h"
+#include "lib/job_manager.h"
#include "lib/ffmpeg_content.h"
#include "lib/string_text_file_content.h"
#include "lib/ffmpeg_subtitle_stream.h"
#include "lib/dcp_content.h"
#include "lib/text_content.h"
#include "lib/decoder_factory.h"
+#include "lib/analyse_subtitles_job.h"
+#include "lib/subtitle_analysis.h"
#include <wx/spinctrl.h>
#include <boost/foreach.hpp>
using boost::shared_ptr;
using boost::optional;
using boost::dynamic_pointer_cast;
+using boost::bind;
/** @param t Original text type of the content, if known */
TextPanel::TextPanel (ContentPanel* p, TextType t)
: ContentSubPanel (p, std_to_wx(text_type_to_name(t)))
+ , _outline_subtitles (0)
, _dcp_track_label (0)
, _dcp_track (0)
, _language_label (0)
, _text_view (0)
, _fonts_dialog (0)
, _original_type (t)
+ , _loading_analysis (false)
{
wxString refer = _("Use this DCP's subtitle as OV and make VF");
if (t == TEXT_CLOSED_CAPTION) {
_grid->Add (_language, wxGBPosition(_language_row, 1), wxDefaultSpan, wxEXPAND);
film_content_changed (TextContentProperty::LANGUAGE);
}
+ if (!_outline_subtitles) {
+ _outline_subtitles = new CheckBox (this, _("Show subtitle area"));
+ _outline_subtitles->Bind (wxEVT_CHECKBOX, boost::bind (&TextPanel::outline_subtitles_changed, this));
+ _grid->Add (_outline_subtitles, wxGBPosition(_outline_subtitles_row, 0), wxGBSpan(1, 2));
+ }
+
break;
case TEXT_CLOSED_CAPTION:
if (_language_label) {
update_dcp_tracks ();
film_content_changed (TextContentProperty::DCP_TRACK);
}
+ if (_outline_subtitles) {
+ _outline_subtitles->Destroy ();
+ _outline_subtitles = 0;
+ clear_outline_subtitles ();
+ }
break;
default:
break;
_grid->Add (_burn, wxGBPosition (r, 0), wxGBSpan (1, 2));
++r;
+ _outline_subtitles_row = r;
+ ++r;
+
add_label_to_sizer (_grid, _offset_label, true, wxGBPosition (r, 0));
wxBoxSizer* offset = new wxBoxSizer (wxHORIZONTAL);
add_label_to_sizer (offset, _x_offset_label, true);
}
_language_row = r;
- setup_visibility ();
++r;
add_label_to_sizer (_grid, _stream_label, true, wxGBPosition (r, 0));
_grid->Add (s, wxGBPosition (r, 0), wxGBSpan (1, 2));
++r;
}
+
+ setup_visibility ();
}
void
}
}
setup_sensitivity ();
+ clear_outline_subtitles ();
} else if (property == TextContentProperty::USE) {
checked_set (_use, text ? text->use() : false);
setup_sensitivity ();
+ clear_outline_subtitles ();
} else if (property == TextContentProperty::TYPE) {
if (text) {
switch (text->type()) {
checked_set (_burn, text ? text->burn() : false);
} else if (property == TextContentProperty::X_OFFSET) {
checked_set (_x_offset, text ? lrint (text->x_offset() * 100) : 0);
+ update_outline_subtitles_in_viewer ();
} else if (property == TextContentProperty::Y_OFFSET) {
checked_set (_y_offset, text ? lrint (text->y_offset() * 100) : 0);
+ update_outline_subtitles_in_viewer ();
} else if (property == TextContentProperty::X_SCALE) {
checked_set (_x_scale, text ? lrint (text->x_scale() * 100) : 100);
+ clear_outline_subtitles ();
} else if (property == TextContentProperty::Y_SCALE) {
checked_set (_y_scale, text ? lrint (text->y_scale() * 100) : 100);
+ clear_outline_subtitles ();
} else if (property == TextContentProperty::LINE_SPACING) {
checked_set (_line_spacing, text ? lrint (text->line_spacing() * 100) : 100);
+ clear_outline_subtitles ();
} else if (property == TextContentProperty::LANGUAGE) {
if (_language) {
checked_set (_language, text ? text->language() : "");
/* Set up sensitivity */
_use->Enable (!reference && any_subs > 0);
bool const use = _use->GetValue ();
+ if (_outline_subtitles) {
+ _outline_subtitles->Enable (!_loading_analysis && any_subs && use && type == TEXT_OPEN_SUBTITLE);
+ }
_type->Enable (!reference && any_subs > 0 && use);
_burn->Enable (!reference && any_subs > 0 && use && type == TEXT_OPEN_SUBTITLE);
_x_offset->Enable (!reference && any_subs > 0 && use && type == TEXT_OPEN_SUBTITLE);
}
d->Destroy ();
}
+
+
+
+/** The user has clicked on the outline subtitles check box */
+void
+TextPanel::outline_subtitles_changed ()
+{
+ if (_outline_subtitles->GetValue()) {
+ _analysis_content = _parent->selected_text().front();
+ try_to_load_analysis ();
+ } else {
+ clear_outline_subtitles ();
+ }
+}
+
+
+void
+TextPanel::try_to_load_analysis ()
+{
+ _loading_analysis = true;
+ setup_sensitivity ();
+ _analysis.reset ();
+
+ shared_ptr<Content> content = _analysis_content.lock ();
+ if (!content) {
+ _loading_analysis = false;
+ setup_sensitivity ();
+ return;
+ }
+
+ boost::filesystem::path const path = _parent->film()->subtitle_analysis_path(content);
+
+ if (!boost::filesystem::exists(path)) {
+ BOOST_FOREACH (shared_ptr<Job> i, JobManager::instance()->get()) {
+ if (dynamic_pointer_cast<AnalyseSubtitlesJob>(i)) {
+ i->cancel ();
+ }
+ }
+
+ JobManager::instance()->analyse_subtitles (
+ _parent->film(), content, _analysis_finished_connection, bind(&TextPanel::analysis_finished, this)
+ );
+ return;
+ }
+
+ try {
+ _analysis.reset (new SubtitleAnalysis(path));
+ } catch (OldFormatError& e) {
+ /* An old analysis file: recreate it */
+ JobManager::instance()->analyse_subtitles (
+ _parent->film(), content, _analysis_finished_connection, bind(&TextPanel::analysis_finished, this)
+ );
+ return;
+ }
+
+ update_outline_subtitles_in_viewer ();
+ _loading_analysis = false;
+ setup_sensitivity ();
+}
+
+
+void
+TextPanel::update_outline_subtitles_in_viewer ()
+{
+ shared_ptr<FilmViewer> fv = _parent->film_viewer().lock();
+ if (!fv) {
+ return;
+ }
+
+ if (_analysis) {
+ optional<dcpomatic::Rect<double> > rect = _analysis->bounding_box ();
+ if (rect) {
+ shared_ptr<Content> content = _analysis_content.lock ();
+ DCPOMATIC_ASSERT (content);
+ rect->x += content->text.front()->x_offset();
+ rect->y += content->text.front()->y_offset();
+ }
+ fv->set_outline_subtitles (rect);
+ } else {
+ fv->set_outline_subtitles (optional<dcpomatic::Rect<double> >());
+ }
+}
+
+
+/** Remove any current subtitle outline display */
+void
+TextPanel::clear_outline_subtitles ()
+{
+ _analysis.reset ();
+ update_outline_subtitles_in_viewer ();
+ if (_outline_subtitles) {
+ _outline_subtitles->SetValue (false);
+ }
+}
+
+
+void
+TextPanel::analysis_finished ()
+{
+ shared_ptr<Content> content = _analysis_content.lock ();
+ if (!content) {
+ _loading_analysis = false;
+ setup_sensitivity ();
+ return;
+ }
+
+ if (!boost::filesystem::exists(_parent->film()->subtitle_analysis_path(content))) {
+ /* We analysed and still nothing showed up, so maybe it was cancelled or it failed.
+ Give up.
+ */
+ error_dialog (_parent->window(), _("Could not analyse subtitles."));
+ clear_outline_subtitles ();
+ _loading_analysis = false;
+ setup_sensitivity ();
+ return;
+ }
+
+ try_to_load_analysis ();
+}
+
/*
- Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
class wxSpinCtrl;
class TextView;
class FontsDialog;
+class SubtitleAnalysis;
class TextPanel : public ContentSubPanel
{
void fonts_dialog_clicked ();
void reference_clicked ();
void appearance_dialog_clicked ();
+ void outline_subtitles_changed ();
TextType current_type () const;
void update_dcp_tracks ();
void update_dcp_track_selection ();
void add_to_grid ();
+ void try_to_load_analysis ();
+ void analysis_finished ();
void setup_sensitivity ();
void setup_visibility ();
+ void update_outline_subtitles_in_viewer ();
+ void clear_outline_subtitles ();
+
wxCheckBox* _reference;
wxStaticText* _reference_note;
+ wxCheckBox* _outline_subtitles;
wxCheckBox* _use;
wxChoice* _type;
wxCheckBox* _burn;
wxButton* _appearance_dialog_button;
TextType _original_type;
+ int _outline_subtitles_row;
int _language_row;
+
+ boost::weak_ptr<Content> _analysis_content;
+ boost::signals2::scoped_connection _analysis_finished_connection;
+ boost::shared_ptr<SubtitleAnalysis> _analysis;
+ bool _loading_analysis;
};