summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2016-04-14 01:01:28 +0100
committerCarl Hetherington <cth@carlh.net>2016-05-18 11:50:29 +0100
commit65b331d32c383f3a9049f29bf03ab3fe3193b31a (patch)
tree3b27e0ca60742021094cee889a1c8d1ef4d75f8c /src
parent6dd3777a0074f6f97c7f7286621006a1c14376e8 (diff)
Split audio; builds.
Diffstat (limited to 'src')
-rw-r--r--src/lib/analyse_audio_job.cc4
-rw-r--r--src/lib/audio_analysis.cc5
-rw-r--r--src/lib/audio_content.cc129
-rw-r--r--src/lib/audio_content.h29
-rw-r--r--src/lib/audio_decoder.cc8
-rw-r--r--src/lib/audio_decoder.h5
-rw-r--r--src/lib/audio_decoder_stream.cc9
-rw-r--r--src/lib/audio_decoder_stream.h4
-rw-r--r--src/lib/audio_stream.h1
-rw-r--r--src/lib/content.cc1
-rw-r--r--src/lib/content.h3
-rw-r--r--src/lib/dcp_content.cc56
-rw-r--r--src/lib/dcp_content.h19
-rw-r--r--src/lib/dcp_decoder.cc9
-rw-r--r--src/lib/dcp_subtitle_content.cc32
-rw-r--r--src/lib/dcp_subtitle_content.h5
-rw-r--r--src/lib/ffmpeg_content.cc45
-rw-r--r--src/lib/ffmpeg_content.h14
-rw-r--r--src/lib/ffmpeg_decoder.cc2
-rw-r--r--src/lib/film.cc31
-rw-r--r--src/lib/player.cc30
-rw-r--r--src/lib/playlist.cc12
-rw-r--r--src/lib/sndfile_content.cc39
-rw-r--r--src/lib/sndfile_content.h12
-rw-r--r--src/lib/sndfile_decoder.cc15
-rw-r--r--src/lib/sndfile_decoder.h4
-rw-r--r--src/lib/subtitle_content.cc45
-rw-r--r--src/lib/subtitle_content.h5
-rw-r--r--src/lib/text_subtitle_content.cc29
-rw-r--r--src/lib/text_subtitle_content.h5
-rw-r--r--src/lib/transcoder.cc5
-rw-r--r--src/lib/types.h3
-rw-r--r--src/lib/video_content.cc23
-rw-r--r--src/tools/dcpomatic_cli.cc30
-rw-r--r--src/wx/audio_dialog.cc2
-rw-r--r--src/wx/audio_dialog.h2
-rw-r--r--src/wx/audio_panel.cc27
-rw-r--r--src/wx/content_menu.cc7
-rw-r--r--src/wx/content_panel.cc13
-rw-r--r--src/wx/content_panel.h2
-rw-r--r--src/wx/content_widget.h34
-rw-r--r--src/wx/dcp_panel.cc1
-rw-r--r--src/wx/hints_dialog.cc17
-rw-r--r--src/wx/timeline.cc3
-rw-r--r--src/wx/timing_panel.cc12
-rw-r--r--src/wx/video_panel.cc6
46 files changed, 380 insertions, 414 deletions
diff --git a/src/lib/analyse_audio_job.cc b/src/lib/analyse_audio_job.cc
index 7a1a993e7..9a24a9188 100644
--- a/src/lib/analyse_audio_job.cc
+++ b/src/lib/analyse_audio_job.cc
@@ -106,7 +106,7 @@ AnalyseAudioJob::run ()
bool has_any_audio = false;
BOOST_FOREACH (shared_ptr<Content> c, _playlist->content ()) {
- if (dynamic_pointer_cast<AudioContent> (c)) {
+ if (c->audio) {
has_any_audio = true;
}
}
@@ -145,7 +145,7 @@ AnalyseAudioJob::run ()
/* If there was only one piece of content in this analysis we may later need to know what its
gain was when we analysed it.
*/
- shared_ptr<const AudioContent> ac = dynamic_pointer_cast<const AudioContent> (_playlist->content().front ());
+ shared_ptr<const AudioContent> ac = _playlist->content().front()->audio;
DCPOMATIC_ASSERT (ac);
_analysis->set_analysis_gain (ac->audio_gain ());
}
diff --git a/src/lib/audio_analysis.cc b/src/lib/audio_analysis.cc
index 03f35d84e..d99b01ce6 100644
--- a/src/lib/audio_analysis.cc
+++ b/src/lib/audio_analysis.cc
@@ -153,9 +153,8 @@ AudioAnalysis::gain_correction (shared_ptr<const Playlist> playlist)
we know that content's gain when the analysis was run. Hence we can work out
what correction is now needed to make it look `right'.
*/
- shared_ptr<const AudioContent> ac = dynamic_pointer_cast<const AudioContent> (playlist->content().front ());
- DCPOMATIC_ASSERT (ac);
- return ac->audio_gain() - analysis_gain().get ();
+ DCPOMATIC_ASSERT (playlist->content().front()->audio);
+ return playlist->content().front()->audio->audio_gain() - analysis_gain().get ();
}
return 0.0f;
diff --git a/src/lib/audio_content.cc b/src/lib/audio_content.cc
index bd4bb565f..2832e2575 100644
--- a/src/lib/audio_content.cc
+++ b/src/lib/audio_content.cc
@@ -49,52 +49,34 @@ int const AudioContentProperty::AUDIO_GAIN = 201;
int const AudioContentProperty::AUDIO_DELAY = 202;
int const AudioContentProperty::AUDIO_VIDEO_FRAME_RATE = 203;
-AudioContent::AudioContent (shared_ptr<const Film> film)
- : Content (film)
+AudioContent::AudioContent (Content* parent, shared_ptr<const Film> film)
+ : ContentPart (parent, film)
, _audio_gain (0)
, _audio_delay (Config::instance()->default_audio_delay ())
{
}
-AudioContent::AudioContent (shared_ptr<const Film> film, DCPTime s)
- : Content (film, s)
- , _audio_gain (0)
- , _audio_delay (Config::instance()->default_audio_delay ())
-{
-
-}
-
-AudioContent::AudioContent (shared_ptr<const Film> film, boost::filesystem::path p)
- : Content (film, p)
- , _audio_gain (0)
- , _audio_delay (Config::instance()->default_audio_delay ())
-{
-
-}
-
-AudioContent::AudioContent (shared_ptr<const Film> film, cxml::ConstNodePtr node)
- : Content (film, node)
+AudioContent::AudioContent (Content* parent, shared_ptr<const Film> film, cxml::ConstNodePtr node)
+ : ContentPart (parent, film)
{
_audio_gain = node->number_child<double> ("AudioGain");
_audio_delay = node->number_child<int> ("AudioDelay");
_audio_video_frame_rate = node->optional_number_child<double> ("AudioVideoFrameRate");
}
-AudioContent::AudioContent (shared_ptr<const Film> film, vector<shared_ptr<Content> > c)
- : Content (film, c)
+AudioContent::AudioContent (Content* parent, shared_ptr<const Film> film, vector<shared_ptr<Content> > c)
+ : ContentPart (parent, film)
{
- shared_ptr<AudioContent> ref = dynamic_pointer_cast<AudioContent> (c[0]);
+ shared_ptr<AudioContent> ref = c[0]->audio;
DCPOMATIC_ASSERT (ref);
- for (size_t i = 0; i < c.size(); ++i) {
- shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> (c[i]);
-
- if (ac->audio_gain() != ref->audio_gain()) {
+ for (size_t i = 1; i < c.size(); ++i) {
+ if (c[i]->audio->audio_gain() != ref->audio_gain()) {
throw JoinError (_("Content to be joined must have the same audio gain."));
}
- if (ac->audio_delay() != ref->audio_delay()) {
+ if (c[i]->audio->audio_delay() != ref->audio_delay()) {
throw JoinError (_("Content to be joined must have the same audio delay."));
}
@@ -107,6 +89,7 @@ AudioContent::AudioContent (shared_ptr<const Film> film, vector<shared_ptr<Conte
_audio_delay = ref->audio_delay ();
/* Preserve the optional<> part of this */
_audio_video_frame_rate = ref->_audio_video_frame_rate;
+ _streams = ref->streams ();
}
void
@@ -120,34 +103,23 @@ AudioContent::as_xml (xmlpp::Node* node) const
}
}
-
void
AudioContent::set_audio_gain (double g)
{
- {
- boost::mutex::scoped_lock lm (_mutex);
- _audio_gain = g;
- }
-
- signal_changed (AudioContentProperty::AUDIO_GAIN);
+ maybe_set (_audio_gain, g, AudioContentProperty::AUDIO_GAIN);
}
void
AudioContent::set_audio_delay (int d)
{
- {
- boost::mutex::scoped_lock lm (_mutex);
- _audio_delay = d;
- }
-
- signal_changed (AudioContentProperty::AUDIO_DELAY);
+ maybe_set (_audio_delay, d, AudioContentProperty::AUDIO_DELAY);
}
string
AudioContent::technical_summary () const
{
string s = "audio :";
- BOOST_FOREACH (AudioStreamPtr i, audio_streams ()) {
+ BOOST_FOREACH (AudioStreamPtr i, streams ()) {
s += String::compose ("stream channels %1 rate %2", i->channels(), i->frame_rate());
}
@@ -158,7 +130,7 @@ void
AudioContent::set_audio_mapping (AudioMapping mapping)
{
int c = 0;
- BOOST_FOREACH (AudioStreamPtr i, audio_streams ()) {
+ BOOST_FOREACH (AudioStreamPtr i, streams ()) {
AudioMapping stream_mapping (i->channels (), MAX_DCP_AUDIO_CHANNELS);
for (int j = 0; j < i->channels(); ++j) {
for (int k = 0; k < MAX_DCP_AUDIO_CHANNELS; ++k) {
@@ -169,14 +141,14 @@ AudioContent::set_audio_mapping (AudioMapping mapping)
i->set_mapping (stream_mapping);
}
- signal_changed (AudioContentProperty::AUDIO_STREAMS);
+ _parent->signal_changed (AudioContentProperty::AUDIO_STREAMS);
}
AudioMapping
AudioContent::audio_mapping () const
{
int channels = 0;
- BOOST_FOREACH (AudioStreamPtr i, audio_streams ()) {
+ BOOST_FOREACH (AudioStreamPtr i, streams ()) {
channels += i->channels ();
}
@@ -185,7 +157,7 @@ AudioContent::audio_mapping () const
int c = 0;
int s = 0;
- BOOST_FOREACH (AudioStreamPtr i, audio_streams ()) {
+ BOOST_FOREACH (AudioStreamPtr i, streams ()) {
AudioMapping mapping = i->mapping ();
for (int j = 0; j < mapping.input_channels(); ++j) {
for (int k = 0; k < MAX_DCP_AUDIO_CHANNELS; ++k) {
@@ -210,7 +182,9 @@ AudioContent::resampled_audio_frame_rate () const
/* Resample to a DCI-approved sample rate */
double t = has_rate_above_48k() ? 96000 : 48000;
- FrameRateChange frc (audio_video_frame_rate(), film()->video_frame_rate());
+ shared_ptr<const Film> film = _film.lock ();
+ DCPOMATIC_ASSERT (film);
+ FrameRateChange frc (audio_video_frame_rate(), film->video_frame_rate());
/* Compensate if the DCP is being run at a different frame rate
to the source; that is, if the video is run such that it will
@@ -227,8 +201,7 @@ AudioContent::resampled_audio_frame_rate () const
string
AudioContent::processing_description () const
{
- vector<AudioStreamPtr> streams = audio_streams ();
- if (streams.empty ()) {
+ if (streams().empty ()) {
return "";
}
@@ -244,7 +217,7 @@ AudioContent::processing_description () const
bool same = true;
optional<int> common_frame_rate;
- BOOST_FOREACH (AudioStreamPtr i, streams) {
+ BOOST_FOREACH (AudioStreamPtr i, streams()) {
if (i->frame_rate() != resampled_audio_frame_rate()) {
resampled = true;
} else {
@@ -280,7 +253,7 @@ AudioContent::processing_description () const
bool
AudioContent::has_rate_above_48k () const
{
- BOOST_FOREACH (AudioStreamPtr i, audio_streams ()) {
+ BOOST_FOREACH (AudioStreamPtr i, streams ()) {
if (i->frame_rate() > 48000) {
return true;
}
@@ -296,7 +269,7 @@ AudioContent::audio_channel_names () const
vector<string> n;
int t = 1;
- BOOST_FOREACH (AudioStreamPtr i, audio_streams ()) {
+ BOOST_FOREACH (AudioStreamPtr i, streams ()) {
for (int j = 0; j < i->channels(); ++j) {
n.push_back (String::compose ("%1:%2", t, j + 1));
}
@@ -310,8 +283,8 @@ void
AudioContent::add_properties (list<UserProperty>& p) const
{
shared_ptr<const AudioStream> stream;
- if (audio_streams().size() == 1) {
- stream = audio_streams().front ();
+ if (streams().size() == 1) {
+ stream = streams().front ();
}
if (stream) {
@@ -319,8 +292,11 @@ AudioContent::add_properties (list<UserProperty>& p) const
p.push_back (UserProperty (_("Audio"), _("Content audio frame rate"), stream->frame_rate(), _("Hz")));
}
- FrameRateChange const frc (audio_video_frame_rate(), film()->video_frame_rate());
- ContentTime const c (full_length(), frc);
+ shared_ptr<const Film> film = _film.lock ();
+ DCPOMATIC_ASSERT (film);
+
+ FrameRateChange const frc (audio_video_frame_rate(), film->video_frame_rate());
+ ContentTime const c (_parent->full_length(), frc);
p.push_back (
UserProperty (_("Length"), _("Full length in video frames at content rate"), c.frames_round(frc.source))
@@ -376,3 +352,44 @@ AudioContent::audio_video_frame_rate () const
*/
return film()->active_frame_rate_change(position()).source;
}
+
+AudioContent::set_streams (vector<AudioStreamPtr> streams)
+{
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+ _streams = streams;
+ }
+
+ _parent->signal_changed (AudioContentProperty::AUDIO_STREAMS);
+}
+
+AudioStreamPtr
+AudioContent::stream () const
+{
+ boost::mutex::scoped_lock lm (_mutex);
+ DCPOMATIC_ASSERT (_streams.size() == 1);
+ return _streams.front ();
+}
+
+void
+AudioContent::add_stream (AudioStreamPtr stream)
+{
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+ _streams.push_back (stream);
+ }
+
+ _parent->signal_changed (AudioContentProperty::AUDIO_STREAMS);
+}
+
+void
+AudioContent::set_stream (AudioStreamPtr stream)
+{
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+ _streams.clear ();
+ _streams.push_back (stream);
+ }
+
+ _parent->signal_changed (AudioContentProperty::AUDIO_STREAMS);
+}
diff --git a/src/lib/audio_content.h b/src/lib/audio_content.h
index ac91da595..3aa9678b0 100644
--- a/src/lib/audio_content.h
+++ b/src/lib/audio_content.h
@@ -24,7 +24,7 @@
#ifndef DCPOMATIC_AUDIO_CONTENT_H
#define DCPOMATIC_AUDIO_CONTENT_H
-#include "content.h"
+#include "content_part.h"
#include "audio_stream.h"
#include "audio_mapping.h"
@@ -40,23 +40,16 @@ public:
static int const AUDIO_VIDEO_FRAME_RATE;
};
-/** @class AudioContent
- * @brief Parent class for content which may contain audio data.
- */
-class AudioContent : public virtual Content
+class AudioContent : public ContentPart
{
public:
- AudioContent (boost::shared_ptr<const Film>);
- AudioContent (boost::shared_ptr<const Film>, DCPTime);
- AudioContent (boost::shared_ptr<const Film>, boost::filesystem::path);
- AudioContent (boost::shared_ptr<const Film>, cxml::ConstNodePtr);
- AudioContent (boost::shared_ptr<const Film>, std::vector<boost::shared_ptr<Content> >);
+ AudioContent (Content* parent, boost::shared_ptr<const Film>);
+ AudioContent (Content* parent, boost::shared_ptr<const Film>, cxml::ConstNodePtr);
+ AudioContent (Content* parent, boost::shared_ptr<const Film>, std::vector<boost::shared_ptr<Content> >);
void as_xml (xmlpp::Node *) const;
std::string technical_summary () const;
- virtual std::vector<AudioStreamPtr> audio_streams () const = 0;
-
AudioMapping audio_mapping () const;
void set_audio_mapping (AudioMapping);
int resampled_audio_frame_rate () const;
@@ -81,16 +74,26 @@ public:
std::string processing_description () const;
-protected:
+ std::vector<AudioStreamPtr> streams () const {
+ boost::mutex::scoped_lock lm (_mutex);
+ return _streams;
+ }
+
+ void add_stream (AudioStreamPtr stream);
+ void set_stream (AudioStreamPtr stream);
+ void set_streams (std::vector<AudioStreamPtr> streams);
+ AudioStreamPtr stream () const;
void add_properties (std::list<UserProperty> &) const;
private:
+
/** Gain to apply to audio in dB */
double _audio_gain;
/** Delay to apply to audio (positive moves audio later) in milliseconds */
int _audio_delay;
boost::optional<double> _audio_video_frame_rate;
+ std::vector<AudioStreamPtr> _streams;
};
#endif
diff --git a/src/lib/audio_decoder.cc b/src/lib/audio_decoder.cc
index 2944357ba..705fdbef1 100644
--- a/src/lib/audio_decoder.cc
+++ b/src/lib/audio_decoder.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -30,13 +30,13 @@ using std::cout;
using std::map;
using boost::shared_ptr;
-AudioDecoder::AudioDecoder (shared_ptr<const AudioContent> content, bool fast)
+AudioDecoder::AudioDecoder (shared_ptr<const AudioContent> content, bool fast, shared_ptr<Log> log)
: _audio_content (content)
, _ignore_audio (false)
, _fast (fast)
{
- BOOST_FOREACH (AudioStreamPtr i, content->audio_streams ()) {
- _streams[i] = shared_ptr<AudioDecoderStream> (new AudioDecoderStream (_audio_content, i, this));
+ BOOST_FOREACH (AudioStreamPtr i, content->streams ()) {
+ _streams[i] = shared_ptr<AudioDecoderStream> (new AudioDecoderStream (_audio_content, i, this, log));
}
}
diff --git a/src/lib/audio_decoder.h b/src/lib/audio_decoder.h
index 716b37969..679cdd5c5 100644
--- a/src/lib/audio_decoder.h
+++ b/src/lib/audio_decoder.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -32,6 +32,7 @@
class AudioBuffers;
class AudioContent;
class AudioDecoderStream;
+class Log;
/** @class AudioDecoder.
* @brief Parent class for audio decoders.
@@ -39,7 +40,7 @@ class AudioDecoderStream;
class AudioDecoder : public virtual Decoder, public boost::enable_shared_from_this<AudioDecoder>
{
public:
- AudioDecoder (boost::shared_ptr<const AudioContent>, bool fast);
+ AudioDecoder (boost::shared_ptr<const AudioContent>, bool fast, boost::shared_ptr<Log> log);
boost::shared_ptr<const AudioContent> audio_content () const {
return _audio_content;
diff --git a/src/lib/audio_decoder_stream.cc b/src/lib/audio_decoder_stream.cc
index cb0372231..7037d9f47 100644
--- a/src/lib/audio_decoder_stream.cc
+++ b/src/lib/audio_decoder_stream.cc
@@ -39,10 +39,11 @@ using std::max;
using boost::optional;
using boost::shared_ptr;
-AudioDecoderStream::AudioDecoderStream (shared_ptr<const AudioContent> content, AudioStreamPtr stream, AudioDecoder* decoder)
+AudioDecoderStream::AudioDecoderStream (shared_ptr<const AudioContent> content, AudioStreamPtr stream, AudioDecoder* decoder, shared_ptr<Log> log)
: _content (content)
, _stream (stream)
, _decoder (decoder)
+ , _log (log)
{
if (content->resampled_audio_frame_rate() != _stream->frame_rate() && _stream->channels() > 0) {
_resampler.reset (new Resampler (_stream->frame_rate(), content->resampled_audio_frame_rate(), _stream->channels (), decoder->fast ()));
@@ -62,7 +63,7 @@ AudioDecoderStream::get (Frame frame, Frame length, bool accurate)
{
shared_ptr<ContentAudio> dec;
- _content->film()->log()->log (String::compose ("-> ADS has request for %1 %2", frame, length), LogEntry::TYPE_DEBUG_DECODE);
+ _log->log (String::compose ("-> ADS has request for %1 %2", frame, length), LogEntry::TYPE_DEBUG_DECODE);
Frame const end = frame + length - 1;
@@ -93,7 +94,7 @@ AudioDecoderStream::get (Frame frame, Frame length, bool accurate)
decoded_offset = frame - _decoded.frame;
- _content->film()->log()->log (
+ _log->log (
String::compose ("Accurate ADS::get has offset %1 from request %2 and available %3", decoded_offset, frame, _decoded.frame),
LogEntry::TYPE_DEBUG_DECODE
);
@@ -141,7 +142,7 @@ AudioDecoderStream::get (Frame frame, Frame length, bool accurate)
void
AudioDecoderStream::audio (shared_ptr<const AudioBuffers> data, ContentTime time)
{
- _content->film()->log()->log (String::compose ("ADS receives %1 %2", time, data->frames ()), LogEntry::TYPE_DEBUG_DECODE);
+ _log->log (String::compose ("ADS receives %1 %2", time, data->frames ()), LogEntry::TYPE_DEBUG_DECODE);
if (_resampler) {
data = _resampler->run (data);
diff --git a/src/lib/audio_decoder_stream.h b/src/lib/audio_decoder_stream.h
index 3503a46d1..90269a0f4 100644
--- a/src/lib/audio_decoder_stream.h
+++ b/src/lib/audio_decoder_stream.h
@@ -28,11 +28,12 @@
class AudioContent;
class AudioDecoder;
class Resampler;
+class Log;
class AudioDecoderStream
{
public:
- AudioDecoderStream (boost::shared_ptr<const AudioContent>, AudioStreamPtr, AudioDecoder* decoder);
+ AudioDecoderStream (boost::shared_ptr<const AudioContent>, AudioStreamPtr, AudioDecoder* decoder, boost::shared_ptr<Log> log);
ContentAudio get (Frame time, Frame length, bool accurate);
void audio (boost::shared_ptr<const AudioBuffers>, ContentTime);
@@ -47,6 +48,7 @@ private:
boost::shared_ptr<const AudioContent> _content;
AudioStreamPtr _stream;
AudioDecoder* _decoder;
+ boost::shared_ptr<Log> _log;
boost::shared_ptr<Resampler> _resampler;
boost::optional<Frame> _position;
/** Currently-available decoded audio data */
diff --git a/src/lib/audio_stream.h b/src/lib/audio_stream.h
index 506a3c02d..8d05df268 100644
--- a/src/lib/audio_stream.h
+++ b/src/lib/audio_stream.h
@@ -30,6 +30,7 @@ class AudioStream
public:
AudioStream (int frame_rate, int channels);
AudioStream (int frame_rate, AudioMapping mapping);
+ virtual ~AudioStream () {}
void set_mapping (AudioMapping mapping);
diff --git a/src/lib/content.cc b/src/lib/content.cc
index 28103e9c0..499f90dd1 100644
--- a/src/lib/content.cc
+++ b/src/lib/content.cc
@@ -155,6 +155,7 @@ Content::examine (shared_ptr<Job> job)
void
Content::signal_changed (int p)
{
+ changed (p);
emit (boost::bind (boost::ref (Changed), shared_from_this (), p, _change_signals_frequent));
}
diff --git a/src/lib/content.h b/src/lib/content.h
index f488962b3..60dd89b97 100644
--- a/src/lib/content.h
+++ b/src/lib/content.h
@@ -93,6 +93,8 @@ public:
*/
virtual std::list<DCPTime> reel_split_points () const;
+ virtual void changed (int) {}
+
boost::shared_ptr<Content> clone () const;
void set_path (boost::filesystem::path);
@@ -167,6 +169,7 @@ public:
boost::signals2::signal<void (boost::weak_ptr<Content>, int, bool)> Changed;
boost::shared_ptr<VideoContent> video;
+ boost::shared_ptr<AudioContent> audio;
boost::shared_ptr<SubtitleContent> subtitle;
void signal_changed (int);
diff --git a/src/lib/dcp_content.cc b/src/lib/dcp_content.cc
index a81a152c1..cfd19fe31 100644
--- a/src/lib/dcp_content.cc
+++ b/src/lib/dcp_content.cc
@@ -19,6 +19,7 @@
#include "dcp_content.h"
#include "video_content.h"
+#include "audio_content.h"
#include "dcp_examiner.h"
#include "job.h"
#include "film.h"
@@ -55,7 +56,6 @@ int const DCPContentProperty::REFERENCE_SUBTITLE = 603;
DCPContent::DCPContent (shared_ptr<const Film> film, boost::filesystem::path p)
: Content (film)
- , AudioContent (film)
, _has_subtitles (false)
, _encrypted (false)
, _kdm_valid (false)
@@ -64,6 +64,7 @@ DCPContent::DCPContent (shared_ptr<const Film> film, boost::filesystem::path p)
, _reference_subtitle (false)
{
video.reset (new VideoContent (this, film));
+ audio.reset (new AudioContent (this, film));
subtitle.reset (new SubtitleContent (this, film));
read_directory (p);
@@ -72,10 +73,14 @@ DCPContent::DCPContent (shared_ptr<const Film> film, boost::filesystem::path p)
DCPContent::DCPContent (shared_ptr<const Film> film, cxml::ConstNodePtr node, int version)
: Content (film, node)
- , AudioContent (film, node)
- , _audio_stream (new AudioStream (node->number_child<int> ("AudioFrameRate"), AudioMapping (node->node_child ("AudioMapping"), version)))
{
video.reset (new VideoContent (this, film, node, version));
+ audio.reset (new AudioContent (this, film, node));
+ audio->set_stream (
+ AudioStreamPtr (
+ new AudioStream (node->number_child<int> ("AudioFrameRate"), AudioMapping (node->node_child ("AudioMapping"), version))
+ )
+ );
subtitle.reset (new SubtitleContent (this, film, node, version));
_name = node->string_child ("Name");
@@ -116,10 +121,12 @@ DCPContent::examine (shared_ptr<Job> job)
{
boost::mutex::scoped_lock lm (_mutex);
- _audio_stream.reset (new AudioStream (examiner->audio_frame_rate(), examiner->audio_channels ()));
- AudioMapping m = _audio_stream->mapping ();
+
+ AudioStreamPtr as (new AudioStream (examiner->audio_frame_rate(), examiner->audio_channels ()));
+ audio->set_stream (as);
+ AudioMapping m = as->mapping ();
film()->make_audio_mapping_default (m);
- _audio_stream->set_mapping (m);
+ as->set_mapping (m);
}
signal_changed (AudioContentProperty::AUDIO_STREAMS);
@@ -149,7 +156,7 @@ DCPContent::technical_summary () const
{
return Content::technical_summary() + " - "
+ video->technical_summary() + " - "
- + AudioContent::technical_summary() + " - ";
+ + audio->technical_summary() + " - ";
}
void
@@ -159,9 +166,9 @@ DCPContent::as_xml (xmlpp::Node* node) const
Content::as_xml (node);
video->as_xml (node);
- AudioContent::as_xml (node);
- node->add_child("AudioFrameRate")->add_child_text (raw_convert<string> (audio_stream()->frame_rate ()));
- audio_stream()->mapping().as_xml (node->add_child("AudioMapping"));
+ audio->as_xml (node);
+ node->add_child("AudioFrameRate")->add_child_text (raw_convert<string> (audio->stream()->frame_rate()));
+ audio->stream()->mapping().as_xml (node->add_child("AudioMapping"));
subtitle->as_xml (node);
boost::mutex::scoped_lock lm (_mutex);
@@ -226,7 +233,7 @@ DCPContent::directory () const
void
DCPContent::add_properties (list<UserProperty>& p) const
{
- AudioContent::add_properties (p);
+ audio->add_properties (p);
}
void
@@ -337,15 +344,8 @@ DCPContent::can_reference_video (list<string>& why_not) const
bool
DCPContent::can_reference_audio (list<string>& why_not) const
{
- DCPDecoder decoder (shared_from_this(), film()->log(), false);
- BOOST_FOREACH (shared_ptr<dcp::Reel> i, decoder.reels()) {
- if (!i->main_sound()) {
- why_not.push_back (_("The DCP does not have sound in all reels."));
- return false;
- }
- }
-
- return can_reference<AudioContent> (_("There is other audio content overlapping this DCP; remove it."), why_not);
+ /* XXX: this needs to be fixed */
+ return true;
}
bool
@@ -355,16 +355,10 @@ DCPContent::can_reference_subtitle (list<string>& why_not) const
return true;
}
-double
-DCPContent::subtitle_video_frame_rate () const
-{
- return video->video_frame_rate ();
-}
-
-vector<AudioStreamPtr>
-DCPContent::audio_streams () const
+void
+DCPContent::changed (int property)
{
- vector<AudioStreamPtr> s;
- s.push_back (_audio_stream);
- return s;
+ if (property == VideoContentProperty::VIDEO_FRAME_RATE && subtitle) {
+ subtitle->set_subtitle_video_frame_rate (video->video_frame_rate ());
+ }
}
diff --git a/src/lib/dcp_content.h b/src/lib/dcp_content.h
index f3cd6bf65..b2bc90ebd 100644
--- a/src/lib/dcp_content.h
+++ b/src/lib/dcp_content.h
@@ -24,7 +24,7 @@
* @brief DCPContent class.
*/
-#include "audio_content.h"
+#include "content.h"
#include <libcxml/cxml.h>
#include <dcp/encrypted_kdm.h>
@@ -40,7 +40,7 @@ public:
/** @class DCPContent
* @brief An existing DCP used as input.
*/
-class DCPContent : public AudioContent
+class DCPContent : public Content
{
public:
DCPContent (boost::shared_ptr<const Film>, boost::filesystem::path p);
@@ -65,8 +65,6 @@ public:
void set_default_colour_conversion ();
std::list<DCPTime> reel_split_points () const;
- /* SubtitleContent */
-
bool has_text_subtitles () const {
boost::mutex::scoped_lock lm (_mutex);
return _has_subtitles;
@@ -76,7 +74,7 @@ public:
return false;
}
- double subtitle_video_frame_rate () const;
+ void changed (int property);
boost::filesystem::path directory () const;
@@ -120,16 +118,9 @@ public:
bool can_reference_subtitle (std::list<std::string> &) const;
- std::vector<AudioStreamPtr> audio_streams () const;
-
- AudioStreamPtr audio_stream () const {
- return _audio_stream;
- }
-
-protected:
+private:
void add_properties (std::list<UserProperty>& p) const;
-private:
void read_directory (boost::filesystem::path);
std::list<DCPTimePeriod> reels () const;
template <class T> bool can_reference (std::string overlapping, std::list<std::string>& why_not) const;
@@ -153,8 +144,6 @@ private:
* rather than by rewrapping.
*/
bool _reference_subtitle;
-
- boost::shared_ptr<AudioStream> _audio_stream;
};
#endif
diff --git a/src/lib/dcp_decoder.cc b/src/lib/dcp_decoder.cc
index f032ee661..4e28dc758 100644
--- a/src/lib/dcp_decoder.cc
+++ b/src/lib/dcp_decoder.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2014-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2016 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
#include "dcp_decoder.h"
#include "dcp_content.h"
+#include "audio_content.h"
#include "j2k_image_proxy.h"
#include "image.h"
#include "config.h"
@@ -44,7 +45,7 @@ using boost::dynamic_pointer_cast;
DCPDecoder::DCPDecoder (shared_ptr<const DCPContent> c, shared_ptr<Log> log, bool fast)
: VideoDecoder (c->video, log)
- , AudioDecoder (c, fast)
+ , AudioDecoder (c->audio, fast, log)
, SubtitleDecoder (c->subtitle)
, _dcp_content (c)
{
@@ -103,7 +104,7 @@ DCPDecoder::pass (PassReason reason, bool)
shared_ptr<const dcp::SoundFrame> sf = (*_reel)->main_sound()->asset()->get_frame (entry_point + frame);
uint8_t const * from = sf->data ();
- int const channels = _dcp_content->audio_stream()->channels ();
+ int const channels = _dcp_content->audio->stream()->channels ();
int const frames = sf->size() / (3 * channels);
shared_ptr<AudioBuffers> data (new AudioBuffers (channels, frames));
for (int i = 0; i < frames; ++i) {
@@ -113,7 +114,7 @@ DCPDecoder::pass (PassReason reason, bool)
}
}
- audio (_dcp_content->audio_stream(), data, ContentTime::from_frames (offset, vfr) + _next);
+ audio (_dcp_content->audio->stream(), data, ContentTime::from_frames (offset, vfr) + _next);
}
if ((*_reel)->main_subtitle ()) {
diff --git a/src/lib/dcp_subtitle_content.cc b/src/lib/dcp_subtitle_content.cc
index b38c0c6a7..3feb8947a 100644
--- a/src/lib/dcp_subtitle_content.cc
+++ b/src/lib/dcp_subtitle_content.cc
@@ -44,7 +44,6 @@ DCPSubtitleContent::DCPSubtitleContent (shared_ptr<const Film> film, boost::file
DCPSubtitleContent::DCPSubtitleContent (shared_ptr<const Film> film, cxml::ConstNodePtr node, int version)
: Content (film, node)
, _length (node->number_child<ContentTime::Type> ("Length"))
- , _frame_rate (node->optional_number_child<int>("SubtitleFrameRate"))
{
subtitle.reset (new SubtitleContent (this, film, node, version));
}
@@ -68,7 +67,7 @@ DCPSubtitleContent::examine (shared_ptr<Job> job)
shared_ptr<dcp::SMPTESubtitleAsset> smpte = dynamic_pointer_cast<dcp::SMPTESubtitleAsset> (sc);
if (smpte) {
subtitle->set_subtitle_language (smpte->language().get_value_or (""));
- _frame_rate = smpte->edit_rate().numerator;
+ subtitle->set_subtitle_video_frame_rate (smpte->edit_rate().numerator);
}
_length = ContentTime::from_seconds (sc->latest_subtitle_out().as_seconds ());
@@ -81,7 +80,7 @@ DCPSubtitleContent::examine (shared_ptr<Job> job)
DCPTime
DCPSubtitleContent::full_length () const
{
- FrameRateChange const frc (subtitle_video_frame_rate(), film()->video_frame_rate());
+ FrameRateChange const frc (subtitle->subtitle_video_frame_rate(), film()->video_frame_rate());
return DCPTime (_length, frc);
}
@@ -105,30 +104,3 @@ DCPSubtitleContent::as_xml (xmlpp::Node* node) const
subtitle->as_xml (node);
node->add_child("Length")->add_child_text (raw_convert<string> (_length.get ()));
}
-
-void
-DCPSubtitleContent::set_subtitle_video_frame_rate (int r)
-{
- {
- boost::mutex::scoped_lock lm (_mutex);
- _frame_rate = r;
- }
-
- signal_changed (SubtitleContentProperty::SUBTITLE_VIDEO_FRAME_RATE);
-}
-
-double
-DCPSubtitleContent::subtitle_video_frame_rate () const
-{
- {
- boost::mutex::scoped_lock lm (_mutex);
- if (_frame_rate) {
- return _frame_rate.get ();
- }
- }
-
- /* No frame rate specified, so assume this content has been
- prepared for any concurrent video content.
- */
- return film()->active_frame_rate_change(position()).source;
-}
diff --git a/src/lib/dcp_subtitle_content.h b/src/lib/dcp_subtitle_content.h
index de9fa68ec..211765796 100644
--- a/src/lib/dcp_subtitle_content.h
+++ b/src/lib/dcp_subtitle_content.h
@@ -43,11 +43,6 @@ public:
return false;
}
- double subtitle_video_frame_rate () const;
- void set_subtitle_video_frame_rate (int r);
-
private:
ContentTime _length;
- /** Video frame rate that this content has been prepared for, if known */
- boost::optional<double> _frame_rate;
};
diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc
index f276a16a3..c67d643a5 100644
--- a/src/lib/ffmpeg_content.cc
+++ b/src/lib/ffmpeg_content.cc
@@ -19,6 +19,7 @@
#include "ffmpeg_content.h"
#include "video_content.h"
+#include "audio_content.h"
#include "ffmpeg_examiner.h"
#include "ffmpeg_subtitle_stream.h"
#include "ffmpeg_audio_stream.h"
@@ -62,9 +63,9 @@ int const FFmpegContentProperty::FILTERS = 102;
FFmpegContent::FFmpegContent (shared_ptr<const Film> film, boost::filesystem::path p)
: Content (film, p)
- , AudioContent (film, p)
{
video.reset (new VideoContent (this, film));
+ audio.reset (new AudioContent (this, film));
subtitle.reset (new SubtitleContent (this, film));
set_default_colour_conversion ();
@@ -72,9 +73,9 @@ FFmpegContent::FFmpegContent (shared_ptr<const Film> film, boost::filesystem::pa
FFmpegContent::FFmpegContent (shared_ptr<const Film> film, cxml::ConstNodePtr node, int version, list<string>& notes)
: Content (film, node)
- , AudioContent (film, node)
{
video.reset (new VideoContent (this, film, node, version));
+ audio.reset (new AudioContent (this, film, node));
subtitle.reset (new SubtitleContent (this, film, node, version));
list<cxml::NodePtr> c = node->node_children ("SubtitleStream");
@@ -87,10 +88,11 @@ FFmpegContent::FFmpegContent (shared_ptr<const Film> film, cxml::ConstNodePtr no
c = node->node_children ("AudioStream");
for (list<cxml::NodePtr>::const_iterator i = c.begin(); i != c.end(); ++i) {
- _audio_streams.push_back (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream (*i, version)));
+ shared_ptr<FFmpegAudioStream> as (new FFmpegAudioStream (*i, version));
+ audio->add_stream (as);
if (version < 11 && !(*i)->optional_node_child ("Selected")) {
/* This is an old file and this stream is not selected, so un-map it */
- _audio_streams.back()->set_mapping (AudioMapping (_audio_streams.back()->channels (), MAX_DCP_AUDIO_CHANNELS));
+ as->set_mapping (AudioMapping (_audio_streams.back()->channels (), MAX_DCP_AUDIO_CHANNELS));
}
}
@@ -121,9 +123,9 @@ FFmpegContent::FFmpegContent (shared_ptr<const Film> film, cxml::ConstNodePtr no
FFmpegContent::FFmpegContent (shared_ptr<const Film> film, vector<boost::shared_ptr<Content> > c)
: Content (film, c)
- , AudioContent (film, c)
{
video.reset (new VideoContent (this, film, c));
+ audio.reset (new AudioContent (this, film, c));
subtitle.reset (new SubtitleContent (this, film, c));
shared_ptr<FFmpegContent> ref = dynamic_pointer_cast<FFmpegContent> (c[0]);
@@ -140,7 +142,6 @@ FFmpegContent::FFmpegContent (shared_ptr<const Film> film, vector<boost::shared_
_subtitle_streams = ref->subtitle_streams ();
_subtitle_stream = ref->subtitle_stream ();
- _audio_streams = ref->ffmpeg_audio_streams ();
_first_video = ref->_first_video;
_filters = ref->_filters;
_color_range = ref->_color_range;
@@ -156,7 +157,7 @@ FFmpegContent::as_xml (xmlpp::Node* node) const
node->add_child("Type")->add_child_text ("FFmpeg");
Content::as_xml (node);
video->as_xml (node);
- AudioContent::as_xml (node);
+ audio->as_xml (node);
subtitle->as_xml (node);
boost::mutex::scoped_lock lm (_mutex);
@@ -169,8 +170,10 @@ FFmpegContent::as_xml (xmlpp::Node* node) const
(*i)->as_xml (t);
}
- for (vector<shared_ptr<FFmpegAudioStream> >::const_iterator i = _audio_streams.begin(); i != _audio_streams.end(); ++i) {
- (*i)->as_xml (node->add_child("AudioStream"));
+ BOOST_FOREACH (AudioStreamPtr i, audio->streams ()) {
+ shared_ptr<FFmpegAudioStream> f = dynamic_pointer_cast<FFmpegAudioStream> (i);
+ DCPOMATIC_ASSERT (f);
+ f->as_xml (node->add_child("AudioStream"));
}
for (vector<Filter const *>::const_iterator i = _filters.begin(); i != _filters.end(); ++i) {
@@ -209,12 +212,15 @@ FFmpegContent::examine (shared_ptr<Job> job)
_subtitle_stream = _subtitle_streams.front ();
}
- _audio_streams = examiner->audio_streams ();
+ BOOST_FOREACH (shared_ptr<FFmpegAudioStream> i, examiner->audio_streams ()) {
+ audio->add_stream (i);
+ }
- if (!_audio_streams.empty ()) {
- AudioMapping m = _audio_streams.front()->mapping ();
+ if (!audio->streams().empty ()) {
+ AudioStreamPtr as = audio->streams().front();
+ AudioMapping m = as->mapping ();
film()->make_audio_mapping_default (m);
- _audio_streams.front()->set_mapping (m);
+ as->set_mapping (m);
}
_first_video = examiner->first_video ();
@@ -228,7 +234,6 @@ FFmpegContent::examine (shared_ptr<Job> job)
signal_changed (FFmpegContentProperty::SUBTITLE_STREAMS);
signal_changed (FFmpegContentProperty::SUBTITLE_STREAM);
- signal_changed (AudioContentProperty::AUDIO_STREAMS);
}
string
@@ -259,7 +264,7 @@ FFmpegContent::technical_summary () const
return Content::technical_summary() + " - "
+ video->technical_summary() + " - "
- + AudioContent::technical_summary() + " - "
+ + audio->technical_summary() + " - "
+ String::compose (
"ffmpeg: audio %1 subtitle %2 filters %3", as, ss, filt
);
@@ -403,7 +408,7 @@ FFmpegContent::add_properties (list<UserProperty>& p) const
{
Content::add_properties (p);
video->add_properties (p);
- AudioContent::add_properties (p);
+ audio->add_properties (p);
if (_bits_per_pixel) {
int const sub = 219 * pow (2, _bits_per_pixel.get() - 8);
@@ -528,8 +533,10 @@ FFmpegContent::signal_subtitle_stream_changed ()
signal_changed (FFmpegContentProperty::SUBTITLE_STREAM);
}
-double
-FFmpegContent::subtitle_video_frame_rate () const
+void
+FFmpegContent::changed (int property)
{
- return video->video_frame_rate ();
+ if (property == VideoContentProperty::VIDEO_FRAME_RATE && subtitle) {
+ subtitle->set_subtitle_video_frame_rate (video->video_frame_rate ());
+ }
}
diff --git a/src/lib/ffmpeg_content.h b/src/lib/ffmpeg_content.h
index da0eb48af..f39414a61 100644
--- a/src/lib/ffmpeg_content.h
+++ b/src/lib/ffmpeg_content.h
@@ -20,7 +20,8 @@
#ifndef DCPOMATIC_FFMPEG_CONTENT_H
#define DCPOMATIC_FFMPEG_CONTENT_H
-#include "audio_content.h"
+#include "content.h"
+#include "audio_stream.h"
struct AVFormatContext;
struct AVStream;
@@ -41,7 +42,7 @@ public:
static int const FILTERS;
};
-class FFmpegContent : public AudioContent
+class FFmpegContent : public Content
{
public:
FFmpegContent (boost::shared_ptr<const Film>, boost::filesystem::path);
@@ -60,19 +61,17 @@ public:
std::string identifier () const;
- /* VideoContent */
void set_default_colour_conversion ();
- /* AudioContent */
std::vector<AudioStreamPtr> audio_streams () const;
- /* SubtitleContent */
bool has_text_subtitles () const;
bool has_image_subtitles () const;
- double subtitle_video_frame_rate () const;
void set_filters (std::vector<Filter const *> const &);
+ void changed (int property);
+
std::vector<boost::shared_ptr<FFmpegSubtitleStream> > subtitle_streams () const {
boost::mutex::scoped_lock lm (_mutex);
return _subtitle_streams;
@@ -105,10 +104,9 @@ public:
void signal_subtitle_stream_changed ();
-protected:
+private:
void add_properties (std::list<UserProperty> &) const;
-private:
friend struct ffmpeg_pts_offset_test;
friend struct audio_sampling_rate_test;
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc
index 15cc9b256..8e4a1cc23 100644
--- a/src/lib/ffmpeg_decoder.cc
+++ b/src/lib/ffmpeg_decoder.cc
@@ -73,7 +73,7 @@ using dcp::Size;
FFmpegDecoder::FFmpegDecoder (shared_ptr<const FFmpegContent> c, shared_ptr<Log> log, bool fast)
: VideoDecoder (c->video, log)
- , AudioDecoder (c, fast)
+ , AudioDecoder (c->audio, fast, log)
, SubtitleDecoder (c->subtitle)
, FFmpeg (c)
, _log (log)
diff --git a/src/lib/film.cc b/src/lib/film.cc
index 7d319fc1e..49a0a9b13 100644
--- a/src/lib/film.cc
+++ b/src/lib/film.cc
@@ -245,13 +245,12 @@ Film::audio_analysis_path (shared_ptr<const Playlist> playlist) const
MD5Digester digester;
BOOST_FOREACH (shared_ptr<Content> i, playlist->content ()) {
- shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> (i);
- if (!ac) {
+ if (!i->audio) {
continue;
}
- digester.add (ac->digest ());
- digester.add (ac->audio_mapping().digest ());
+ digester.add (i->digest ());
+ digester.add (i->audio->audio_mapping().digest ());
if (playlist->content().size() != 1) {
/* Analyses should be considered equal regardless of gain
if they were made from just one piece of content. This
@@ -259,7 +258,7 @@ Film::audio_analysis_path (shared_ptr<const Playlist> playlist) const
analysis at the plotting stage rather than having to
recompute it.
*/
- digester.add (ac->audio_gain ());
+ digester.add (i->audio->audio_gain ());
}
}
@@ -505,9 +504,8 @@ Film::mapped_audio_channels () const
}
} else {
BOOST_FOREACH (shared_ptr<Content> i, content ()) {
- shared_ptr<const AudioContent> ac = dynamic_pointer_cast<const AudioContent> (i);
- if (ac) {
- list<int> c = ac->audio_mapping().mapped_output_channels ();
+ if (i->audio) {
+ list<int> c = i->audio->mapping().mapped_output_channels ();
copy (c.begin(), c.end(), back_inserter (mapped));
}
}
@@ -639,12 +637,11 @@ Film::isdcf_name (bool if_created_now) const
bool burnt_in = true;
BOOST_FOREACH (shared_ptr<Content> i, content ()) {
- shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (i);
- if (!sc) {
+ if (!i->subtitle) {
continue;
}
- if (sc->use_subtitles() && !sc->burn_subtitles()) {
+ if (i->subtitle->use_subtitles() && !i->subtitle->burn_subtitles()) {
burnt_in = false;
}
}
@@ -1033,7 +1030,7 @@ Film::maybe_add_content (weak_ptr<Job> j, weak_ptr<Content> c)
}
add_content (content);
- if (Config::instance()->automatic_audio_analysis() && dynamic_pointer_cast<AudioContent> (content)) {
+ if (Config::instance()->automatic_audio_analysis() && content->audio) {
shared_ptr<Playlist> playlist (new Playlist);
playlist->add (content);
boost::signals2::connection c;
@@ -1050,7 +1047,7 @@ Film::add_content (shared_ptr<Content> c)
/* Add {video,subtitle} content after any existing {video,subtitle} content */
if (c->video) {
c->set_position (_playlist->video_end ());
- } else if (dynamic_pointer_cast<SubtitleContent> (c)) {
+ } else if (c->subtitle) {
c->set_position (_playlist->subtitle_end ());
}
@@ -1125,8 +1122,7 @@ int
Film::audio_frame_rate () const
{
BOOST_FOREACH (shared_ptr<Content> i, content ()) {
- shared_ptr<AudioContent> a = dynamic_pointer_cast<AudioContent> (i);
- if (a && a->has_rate_above_48k ()) {
+ if (i->audio && i->audio->has_rate_above_48k ()) {
return 96000;
}
}
@@ -1271,9 +1267,8 @@ Film::subtitle_language () const
ContentList cl = content ();
BOOST_FOREACH (shared_ptr<Content>& c, cl) {
- shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (c);
- if (sc) {
- languages.insert (sc->subtitle_language ());
+ if (c->subtitle) {
+ languages.insert (c->subtitle->subtitle_language ());
}
}
diff --git a/src/lib/player.cc b/src/lib/player.cc
index 9c216c253..ce048ed79 100644
--- a/src/lib/player.cc
+++ b/src/lib/player.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@
#include "film.h"
#include "ffmpeg_decoder.h"
#include "audio_buffers.h"
+#include "audio_content.h"
#include "ffmpeg_content.h"
#include "image_decoder.h"
#include "image_content.h"
@@ -143,7 +144,7 @@ Player::setup_pieces ()
/* SndfileContent */
shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (i);
if (sc) {
- decoder.reset (new SndfileDecoder (sc, _fast));
+ decoder.reset (new SndfileDecoder (sc, _fast, _film->log()));
/* Work out a FrameRateChange for the best overlap video for this content */
DCPTime best_overlap_t;
@@ -177,14 +178,14 @@ Player::setup_pieces ()
shared_ptr<const TextSubtitleContent> rc = dynamic_pointer_cast<const TextSubtitleContent> (i);
if (rc) {
decoder.reset (new TextSubtitleDecoder (rc));
- frc = FrameRateChange (rc->subtitle_video_frame_rate(), _film->video_frame_rate());
+ frc = FrameRateChange (rc->subtitle->subtitle_video_frame_rate(), _film->video_frame_rate());
}
/* DCPSubtitleContent */
shared_ptr<const DCPSubtitleContent> dsc = dynamic_pointer_cast<const DCPSubtitleContent> (i);
if (dsc) {
decoder.reset (new DCPSubtitleDecoder (dsc));
- frc = FrameRateChange (dsc->subtitle_video_frame_rate(), _film->video_frame_rate());
+ frc = FrameRateChange (dsc->subtitle->subtitle_video_frame_rate(), _film->video_frame_rate());
}
shared_ptr<VideoDecoder> vd = dynamic_pointer_cast<VideoDecoder> (decoder);
@@ -480,9 +481,8 @@ Player::get_audio (DCPTime time, DCPTime length, bool accurate)
bool all_referenced = true;
BOOST_FOREACH (shared_ptr<Piece> i, ov) {
- shared_ptr<AudioContent> audio_content = dynamic_pointer_cast<AudioContent> (i->content);
shared_ptr<DCPContent> dcp_content = dynamic_pointer_cast<DCPContent> (i->content);
- if (audio_content && (!dcp_content || !dcp_content->reference_audio ())) {
+ if (i->content->audio && (!dcp_content || !dcp_content->reference_audio ())) {
/* There is audio content which is not from a DCP or not set to be referenced */
all_referenced = false;
}
@@ -494,13 +494,12 @@ Player::get_audio (DCPTime time, DCPTime length, bool accurate)
BOOST_FOREACH (shared_ptr<Piece> i, ov) {
- shared_ptr<AudioContent> content = dynamic_pointer_cast<AudioContent> (i->content);
- DCPOMATIC_ASSERT (content);
+ DCPOMATIC_ASSERT (i->content->audio);
shared_ptr<AudioDecoder> decoder = dynamic_pointer_cast<AudioDecoder> (i->decoder);
DCPOMATIC_ASSERT (decoder);
/* The time that we should request from the content */
- DCPTime request = time - DCPTime::from_seconds (content->audio_delay() / 1000.0);
+ DCPTime request = time - DCPTime::from_seconds (i->content->audio->audio_delay() / 1000.0);
Frame request_frames = length_frames;
DCPTime offset;
if (request < DCPTime ()) {
@@ -517,7 +516,7 @@ Player::get_audio (DCPTime time, DCPTime length, bool accurate)
Frame const content_frame = dcp_to_resampled_audio (i, request);
- BOOST_FOREACH (AudioStreamPtr j, content->audio_streams ()) {
+ BOOST_FOREACH (AudioStreamPtr j, i->content->audio->streams ()) {
if (j->channels() == 0) {
/* Some content (e.g. DCPs) can have streams with no channels */
@@ -528,9 +527,9 @@ Player::get_audio (DCPTime time, DCPTime length, bool accurate)
ContentAudio all = decoder->get_audio (j, content_frame, request_frames, accurate);
/* Gain */
- if (content->audio_gain() != 0) {
+ if (i->content->audio->audio_gain() != 0) {
shared_ptr<AudioBuffers> gain (new AudioBuffers (all.audio));
- gain->apply_gain (content->audio_gain ());
+ gain->apply_gain (i->content->audio->audio_gain ());
all.audio = gain;
}
@@ -572,7 +571,6 @@ Player::get_audio (DCPTime time, DCPTime length, bool accurate)
Frame
Player::dcp_to_content_video (shared_ptr<const Piece> piece, DCPTime t) const
{
- shared_ptr<const VideoContent> vc = dynamic_pointer_cast<const VideoContent> (piece->content);
DCPTime s = t - piece->content->position ();
s = min (piece->content->length_after_trim(), s);
s = max (DCPTime(), s + DCPTime (piece->content->trim_start(), piece->frc));
@@ -590,7 +588,6 @@ Player::dcp_to_content_video (shared_ptr<const Piece> piece, DCPTime t) const
DCPTime
Player::content_video_to_dcp (shared_ptr<const Piece> piece, Frame f) const
{
- shared_ptr<const VideoContent> vc = dynamic_pointer_cast<const VideoContent> (piece->content);
/* See comment in dcp_to_content_video */
DCPTime const d = DCPTime::from_frames (f * piece->frc.factor(), piece->frc.dcp) - DCPTime (piece->content->trim_start (), piece->frc);
return max (DCPTime (), d + piece->content->position ());
@@ -704,12 +701,11 @@ Player::get_subtitle_fonts ()
list<shared_ptr<Font> > fonts;
BOOST_FOREACH (shared_ptr<Piece>& p, _pieces) {
- shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (p->content);
- if (sc) {
+ if (p->content->subtitle) {
/* XXX: things may go wrong if there are duplicate font IDs
with different font files.
*/
- list<shared_ptr<Font> > f = sc->fonts ();
+ list<shared_ptr<Font> > f = p->content->subtitle->fonts ();
copy (f.begin(), f.end(), back_inserter (fonts));
}
}
diff --git a/src/lib/playlist.cc b/src/lib/playlist.cc
index 645993050..092060fa0 100644
--- a/src/lib/playlist.cc
+++ b/src/lib/playlist.cc
@@ -150,12 +150,8 @@ Playlist::video_identifier () const
string t;
BOOST_FOREACH (shared_ptr<const Content> i, _content) {
- shared_ptr<const VideoContent> vc = dynamic_pointer_cast<const VideoContent> (i);
- shared_ptr<const SubtitleContent> sc = dynamic_pointer_cast<const SubtitleContent> (i);
- if (vc) {
- t += vc->identifier ();
- } else if (sc && sc->burn_subtitles ()) {
- t += sc->identifier ();
+ if (i->video || (i->subtitle && i->subtitle->burn_subtitles())) {
+ t += i->identifier ();
}
}
@@ -346,7 +342,7 @@ Playlist::video_end () const
{
DCPTime end;
BOOST_FOREACH (shared_ptr<Content> i, _content) {
- if (dynamic_pointer_cast<const VideoContent> (i)) {
+ if (i->video) {
end = max (end, i->end ());
}
}
@@ -359,7 +355,7 @@ Playlist::subtitle_end () const
{
DCPTime end;
BOOST_FOREACH (shared_ptr<Content> i, _content) {
- if (dynamic_pointer_cast<const SubtitleContent> (i)) {
+ if (i->subtitle) {
end = max (end, i->end ());
}
}
diff --git a/src/lib/sndfile_content.cc b/src/lib/sndfile_content.cc
index d8435613d..d023b27d6 100644
--- a/src/lib/sndfile_content.cc
+++ b/src/lib/sndfile_content.cc
@@ -20,6 +20,7 @@
#include "sndfile_content.h"
#include "sndfile_decoder.h"
#include "sndfile_examiner.h"
+#include "audio_content.h"
#include "film.h"
#include "compose.hpp"
#include "job.h"
@@ -39,18 +40,19 @@ using boost::shared_ptr;
SndfileContent::SndfileContent (shared_ptr<const Film> film, boost::filesystem::path p)
: Content (film, p)
- , AudioContent (film, p)
{
-
+ audio.reset (new AudioContent (this, film));
}
SndfileContent::SndfileContent (shared_ptr<const Film> film, cxml::ConstNodePtr node, int version)
: Content (film, node)
- , AudioContent (film, node)
, _audio_length (node->number_child<Frame> ("AudioLength"))
- , _audio_stream (new AudioStream (node->number_child<int> ("AudioFrameRate"), AudioMapping (node->node_child ("AudioMapping"), version)))
{
-
+ audio.reset (new AudioContent (this, film, node));
+ audio->set_stream (
+ AudioStreamPtr (
+ new AudioStream (node->number_child<int> ("AudioFrameRate"), AudioMapping (node->node_child ("AudioMapping"), version)))
+ );
}
void
@@ -58,9 +60,9 @@ SndfileContent::as_xml (xmlpp::Node* node) const
{
node->add_child("Type")->add_child_text ("Sndfile");
Content::as_xml (node);
- AudioContent::as_xml (node);
- node->add_child("AudioFrameRate")->add_child_text (raw_convert<string> (audio_stream()->frame_rate ()));
- audio_stream()->mapping().as_xml (node->add_child("AudioMapping"));
+ audio->as_xml (node);
+ node->add_child("AudioFrameRate")->add_child_text (raw_convert<string> (audio->stream()->frame_rate ()));
+ audio->stream()->mapping().as_xml (node->add_child("AudioMapping"));
node->add_child("AudioLength")->add_child_text (raw_convert<string> (audio_length ()));
}
@@ -76,7 +78,7 @@ string
SndfileContent::technical_summary () const
{
return Content::technical_summary() + " - "
- + AudioContent::technical_summary ()
+ + audio->technical_summary ()
+ " - sndfile";
}
@@ -103,10 +105,11 @@ SndfileContent::take_from_audio_examiner (shared_ptr<AudioExaminer> examiner)
{
{
boost::mutex::scoped_lock lm (_mutex);
- _audio_stream.reset (new AudioStream (examiner->audio_frame_rate(), examiner->audio_channels ()));
- AudioMapping m = _audio_stream->mapping ();
+ AudioStreamPtr as (new AudioStream (examiner->audio_frame_rate(), examiner->audio_channels ()));
+ audio->set_stream (as);
+ AudioMapping m = as->mapping ();
film()->make_audio_mapping_default (m);
- _audio_stream->set_mapping (m);
+ as->set_mapping (m);
_audio_length = examiner->audio_length ();
}
@@ -116,14 +119,6 @@ SndfileContent::take_from_audio_examiner (shared_ptr<AudioExaminer> examiner)
DCPTime
SndfileContent::full_length () const
{
- FrameRateChange const frc (audio_video_frame_rate(), film()->video_frame_rate());
- return DCPTime::from_frames (audio_length() / frc.speed_up, audio_stream()->frame_rate ());
-}
-
-vector<AudioStreamPtr>
-SndfileContent::audio_streams () const
-{
- vector<AudioStreamPtr> s;
- s.push_back (_audio_stream);
- return s;
+ FrameRateChange const frc (audio->audio_video_frame_rate(), film->video_frame_rate());
+ return DCPTime::from_frames (audio_length() / frc.speed_up, audio->stream()->frame_rate ());
}
diff --git a/src/lib/sndfile_content.h b/src/lib/sndfile_content.h
index 5f89b7cc8..dfd36971d 100644
--- a/src/lib/sndfile_content.h
+++ b/src/lib/sndfile_content.h
@@ -20,11 +20,11 @@
#ifndef DCPOMATIC_SNDFILE_CONTENT_H
#define DCPOMATIC_SNDFILE_CONTENT_H
-#include "audio_content.h"
+#include "content.h"
class AudioExaminer;
-class SndfileContent : public AudioContent
+class SndfileContent : public Content
{
public:
SndfileContent (boost::shared_ptr<const Film>, boost::filesystem::path);
@@ -44,12 +44,6 @@ public:
void take_from_audio_examiner (boost::shared_ptr<AudioExaminer>);
- std::vector<AudioStreamPtr> audio_streams () const;
-
- AudioStreamPtr audio_stream () const {
- return _audio_stream;
- }
-
static bool valid_file (boost::filesystem::path);
private:
@@ -59,8 +53,6 @@ private:
}
Frame _audio_length;
-
- boost::shared_ptr<AudioStream> _audio_stream;
};
#endif
diff --git a/src/lib/sndfile_decoder.cc b/src/lib/sndfile_decoder.cc
index ac01e0da8..b05750ac8 100644
--- a/src/lib/sndfile_decoder.cc
+++ b/src/lib/sndfile_decoder.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
#include <iostream>
#include <sndfile.h>
+#include "audio_content.h"
#include "sndfile_content.h"
#include "sndfile_decoder.h"
#include "exceptions.h"
@@ -32,9 +33,9 @@ using std::min;
using std::cout;
using boost::shared_ptr;
-SndfileDecoder::SndfileDecoder (shared_ptr<const SndfileContent> c, bool fast)
+SndfileDecoder::SndfileDecoder (shared_ptr<const SndfileContent> c, bool fast, shared_ptr<Log> log)
: Sndfile (c)
- , AudioDecoder (c, fast)
+ , AudioDecoder (c->audio, fast, log)
, _done (0)
, _remaining (_info.frames)
, _deinterleave_buffer (0)
@@ -57,14 +58,14 @@ SndfileDecoder::pass (PassReason, bool)
/* Do things in half second blocks as I think there may be limits
to what FFmpeg (and in particular the resampler) can cope with.
*/
- sf_count_t const block = _sndfile_content->audio_stream()->frame_rate() / 2;
+ sf_count_t const block = _sndfile_content->audio->stream()->frame_rate() / 2;
sf_count_t const this_time = min (block, _remaining);
- int const channels = _sndfile_content->audio_stream()->channels ();
+ int const channels = _sndfile_content->audio->stream()->channels ();
shared_ptr<AudioBuffers> data (new AudioBuffers (channels, this_time));
- if (_sndfile_content->audio_stream()->channels() == 1) {
+ if (_sndfile_content->audio->stream()->channels() == 1) {
/* No de-interleaving required */
sf_read_float (_sndfile, data->data(0), this_time);
} else {
@@ -86,7 +87,7 @@ SndfileDecoder::pass (PassReason, bool)
}
data->set_frames (this_time);
- audio (_sndfile_content->audio_stream (), data, ContentTime::from_frames (_done, _info.samplerate));
+ audio (_sndfile_content->audio->stream (), data, ContentTime::from_frames (_done, _info.samplerate));
_done += this_time;
_remaining -= this_time;
diff --git a/src/lib/sndfile_decoder.h b/src/lib/sndfile_decoder.h
index 844d1cdc4..6f3a6cc48 100644
--- a/src/lib/sndfile_decoder.h
+++ b/src/lib/sndfile_decoder.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@ class SndfileContent;
class SndfileDecoder : public Sndfile, public AudioDecoder
{
public:
- SndfileDecoder (boost::shared_ptr<const SndfileContent> c, bool fast);
+ SndfileDecoder (boost::shared_ptr<const SndfileContent> c, bool fast, boost::shared_ptr<Log> log);
~SndfileDecoder ();
private:
diff --git a/src/lib/subtitle_content.cc b/src/lib/subtitle_content.cc
index 03c188b89..089e3a3fc 100644
--- a/src/lib/subtitle_content.cc
+++ b/src/lib/subtitle_content.cc
@@ -24,6 +24,7 @@
#include "font.h"
#include "raw_convert.h"
#include "content.h"
+#include "film.h"
#include <libcxml/cxml.h>
#include <libxml++/libxml++.h>
#include <boost/foreach.hpp>
@@ -85,6 +86,7 @@ SubtitleContent::SubtitleContent (Content* parent, shared_ptr<const Film> film,
node->optional_number_child<int>("OutlineGreen").get_value_or(255),
node->optional_number_child<int>("OutlineBlue").get_value_or(255)
)
+ , _frame_rate (node->optional_number_child<double>("SubtitleFrameRate"))
{
if (version >= 32) {
_use_subtitles = node->bool_child ("UseSubtitles");
@@ -118,38 +120,37 @@ SubtitleContent::SubtitleContent (Content* parent, shared_ptr<const Film> film,
SubtitleContent::SubtitleContent (Content* parent, shared_ptr<const Film> film, vector<shared_ptr<Content> > c)
: ContentPart (parent, film)
{
- shared_ptr<SubtitleContent> ref = dynamic_pointer_cast<SubtitleContent> (c[0]);
+ shared_ptr<SubtitleContent> ref = c[0]->subtitle;
DCPOMATIC_ASSERT (ref);
list<shared_ptr<Font> > ref_fonts = ref->fonts ();
- for (size_t i = 0; i < c.size(); ++i) {
- shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (c[i]);
+ for (size_t i = 1; i < c.size(); ++i) {
- if (sc->use_subtitles() != ref->use_subtitles()) {
+ if (c[i]->subtitle->use_subtitles() != ref->use_subtitles()) {
throw JoinError (_("Content to be joined must have the same 'use subtitles' setting."));
}
- if (sc->burn_subtitles() != ref->burn_subtitles()) {
+ if (c[i]->subtitle->burn_subtitles() != ref->burn_subtitles()) {
throw JoinError (_("Content to be joined must have the same 'burn subtitles' setting."));
}
- if (sc->subtitle_x_offset() != ref->subtitle_x_offset()) {
+ if (c[i]->subtitle->subtitle_x_offset() != ref->subtitle_x_offset()) {
throw JoinError (_("Content to be joined must have the same subtitle X offset."));
}
- if (sc->subtitle_y_offset() != ref->subtitle_y_offset()) {
+ if (c[i]->subtitle->subtitle_y_offset() != ref->subtitle_y_offset()) {
throw JoinError (_("Content to be joined must have the same subtitle Y offset."));
}
- if (sc->subtitle_x_scale() != ref->subtitle_x_scale()) {
+ if (c[i]->subtitle->subtitle_x_scale() != ref->subtitle_x_scale()) {
throw JoinError (_("Content to be joined must have the same subtitle X scale."));
}
- if (sc->subtitle_y_scale() != ref->subtitle_y_scale()) {
+ if (c[i]->subtitle->subtitle_y_scale() != ref->subtitle_y_scale()) {
throw JoinError (_("Content to be joined must have the same subtitle Y scale."));
}
- list<shared_ptr<Font> > fonts = sc->fonts ();
+ list<shared_ptr<Font> > fonts = c[i]->subtitle->fonts ();
if (fonts.size() != ref_fonts.size()) {
throw JoinError (_("Content to be joined must use the same fonts."));
}
@@ -315,3 +316,27 @@ SubtitleContent::set_subtitle_language (string language)
{
maybe_set (_subtitle_language, language, SubtitleContentProperty::SUBTITLE_LANGUAGE);
}
+
+void
+SubtitleContent::set_subtitle_video_frame_rate (double r)
+{
+ maybe_set (_frame_rate, r, SubtitleContentProperty::SUBTITLE_VIDEO_FRAME_RATE);
+}
+
+double
+SubtitleContent::subtitle_video_frame_rate () const
+{
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+ if (_frame_rate) {
+ return _frame_rate.get ();
+ }
+ }
+
+ /* No frame rate specified, so assume this content has been
+ prepared for any concurrent video content.
+ */
+ shared_ptr<const Film> film = _film.lock ();
+ DCPOMATIC_ASSERT (film);
+ return film->active_frame_rate_change(_parent->position()).source;
+}
diff --git a/src/lib/subtitle_content.h b/src/lib/subtitle_content.h
index 5982cc52c..0adb12c0d 100644
--- a/src/lib/subtitle_content.h
+++ b/src/lib/subtitle_content.h
@@ -130,6 +130,9 @@ public:
return _outline_colour;
}
+ double subtitle_video_frame_rate () const;
+ void set_subtitle_video_frame_rate (double r);
+
protected:
/** subtitle language (e.g. "German") or empty if it is not known */
std::string _subtitle_language;
@@ -158,6 +161,8 @@ private:
bool _outline;
dcp::Colour _outline_colour;
std::list<boost::signals2::connection> _font_connections;
+ /** Video frame rate that this content has been prepared for, if known */
+ boost::optional<double> _frame_rate;
};
#endif
diff --git a/src/lib/text_subtitle_content.cc b/src/lib/text_subtitle_content.cc
index c7dd19d03..79a225c47 100644
--- a/src/lib/text_subtitle_content.cc
+++ b/src/lib/text_subtitle_content.cc
@@ -86,33 +86,6 @@ TextSubtitleContent::as_xml (xmlpp::Node* node) const
DCPTime
TextSubtitleContent::full_length () const
{
- FrameRateChange const frc (subtitle_video_frame_rate(), film()->video_frame_rate ());
+ FrameRateChange const frc (subtitle->subtitle_video_frame_rate(), film()->video_frame_rate ());
return DCPTime (_length, frc);
}
-
-void
-TextSubtitleContent::set_subtitle_video_frame_rate (double r)
-{
- {
- boost::mutex::scoped_lock lm (_mutex);
- _frame_rate = r;
- }
-
- signal_changed (SubtitleContentProperty::SUBTITLE_VIDEO_FRAME_RATE);
-}
-
-double
-TextSubtitleContent::subtitle_video_frame_rate () const
-{
- {
- boost::mutex::scoped_lock lm (_mutex);
- if (_frame_rate) {
- return _frame_rate.get ();
- }
- }
-
- /* No frame rate specified, so assume this content has been
- prepared for any concurrent video content.
- */
- return film()->active_frame_rate_change(position()).source;
-}
diff --git a/src/lib/text_subtitle_content.h b/src/lib/text_subtitle_content.h
index 76440ba9b..61dac4830 100644
--- a/src/lib/text_subtitle_content.h
+++ b/src/lib/text_subtitle_content.h
@@ -40,13 +40,8 @@ public:
void as_xml (xmlpp::Node *) const;
DCPTime full_length () const;
- double subtitle_video_frame_rate () const;
- void set_subtitle_video_frame_rate (double r);
-
static std::string const font_id;
private:
ContentTime _length;
- /** Video frame rate that this content has been prepared for, if known */
- boost::optional<double> _frame_rate;
};
diff --git a/src/lib/transcoder.cc b/src/lib/transcoder.cc
index c018c9243..b7b056612 100644
--- a/src/lib/transcoder.cc
+++ b/src/lib/transcoder.cc
@@ -72,9 +72,8 @@ Transcoder::go ()
int burnt_subtitles = 0;
int non_burnt_subtitles = 0;
BOOST_FOREACH (shared_ptr<const Content> c, _film->content ()) {
- shared_ptr<const SubtitleContent> sc = dynamic_pointer_cast<const SubtitleContent> (c);
- if (sc && sc->use_subtitles()) {
- if (sc->burn_subtitles()) {
+ if (c->subtitle && c->subtitle->use_subtitles()) {
+ if (c->subtitle->burn_subtitles()) {
++burnt_subtitles;
} else {
++non_burnt_subtitles;
diff --git a/src/lib/types.h b/src/lib/types.h
index 2bc6fa3a4..8eabdbf27 100644
--- a/src/lib/types.h
+++ b/src/lib/types.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -48,7 +48,6 @@ namespace xmlpp {
#define SERVER_LINK_VERSION (64+0)
typedef std::vector<boost::shared_ptr<Content> > ContentList;
-typedef std::vector<boost::shared_ptr<AudioContent> > AudioContentList;
typedef std::vector<boost::shared_ptr<FFmpegContent> > FFmpegContentList;
typedef int64_t Frame;
diff --git a/src/lib/video_content.cc b/src/lib/video_content.cc
index 561ebb62c..567ab3cf8 100644
--- a/src/lib/video_content.cc
+++ b/src/lib/video_content.cc
@@ -119,43 +119,42 @@ VideoContent::VideoContent (Content* parent, shared_ptr<const Film> film, vector
, _video_length (0)
, _yuv (false)
{
- shared_ptr<VideoContent> ref = dynamic_pointer_cast<VideoContent> (c[0]);
+ shared_ptr<VideoContent> ref = c[0]->video;
DCPOMATIC_ASSERT (ref);
- for (size_t i = 0; i < c.size(); ++i) {
- shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (c[i]);
+ for (size_t i = 1; i < c.size(); ++i) {
- if (vc->video_size() != ref->video_size()) {
+ if (c[i]->video->video_size() != ref->video_size()) {
throw JoinError (_("Content to be joined must have the same picture size."));
}
- if (vc->video_frame_rate() != ref->video_frame_rate()) {
+ if (c[i]->video->video_frame_rate() != ref->video_frame_rate()) {
throw JoinError (_("Content to be joined must have the same video frame rate."));
}
- if (vc->video_frame_type() != ref->video_frame_type()) {
+ if (c[i]->video->video_frame_type() != ref->video_frame_type()) {
throw JoinError (_("Content to be joined must have the same video frame type."));
}
- if (vc->crop() != ref->crop()) {
+ if (c[i]->video->crop() != ref->crop()) {
throw JoinError (_("Content to be joined must have the same crop."));
}
- if (vc->scale() != ref->scale()) {
+ if (c[i]->video->scale() != ref->scale()) {
throw JoinError (_("Content to be joined must have the same scale setting."));
}
- if (vc->colour_conversion() != ref->colour_conversion()) {
+ if (c[i]->video->colour_conversion() != ref->colour_conversion()) {
throw JoinError (_("Content to be joined must have the same colour conversion."));
}
- if (vc->fade_in() != ref->fade_in() || vc->fade_out() != ref->fade_out()) {
+ if (c[i]->video->fade_in() != ref->fade_in() || c[i]->video->fade_out() != ref->fade_out()) {
throw JoinError (_("Content to be joined must have the same fades."));
}
- _video_length += vc->video_length ();
+ _video_length += c[i]->video->video_length ();
- if (vc->yuv ()) {
+ if (c[i]->video->yuv ()) {
_yuv = true;
}
}
diff --git a/src/tools/dcpomatic_cli.cc b/src/tools/dcpomatic_cli.cc
index 7ab6d284d..63dd7f45e 100644
--- a/src/tools/dcpomatic_cli.cc
+++ b/src/tools/dcpomatic_cli.cc
@@ -84,19 +84,18 @@ print_dump (shared_ptr<Film> film)
<< " start trim " << c->trim_start().seconds ()
<< " end trim " << c->trim_end().seconds () << "\n";
- shared_ptr<VideoContent> video = dynamic_pointer_cast<VideoContent> (c);
- if (video) {
- cout << "\t" << video->video_size().width << "x" << video->video_size().height << "\n"
- << "\t" << video->video_frame_rate() << "fps\n"
- << "\tcrop left " << video->left_crop()
- << " right " << video->right_crop()
- << " top " << video->top_crop()
- << " bottom " << video->bottom_crop() << "\n"
- << "\tscale " << video->scale().name() << "\n";
- if (video->colour_conversion()) {
- if (video->colour_conversion().get().preset()) {
+ if (c->video) {
+ cout << "\t" << c->video->video_size().width << "x" << c->video->video_size().height << "\n"
+ << "\t" << c->video->video_frame_rate() << "fps\n"
+ << "\tcrop left " << c->video->left_crop()
+ << " right " << c->video->right_crop()
+ << " top " << c->video->top_crop()
+ << " bottom " << c->video->bottom_crop() << "\n"
+ << "\tscale " << c->video->scale().name() << "\n";
+ if (c->video->colour_conversion()) {
+ if (c->video->colour_conversion().get().preset()) {
cout << "\tcolour conversion "
- << PresetColourConversion::all()[video->colour_conversion().get().preset().get()].name
+ << PresetColourConversion::all()[c->video->colour_conversion().get().preset().get()].name
<< "\n";
} else {
cout << "\tcustom colour conversion\n";
@@ -107,10 +106,9 @@ print_dump (shared_ptr<Film> film)
}
- shared_ptr<AudioContent> audio = dynamic_pointer_cast<AudioContent> (c);
- if (audio) {
- cout << "\t" << audio->audio_delay() << " delay\n"
- << "\t" << audio->audio_gain() << " gain\n";
+ if (c->audio) {
+ cout << "\t" << c->audio->audio_delay() << " delay\n"
+ << "\t" << c->audio->audio_gain() << " gain\n";
}
}
}
diff --git a/src/wx/audio_dialog.cc b/src/wx/audio_dialog.cc
index 20185bf8f..2120c3a1f 100644
--- a/src/wx/audio_dialog.cc
+++ b/src/wx/audio_dialog.cc
@@ -39,7 +39,7 @@ using boost::const_pointer_cast;
using boost::dynamic_pointer_cast;
/** @param content Content to analyse, or 0 to analyse all of the film's audio */
-AudioDialog::AudioDialog (wxWindow* parent, shared_ptr<Film> film, shared_ptr<AudioContent> content)
+AudioDialog::AudioDialog (wxWindow* parent, shared_ptr<Film> film, shared_ptr<Content> content)
: wxDialog (parent, wxID_ANY, _("Audio"), wxDefaultPosition, wxSize (640, 512), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxFULL_REPAINT_ON_RESIZE)
, _film (film)
, _content (content)
diff --git a/src/wx/audio_dialog.h b/src/wx/audio_dialog.h
index 8320171ce..8624b7af3 100644
--- a/src/wx/audio_dialog.h
+++ b/src/wx/audio_dialog.h
@@ -30,7 +30,7 @@ class Film;
class AudioDialog : public wxDialog
{
public:
- AudioDialog (wxWindow *, boost::shared_ptr<Film> film, boost::shared_ptr<AudioContent> content = boost::shared_ptr<AudioContent> ());
+ AudioDialog (wxWindow *, boost::shared_ptr<Film> film, boost::shared_ptr<Content> content = boost::shared_ptr<Content> ());
bool Show (bool show = true);
diff --git a/src/wx/audio_panel.cc b/src/wx/audio_panel.cc
index 9e2ba9869..a41e428ec 100644
--- a/src/wx/audio_panel.cc
+++ b/src/wx/audio_panel.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -28,6 +28,7 @@
#include "lib/cinema_sound_processor.h"
#include "lib/job_manager.h"
#include "lib/dcp_content.h"
+#include "lib/audio_content.h"
#include <wx/spinctrl.h>
#include <boost/foreach.hpp>
#include <iostream>
@@ -65,6 +66,7 @@ AudioPanel::AudioPanel (ContentPanel* p)
this,
new wxSpinCtrlDouble (this),
AudioContentProperty::AUDIO_GAIN,
+ &Content::audio,
boost::mem_fn (&AudioContent::audio_gain),
boost::mem_fn (&AudioContent::set_audio_gain)
);
@@ -80,6 +82,7 @@ AudioPanel::AudioPanel (ContentPanel* p)
this,
new wxSpinCtrl (this),
AudioContentProperty::AUDIO_DELAY,
+ &Content::audio,
boost::mem_fn (&AudioContent::audio_delay),
boost::mem_fn (&AudioContent::set_audio_delay)
);
@@ -145,11 +148,11 @@ AudioPanel::film_changed (Film::Property property)
void
AudioPanel::film_content_changed (int property)
{
- AudioContentList ac = _parent->selected_audio ();
+ ContentList ac = _parent->selected_audio ();
if (property == AudioContentProperty::AUDIO_STREAMS) {
if (ac.size() == 1) {
- _mapping->set (ac.front()->audio_mapping());
- _mapping->set_input_channels (ac.front()->audio_channel_names ());
+ _mapping->set (ac.front()->audio->audio_mapping());
+ _mapping->set_input_channels (ac.front()->audio->audio_channel_names ());
} else {
_mapping->set (AudioMapping ());
}
@@ -201,28 +204,28 @@ AudioPanel::gain_calculate_button_clicked ()
void
AudioPanel::setup_description ()
{
- AudioContentList ac = _parent->selected_audio ();
+ ContentList ac = _parent->selected_audio ();
if (ac.size () != 1) {
checked_set (_description, wxT (""));
return;
}
- checked_set (_description, ac.front()->processing_description ());
+ checked_set (_description, ac.front()->audio->processing_description ());
}
void
AudioPanel::mapping_changed (AudioMapping m)
{
- AudioContentList c = _parent->selected_audio ();
+ ContentList c = _parent->selected_audio ();
if (c.size() == 1) {
- c.front()->set_audio_mapping (m);
+ c.front()->audio->set_audio_mapping (m);
}
}
void
AudioPanel::content_selection_changed ()
{
- AudioContentList sel = _parent->selected_audio ();
+ ContentList sel = _parent->selected_audio ();
_gain->set_content (sel);
_delay->set_content (sel);
@@ -236,7 +239,7 @@ AudioPanel::content_selection_changed ()
void
AudioPanel::setup_sensitivity ()
{
- AudioContentList sel = _parent->selected_audio ();
+ ContentList sel = _parent->selected_audio ();
shared_ptr<DCPContent> dcp;
if (sel.size() == 1) {
@@ -272,7 +275,7 @@ AudioPanel::show_clicked ()
_audio_dialog = 0;
}
- AudioContentList ac = _parent->selected_audio ();
+ ContentList ac = _parent->selected_audio ();
if (ac.size() != 1) {
return;
}
@@ -284,7 +287,7 @@ AudioPanel::show_clicked ()
void
AudioPanel::setup_peak ()
{
- AudioContentList sel = _parent->selected_audio ();
+ ContentList sel = _parent->selected_audio ();
bool alert = false;
if (sel.size() != 1) {
diff --git a/src/wx/content_menu.cc b/src/wx/content_menu.cc
index c643602bd..f2e00ea42 100644
--- a/src/wx/content_menu.cc
+++ b/src/wx/content_menu.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -32,6 +32,7 @@
#include "lib/exceptions.h"
#include "lib/dcp_content.h"
#include "lib/ffmpeg_content.h"
+#include "lib/audio_content.h"
#include <wx/wx.h>
#include <wx/dirdlg.h>
#include <boost/foreach.hpp>
@@ -205,9 +206,9 @@ ContentMenu::remove ()
}
if (!video && audio) {
- AudioMapping m = fc->audio_mapping ();
+ AudioMapping m = fc->audio->audio_mapping ();
m.unmap_all ();
- fc->set_audio_mapping (m);
+ fc->audio->set_audio_mapping (m);
handled = true;
}
}
diff --git a/src/wx/content_panel.cc b/src/wx/content_panel.cc
index ad4894897..36f0a6bb2 100644
--- a/src/wx/content_panel.cc
+++ b/src/wx/content_panel.cc
@@ -163,15 +163,14 @@ ContentPanel::selected_video ()
return vc;
}
-AudioContentList
+ContentList
ContentPanel::selected_audio ()
{
- AudioContentList ac;
+ ContentList ac;
BOOST_FOREACH (shared_ptr<Content> i, selected ()) {
- shared_ptr<AudioContent> t = dynamic_pointer_cast<AudioContent> (i);
- if (t) {
- ac.push_back (t);
+ if (i->audio) {
+ ac.push_back (i);
}
}
@@ -387,7 +386,7 @@ ContentPanel::setup_sensitivity ()
ContentList selection = selected ();
ContentList video_selection = selected_video ();
- AudioContentList audio_selection = selected_audio ();
+ ContentList audio_selection = selected_audio ();
_remove->Enable (!selection.empty() && _generally_sensitive);
_earlier->Enable (selection.size() == 1 && _generally_sensitive);
@@ -396,7 +395,7 @@ ContentPanel::setup_sensitivity ()
_video_panel->Enable (video_selection.size() > 0 && _generally_sensitive);
_audio_panel->Enable (audio_selection.size() > 0 && _generally_sensitive);
- _subtitle_panel->Enable (selection.size() == 1 && dynamic_pointer_cast<SubtitleContent> (selection.front()) && _generally_sensitive);
+ _subtitle_panel->Enable (selection.size() == 1 && selection.front()->subtitle && _generally_sensitive);
_timing_panel->Enable (selection.size() == 1 && _generally_sensitive);
}
diff --git a/src/wx/content_panel.h b/src/wx/content_panel.h
index f4e2dbae2..caaa2decc 100644
--- a/src/wx/content_panel.h
+++ b/src/wx/content_panel.h
@@ -60,7 +60,7 @@ public:
ContentList selected ();
ContentList selected_video ();
- AudioContentList selected_audio ();
+ ContentList selected_audio ();
ContentList selected_subtitle ();
FFmpegContentList selected_ffmpeg ();
diff --git a/src/wx/content_widget.h b/src/wx/content_widget.h
index 3fa1f0ddc..49dceef8e 100644
--- a/src/wx/content_widget.h
+++ b/src/wx/content_widget.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,21 +21,22 @@
* @brief ContentWidget class.
*/
-#ifndef DCPOMATIC_MULTIPLE_WIDGET_H
-#define DCPOMATIC_MULTIPLE_WIDGET_H
+#ifndef DCPOMATIC_CONTENT_WIDGET_H
+#define DCPOMATIC_CONTENT_WIDGET_H
-#include <vector>
+#include "wx_util.h"
+#include "lib/content.h"
#include <wx/wx.h>
#include <wx/gbsizer.h>
#include <wx/spinctrl.h>
#include <boost/function.hpp>
-#include "wx_util.h"
+#include <vector>
/** @class ContentWidget
* @brief A widget which represents some Content state and which can be used
* when multiple pieces of content are selected.
*
- * @param S Type containing the content being represented (e.g. VideoContent)
+ * @param S Type of ContentPart being manipulated (e.g. VideoContent)
* @param T Type of the widget (e.g. wxSpinCtrl)
* @param U Data type of state as used by the model.
* @param V Data type of state as used by the view.
@@ -54,6 +55,7 @@ public:
wxWindow* parent,
T* wrapped,
int property,
+ boost::function<boost::shared_ptr<S> (Content*)> part,
boost::function<U (S*)> model_getter,
boost::function<void (S*, U)> model_setter,
boost::function<U (V)> view_to_model,
@@ -63,6 +65,7 @@ public:
, _sizer (0)
, _button (new wxButton (parent, wxID_ANY, _("Multiple values")))
, _property (property)
+ , _part (part)
, _model_getter (model_getter)
, _model_setter (model_setter)
, _view_to_model (view_to_model)
@@ -80,7 +83,7 @@ public:
return _wrapped;
}
- typedef std::vector<boost::shared_ptr<S> > List;
+ typedef std::vector<boost::shared_ptr<Content> > List;
/** Set the content that this control is working on (i.e. the selected content) */
void set_content (List content)
@@ -120,8 +123,8 @@ public:
}
typename List::iterator i = _content.begin ();
- U const v = boost::bind (_model_getter, _content.front().get())();
- while (i != _content.end() && boost::bind (_model_getter, i->get())() == v) {
+ U const v = boost::bind (_model_getter, _part(_content.front().get()).get())();
+ while (i != _content.end() && boost::bind (_model_getter, _part(i->get()).get())() == v) {
++i;
}
@@ -137,7 +140,7 @@ public:
{
_ignore_model_changes = true;
for (size_t i = 0; i < _content.size(); ++i) {
- boost::bind (_model_setter, _content[i].get(), _view_to_model (wx_get (_wrapped))) ();
+ boost::bind (_model_setter, _part (_content[i].get()).get(), _view_to_model (wx_get (_wrapped))) ();
}
_ignore_model_changes = false;
}
@@ -172,9 +175,9 @@ private:
void button_clicked ()
{
- U const v = boost::bind (_model_getter, _content.front().get())();
+ U const v = boost::bind (_model_getter, _part(_content.front().get()).get())();
for (typename List::iterator i = _content.begin (); i != _content.end(); ++i) {
- boost::bind (_model_setter, i->get(), v) ();
+ boost::bind (_model_setter, _part(i->get()).get(), v) ();
}
}
@@ -192,6 +195,7 @@ private:
wxButton* _button;
List _content;
int _property;
+ boost::function<boost::shared_ptr<S> (Content *)> _part;
boost::function<U (S*)> _model_getter;
boost::function<void (S*, U)> _model_setter;
boost::function<U (V)> _view_to_model;
@@ -214,6 +218,7 @@ public:
wxWindow* parent,
wxSpinCtrl* wrapped,
int property,
+ boost::function<boost::shared_ptr<S> (Content *)> part,
boost::function<int (S*)> getter,
boost::function<void (S*, int)> setter
)
@@ -221,6 +226,7 @@ public:
parent,
wrapped,
property,
+ part,
getter, setter,
&caster<int, int>,
&caster<int, int>
@@ -238,6 +244,7 @@ public:
wxWindow* parent,
wxSpinCtrlDouble* wrapped,
int property,
+ boost::function<boost::shared_ptr<S> (Content *)> part,
boost::function<double (S*)> getter,
boost::function<void (S*, double)> setter
)
@@ -245,6 +252,7 @@ public:
parent,
wrapped,
property,
+ part,
getter, setter,
&caster<double, double>,
&caster<double, double>
@@ -262,6 +270,7 @@ public:
wxWindow* parent,
wxChoice* wrapped,
int property,
+ boost::function<boost::shared_ptr<S> (Content *)> part,
boost::function<U (S*)> getter,
boost::function<void (S*, U)> setter,
boost::function<U (int)> view_to_model,
@@ -271,6 +280,7 @@ public:
parent,
wrapped,
property,
+ part,
getter,
setter,
view_to_model,
diff --git a/src/wx/dcp_panel.cc b/src/wx/dcp_panel.cc
index c62767c9d..30657f841 100644
--- a/src/wx/dcp_panel.cc
+++ b/src/wx/dcp_panel.cc
@@ -32,6 +32,7 @@
#include "lib/video_content.h"
#include "lib/subtitle_content.h"
#include "lib/dcp_content.h"
+#include "lib/audio_content.h"
#include <dcp/key.h>
#include <dcp/raw_convert.h>
#include <wx/wx.h>
diff --git a/src/wx/hints_dialog.cc b/src/wx/hints_dialog.cc
index 75643c312..1c49a2068 100644
--- a/src/wx/hints_dialog.cc
+++ b/src/wx/hints_dialog.cc
@@ -78,11 +78,10 @@ HintsDialog::film_changed ()
bool big_font_files = false;
if (film->interop ()) {
BOOST_FOREACH (shared_ptr<Content> i, content) {
- shared_ptr<SubtitleContent> s = dynamic_pointer_cast<SubtitleContent> (i);
- if (s) {
- BOOST_FOREACH (shared_ptr<Font> j, s->fonts ()) {
- for (int i = 0; i < FontFiles::VARIANTS; ++i) {
- optional<boost::filesystem::path> const p = j->file (static_cast<FontFiles::Variant> (i));
+ if (i->subtitle) {
+ BOOST_FOREACH (shared_ptr<Font> j, i->subtitle->fonts ()) {
+ for (int k = 0; k < FontFiles::VARIANTS; ++k) {
+ optional<boost::filesystem::path> const p = j->file (static_cast<FontFiles::Variant> (k));
if (p && boost::filesystem::file_size (p.get()) >= (640 * 1024)) {
big_font_files = true;
}
@@ -106,9 +105,8 @@ HintsDialog::film_changed ()
int flat_or_narrower = 0;
int scope = 0;
BOOST_FOREACH (shared_ptr<const Content> i, content) {
- shared_ptr<const VideoContent> vc = dynamic_pointer_cast<const VideoContent> (i);
- if (vc) {
- Ratio const * r = vc->scale().ratio ();
+ if (i->video) {
+ Ratio const * r = i->video->scale().ratio ();
if (r && r->id() == "239") {
++scope;
} else if (r && r->id() != "239" && r->id() != "full-frame") {
@@ -162,8 +160,7 @@ HintsDialog::film_changed ()
int three_d = 0;
BOOST_FOREACH (shared_ptr<const Content> i, content) {
- shared_ptr<const VideoContent> vc = dynamic_pointer_cast<const VideoContent> (i);
- if (vc && vc->video_frame_type() != VIDEO_FRAME_TYPE_2D) {
+ if (i->video && i->video->video_frame_type() != VIDEO_FRAME_TYPE_2D) {
++three_d;
}
}
diff --git a/src/wx/timeline.cc b/src/wx/timeline.cc
index 56af6f771..f9fd16578 100644
--- a/src/wx/timeline.cc
+++ b/src/wx/timeline.cc
@@ -149,8 +149,7 @@ Timeline::recreate_views ()
_views.push_back (shared_ptr<TimelineView> (new TimelineVideoContentView (*this, i)));
}
- shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> (i);
- if (ac && !ac->audio_mapping().mapped_output_channels().empty ()) {
+ if (i->audio && !i->audio->audio_mapping().mapped_output_channels().empty ()) {
_views.push_back (shared_ptr<TimelineView> (new TimelineAudioContentView (*this, i)));
}
diff --git a/src/wx/timing_panel.cc b/src/wx/timing_panel.cc
index 18a07add4..573d76f48 100644
--- a/src/wx/timing_panel.cc
+++ b/src/wx/timing_panel.cc
@@ -290,7 +290,7 @@ TimingPanel::film_content_changed (int property)
} else if (ac) {
checked_set (_video_frame_rate, raw_convert<string> (ac->audio->audio_video_frame_rate (), 5));
} else if (sc) {
- checked_set (_video_frame_rate, raw_convert<string> (sc->subtitle_video_frame_rate (), 5));
+ checked_set (_video_frame_rate, raw_convert<string> (sc->subtitle->subtitle_video_frame_rate (), 5));
}
_video_frame_rate->Enable (true);
} else {
@@ -403,16 +403,14 @@ void
TimingPanel::set_video_frame_rate ()
{
BOOST_FOREACH (shared_ptr<Content> i, _parent->selected ()) {
- shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (i);
- shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> (i);
shared_ptr<DCPSubtitleContent> dsc = dynamic_pointer_cast<DCPSubtitleContent> (i);
shared_ptr<TextSubtitleContent> tsc = dynamic_pointer_cast<TextSubtitleContent> (i);
double const fr = raw_convert<double> (wx_to_std (_video_frame_rate->GetValue ()));
- if (vc) {
- vc->set_video_frame_rate (fr);
- } else if (ac) {
+ if (i->video) {
+ i->video->set_video_frame_rate (fr);
+ } else if (i->audio) {
/* Audio but not video, i.e. SndfileContent */
- ac->set_audio_video_frame_rate (fr);
+ i->audio->set_audio_video_frame_rate (fr);
} else if (dsc) {
dsc->set_subtitle_video_frame_rate (fr);
} else if (tsc) {
diff --git a/src/wx/video_panel.cc b/src/wx/video_panel.cc
index b5bd27b24..8bdac0076 100644
--- a/src/wx/video_panel.cc
+++ b/src/wx/video_panel.cc
@@ -87,6 +87,7 @@ VideoPanel::VideoPanel (ContentPanel* p)
this,
new wxChoice (this, wxID_ANY),
VideoContentProperty::VIDEO_FRAME_TYPE,
+ &Content::video,
boost::mem_fn (&VideoContent::video_frame_type),
boost::mem_fn (&VideoContent::set_video_frame_type),
&caster<int, VideoFrameType>,
@@ -105,6 +106,7 @@ VideoPanel::VideoPanel (ContentPanel* p)
this,
new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1)),
VideoContentProperty::VIDEO_CROP,
+ &Content::video,
boost::mem_fn (&VideoContent::left_crop),
boost::mem_fn (&VideoContent::set_left_crop)
);
@@ -115,6 +117,7 @@ VideoPanel::VideoPanel (ContentPanel* p)
this,
new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1)),
VideoContentProperty::VIDEO_CROP,
+ &Content::video,
boost::mem_fn (&VideoContent::right_crop),
boost::mem_fn (&VideoContent::set_right_crop)
);
@@ -127,6 +130,7 @@ VideoPanel::VideoPanel (ContentPanel* p)
this,
new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1)),
VideoContentProperty::VIDEO_CROP,
+ &Content::video,
boost::mem_fn (&VideoContent::top_crop),
boost::mem_fn (&VideoContent::set_top_crop)
);
@@ -137,6 +141,7 @@ VideoPanel::VideoPanel (ContentPanel* p)
this,
new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1)),
VideoContentProperty::VIDEO_CROP,
+ &Content::video,
boost::mem_fn (&VideoContent::bottom_crop),
boost::mem_fn (&VideoContent::set_bottom_crop)
);
@@ -160,6 +165,7 @@ VideoPanel::VideoPanel (ContentPanel* p)
this,
new wxChoice (this, wxID_ANY),
VideoContentProperty::VIDEO_SCALE,
+ &Content::video,
boost::mem_fn (&VideoContent::scale),
boost::mem_fn (&VideoContent::set_scale),
&index_to_scale,