for (size_t i = 0; i < c.size(); ++i) {
shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (c[i]);
- if (f->with_subtitles() && *(fc->_subtitle_stream.get()) != *(ref->_subtitle_stream.get())) {
+ if (fc->subtitle_use() && *(fc->_subtitle_stream.get()) != *(ref->_subtitle_stream.get())) {
throw JoinError (_("Content to be joined must use the same subtitle stream."));
}
, _container (Config::instance()->default_container ())
, _resolution (RESOLUTION_2K)
, _scaler (Scaler::from_id ("bicubic"))
- , _with_subtitles (false)
, _signed (true)
, _encrypted (false)
, _j2k_bandwidth (Config::instance()->default_j2k_bandwidth ())
s << "_3D";
}
- if (_with_subtitles) {
- s << "_WS";
- }
-
return s.str ();
}
root->add_child("Resolution")->add_child_text (resolution_to_string (_resolution));
root->add_child("Scaler")->add_child_text (_scaler->id ());
- root->add_child("WithSubtitles")->add_child_text (_with_subtitles ? "1" : "0");
root->add_child("J2KBandwidth")->add_child_text (raw_convert<string> (_j2k_bandwidth));
_isdcf_metadata.as_xml (root->add_child ("ISDCFMetadata"));
root->add_child("VideoFrameRate")->add_child_text (raw_convert<string> (_video_frame_rate));
_resolution = string_to_resolution (f.string_child ("Resolution"));
_scaler = Scaler::from_id (f.string_child ("Scaler"));
- _with_subtitles = f.bool_child ("WithSubtitles");
_j2k_bandwidth = f.number_child<int> ("J2KBandwidth");
_video_frame_rate = f.number_child<int> ("VideoFrameRate");
_signed = f.optional_bool_child("Signed").get_value_or (true);
signal_changed (SCALER);
}
-void
-Film::set_with_subtitles (bool w)
-{
- _with_subtitles = w;
- signal_changed (WITH_SUBTITLES);
-}
-
void
Film::set_j2k_bandwidth (int b)
{
return _playlist->length ();
}
-bool
-Film::has_subtitles () const
-{
- return _playlist->has_subtitles ();
-}
-
int
Film::best_video_frame_rate () const
{
ContentList content () const;
DCPTime length () const;
- bool has_subtitles () const;
int best_video_frame_rate () const;
FrameRateChange active_frame_rate_change (DCPTime) const;
CONTAINER,
RESOLUTION,
SCALER,
- WITH_SUBTITLES,
SIGNED,
ENCRYPTED,
J2K_BANDWIDTH,
return _scaler;
}
- bool with_subtitles () const {
- return _with_subtitles;
- }
-
/* signed is a reserved word */
bool is_signed () const {
return _signed;
void set_container (Ratio const *);
void set_resolution (Resolution);
void set_scaler (Scaler const *);
- void set_with_subtitles (bool);
void set_signed (bool);
void set_encrypted (bool);
void set_j2k_bandwidth (int);
Resolution _resolution;
/** Scaler algorithm to use */
Scaler const * _scaler;
- /** True if subtitles should be shown for this film */
- bool _with_subtitles;
bool _signed;
bool _encrypted;
/** bandwidth for J2K files in bits per second */
Changed (frequent);
} else if (
+ property == SubtitleContentProperty::SUBTITLE_USE ||
property == SubtitleContentProperty::SUBTITLE_X_OFFSET ||
property == SubtitleContentProperty::SUBTITLE_Y_OFFSET ||
property == SubtitleContentProperty::SUBTITLE_SCALE ||
last time we were run.
*/
- if (p == Film::SCALER || p == Film::WITH_SUBTITLES || p == Film::CONTAINER || p == Film::VIDEO_FRAME_RATE) {
+ if (p == Film::SCALER || p == Film::CONTAINER || p == Film::VIDEO_FRAME_RATE) {
Changed (false);
}
}
list<PositionImage> sub_images;
for (list<shared_ptr<Piece> >::const_iterator j = subs.begin(); j != subs.end(); ++j) {
- shared_ptr<SubtitleDecoder> subtitle_decoder = dynamic_pointer_cast<SubtitleDecoder> ((*j)->decoder);
shared_ptr<SubtitleContent> subtitle_content = dynamic_pointer_cast<SubtitleContent> ((*j)->content);
+ if (!subtitle_content->subtitle_use ()) {
+ continue;
+ }
+
+ shared_ptr<SubtitleDecoder> subtitle_decoder = dynamic_pointer_cast<SubtitleDecoder> ((*j)->decoder);
ContentTime const from = dcp_to_content_subtitle (*j, time);
/* XXX: this video_frame_rate() should be the rate that the subtitle content has been prepared for */
ContentTime const to = from + ContentTime::from_frames (1, _film->video_frame_rate ());
Changed ();
}
-bool
-Playlist::has_subtitles () const
-{
- for (ContentList::const_iterator i = _content.begin(); i != _content.end(); ++i) {
- shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (*i);
- if (fc && !fc->subtitle_streams().empty()) {
- return true;
- }
-
- shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (*i);
- if (sc) {
- return true;
- }
- }
-
- return false;
-}
-
class FrameRateCandidate
{
public:
void move_earlier (boost::shared_ptr<Content>);
void move_later (boost::shared_ptr<Content>);
- bool has_subtitles () const;
-
ContentList content () const;
std::string video_identifier () const;
int const SubtitleContentProperty::SUBTITLE_X_OFFSET = 500;
int const SubtitleContentProperty::SUBTITLE_Y_OFFSET = 501;
int const SubtitleContentProperty::SUBTITLE_SCALE = 502;
+int const SubtitleContentProperty::SUBTITLE_USE = 503;
SubtitleContent::SubtitleContent (shared_ptr<const Film> f, boost::filesystem::path p)
: Content (f, p)
+ , _subtitle_use (false)
, _subtitle_x_offset (0)
, _subtitle_y_offset (0)
, _subtitle_scale (1)
SubtitleContent::SubtitleContent (shared_ptr<const Film> f, cxml::ConstNodePtr node, int version)
: Content (f, node)
+ , _subtitle_use (false)
, _subtitle_x_offset (0)
, _subtitle_y_offset (0)
, _subtitle_scale (1)
{
if (version >= 7) {
+ _subtitle_use = node->bool_child ("SubtitleUse");
_subtitle_x_offset = node->number_child<float> ("SubtitleXOffset");
_subtitle_y_offset = node->number_child<float> ("SubtitleYOffset");
} else {
for (size_t i = 0; i < c.size(); ++i) {
shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (c[i]);
+ if (sc->subtitle_use() != ref->subtitle_use()) {
+ throw JoinError (_("Content to be joined must have the same 'use subtitles' setting."));
+ }
+
if (sc->subtitle_x_offset() != ref->subtitle_x_offset()) {
throw JoinError (_("Content to be joined must have the same subtitle X offset."));
}
}
}
+ _subtitle_use = ref->subtitle_use ();
_subtitle_x_offset = ref->subtitle_x_offset ();
_subtitle_y_offset = ref->subtitle_y_offset ();
_subtitle_scale = ref->subtitle_scale ();
void
SubtitleContent::as_xml (xmlpp::Node* root) const
{
+ root->add_child("SubtitleUse")->add_child_text (raw_convert<string> (_subtitle_use));
root->add_child("SubtitleXOffset")->add_child_text (raw_convert<string> (_subtitle_x_offset));
root->add_child("SubtitleYOffset")->add_child_text (raw_convert<string> (_subtitle_y_offset));
root->add_child("SubtitleScale")->add_child_text (raw_convert<string> (_subtitle_scale));
}
+void
+SubtitleContent::set_subtitle_use (bool u)
+{
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+ _subtitle_use = u;
+ }
+ signal_changed (SubtitleContentProperty::SUBTITLE_USE);
+}
+
void
SubtitleContent::set_subtitle_x_offset (double o)
{
static int const SUBTITLE_X_OFFSET;
static int const SUBTITLE_Y_OFFSET;
static int const SUBTITLE_SCALE;
+ static int const SUBTITLE_USE;
};
class SubtitleContent : public virtual Content
void as_xml (xmlpp::Node *) const;
+ void set_subtitle_use (bool);
void set_subtitle_x_offset (double);
void set_subtitle_y_offset (double);
void set_subtitle_scale (double);
+ bool subtitle_use () const {
+ boost::mutex::scoped_lock lm (_mutex);
+ return _subtitle_use;
+ }
+
double subtitle_x_offset () const {
boost::mutex::scoped_lock lm (_mutex);
return _subtitle_x_offset;
private:
friend class ffmpeg_pts_offset_test;
+ bool _subtitle_use;
/** x offset for placing subtitles, as a proportion of the container width;
* +ve is further right, -ve is further left.
*/
checked_set (_name, _film->name());
setup_dcp_name ();
break;
- case Film::WITH_SUBTITLES:
- setup_dcp_name ();
- break;
case Film::DCP_CONTENT_TYPE:
checked_set (_dcp_content_type, DCPContentType::as_index (_film->dcp_content_type ()));
setup_dcp_name ();
(*i)->film_content_changed (property);
}
- if (property == FFmpegContentProperty::AUDIO_STREAM) {
+ if (property == FFmpegContentProperty::AUDIO_STREAM || property == SubtitleContentProperty::SUBTITLE_USE) {
setup_dcp_name ();
} else if (property == ContentProperty::PATH) {
setup_content ();
film_changed (Film::CONTAINER);
film_changed (Film::RESOLUTION);
film_changed (Film::SCALER);
- film_changed (Film::WITH_SUBTITLES);
film_changed (Film::SIGNED);
film_changed (Film::ENCRYPTED);
film_changed (Film::J2K_BANDWIDTH);
wxFlexGridSizer* grid = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
_sizer->Add (grid, 0, wxALL, 8);
- _with_subtitles = new wxCheckBox (this, wxID_ANY, _("With Subtitles"));
- grid->Add (_with_subtitles, 1);
+ _use = new wxCheckBox (this, wxID_ANY, _("Use subtitles"));
+ grid->Add (_use);
grid->AddSpacer (0);
-
+
{
- add_label_to_sizer (grid, this, _("Subtitle X Offset"), true);
+ add_label_to_sizer (grid, this, _("X Offset"), true);
wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
_x_offset = new wxSpinCtrl (this);
s->Add (_x_offset);
}
{
- add_label_to_sizer (grid, this, _("Subtitle Y Offset"), true);
+ add_label_to_sizer (grid, this, _("Y Offset"), true);
wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
_y_offset = new wxSpinCtrl (this);
s->Add (_y_offset);
}
{
- add_label_to_sizer (grid, this, _("Subtitle Scale"), true);
+ add_label_to_sizer (grid, this, _("Scale"), true);
wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
_scale = new wxSpinCtrl (this);
s->Add (_scale);
grid->Add (s);
}
- add_label_to_sizer (grid, this, _("Subtitle Stream"), true);
+ add_label_to_sizer (grid, this, _("Stream"), true);
_stream = new wxChoice (this, wxID_ANY);
grid->Add (_stream, 1, wxEXPAND);
_scale->SetRange (1, 1000);
_scale->SetValue (100);
- _with_subtitles->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&SubtitlePanel::with_subtitles_toggled, this));
- _x_offset->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&SubtitlePanel::x_offset_changed, this));
- _y_offset->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&SubtitlePanel::y_offset_changed, this));
- _scale->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&SubtitlePanel::scale_changed, this));
- _stream->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&SubtitlePanel::stream_changed, this));
- _view_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&SubtitlePanel::view_clicked, this));
+ _use->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&SubtitlePanel::use_toggled, this));
+ _x_offset->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&SubtitlePanel::x_offset_changed, this));
+ _y_offset->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&SubtitlePanel::y_offset_changed, this));
+ _scale->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&SubtitlePanel::scale_changed, this));
+ _stream->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&SubtitlePanel::stream_changed, this));
+ _view_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&SubtitlePanel::view_clicked, this));
}
void
SubtitlePanel::film_changed (Film::Property property)
{
- switch (property) {
- case Film::CONTENT:
+ if (property == Film::CONTENT) {
setup_sensitivity ();
- break;
- case Film::WITH_SUBTITLES:
- checked_set (_with_subtitles, _editor->film()->with_subtitles ());
- setup_sensitivity ();
- break;
- default:
- break;
}
}
if (sc.size() == 1) {
scs = sc.front ();
}
-
+
if (property == FFmpegContentProperty::SUBTITLE_STREAMS) {
_stream->Clear ();
if (fcs) {
}
}
setup_sensitivity ();
+ } else if (property == SubtitleContentProperty::SUBTITLE_USE) {
+ checked_set (_use, scs ? scs->subtitle_use() : false);
+ setup_sensitivity ();
} else if (property == SubtitleContentProperty::SUBTITLE_X_OFFSET) {
checked_set (_x_offset, scs ? (scs->subtitle_x_offset() * 100) : 0);
} else if (property == SubtitleContentProperty::SUBTITLE_Y_OFFSET) {
}
void
-SubtitlePanel::with_subtitles_toggled ()
+SubtitlePanel::use_toggled ()
{
- if (!_editor->film()) {
- return;
+ SubtitleContentList c = _editor->selected_subtitle_content ();
+ for (SubtitleContentList::iterator i = c.begin(); i != c.end(); ++i) {
+ (*i)->set_subtitle_use (_use->GetValue());
}
-
- _editor->film()->set_with_subtitles (_with_subtitles->GetValue ());
}
void
SubtitlePanel::setup_sensitivity ()
{
- bool h = false;
- bool j = false;
- if (_editor->film()) {
- h = _editor->film()->has_subtitles ();
- j = _editor->film()->with_subtitles ();
+ int any_subs = 0;
+ int ffmpeg_subs = 0;
+ SubtitleContentList c = _editor->selected_subtitle_content ();
+ for (SubtitleContentList::const_iterator i = c.begin(); i != c.end(); ++i) {
+ shared_ptr<const FFmpegContent> fc = boost::dynamic_pointer_cast<const FFmpegContent> (*i);
+ if (fc) {
+ if (!fc->subtitle_streams().empty ()) {
+ ++ffmpeg_subs;
+ ++any_subs;
+ }
+ } else {
+ ++any_subs;
+ }
}
+
+ _use->Enable (any_subs > 0);
+ bool const use = _use->GetValue ();
- _with_subtitles->Enable (h);
- _x_offset->Enable (j);
- _y_offset->Enable (j);
- _scale->Enable (j);
- _stream->Enable (j);
-
- SubtitleContentList c = _editor->selected_subtitle_content ();
- _view_button->Enable (c.size() == 1);
+ _x_offset->Enable (any_subs > 0 && use);
+ _y_offset->Enable (any_subs > 0 && use);
+ _scale->Enable (any_subs > 0 && use);
+ _stream->Enable (ffmpeg_subs == 1);
+ _view_button->Enable (any_subs == 1);
}
void
SubtitlePanel::x_offset_changed ()
{
SubtitleContentList c = _editor->selected_subtitle_content ();
- if (c.size() == 1) {
- c.front()->set_subtitle_x_offset (_x_offset->GetValue() / 100.0);
+ for (SubtitleContentList::iterator i = c.begin(); i != c.end(); ++i) {
+ (*i)->set_subtitle_x_offset (_x_offset->GetValue() / 100.0);
}
}
SubtitlePanel::y_offset_changed ()
{
SubtitleContentList c = _editor->selected_subtitle_content ();
- if (c.size() == 1) {
- c.front()->set_subtitle_y_offset (_y_offset->GetValue() / 100.0);
+ for (SubtitleContentList::iterator i = c.begin(); i != c.end(); ++i) {
+ (*i)->set_subtitle_y_offset (_y_offset->GetValue() / 100.0);
}
}
SubtitlePanel::scale_changed ()
{
SubtitleContentList c = _editor->selected_subtitle_content ();
- if (c.size() == 1) {
- c.front()->set_subtitle_scale (_scale->GetValue() / 100.0);
+ for (SubtitleContentList::iterator i = c.begin(); i != c.end(); ++i) {
+ (*i)->set_subtitle_scale (_scale->GetValue() / 100.0);
}
}
SubtitlePanel::content_selection_changed ()
{
film_content_changed (FFmpegContentProperty::SUBTITLE_STREAMS);
+ film_content_changed (SubtitleContentProperty::SUBTITLE_USE);
film_content_changed (SubtitleContentProperty::SUBTITLE_X_OFFSET);
film_content_changed (SubtitleContentProperty::SUBTITLE_Y_OFFSET);
film_content_changed (SubtitleContentProperty::SUBTITLE_SCALE);
void content_selection_changed ();
private:
- void with_subtitles_toggled ();
+ void use_toggled ();
void x_offset_changed ();
void y_offset_changed ();
void scale_changed ();
void setup_sensitivity ();
- wxCheckBox* _with_subtitles;
+ wxCheckBox* _use;
wxSpinCtrl* _x_offset;
wxSpinCtrl* _y_offset;
wxSpinCtrl* _scale;
wxBoxSizer* sizer = new wxBoxSizer (wxVERTICAL);
sizer->Add (_list, 1, wxEXPAND);
- wxSizer* buttons = CreateSeparatedButtonSizer (wxOK | wxCANCEL);
+ wxSizer* buttons = CreateSeparatedButtonSizer (wxOK);
if (buttons) {
sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
}
film->set_container (Ratio::from_id ("185"));
film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TLR"));
film->set_name ("frobozz");
- film->set_with_subtitles (true);
shared_ptr<SubRipContent> content (new SubRipContent (film, "test/data/subrip2.srt"));
+ content->set_subtitle_use (true);
film->examine_and_add_content (content);
wait_for_jobs ();
film->make_dcp ();