summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-04-29 14:46:27 +0100
committerCarl Hetherington <cth@carlh.net>2013-04-29 14:46:27 +0100
commit2cc2dc2aeaec62a4983991170fc5368e10d21748 (patch)
treefe7ac759c5c4bd8b08ad656298542affcdc2964e /src/lib
parentdbc43b6e3021e34875d7d5bba04abf7ad1fc8633 (diff)
parentfca4842c205bc2fa74af94955100ca873bffc5d0 (diff)
Merge branch '1.0' of /home/carl/git/dvdomatic into 1.0
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/audio_mapping.cc2
-rw-r--r--src/lib/config.cc9
-rw-r--r--src/lib/config.h11
-rw-r--r--src/lib/film.cc159
-rw-r--r--src/lib/film.h18
-rw-r--r--src/lib/imagemagick_content.cc3
-rw-r--r--src/lib/player.cc123
-rw-r--r--src/lib/playlist.cc140
-rw-r--r--src/lib/playlist.h26
-rw-r--r--src/lib/po/it_IT.po21
-rw-r--r--src/lib/sndfile_decoder.cc4
-rw-r--r--src/lib/sndfile_decoder.h3
12 files changed, 309 insertions, 210 deletions
diff --git a/src/lib/audio_mapping.cc b/src/lib/audio_mapping.cc
index 83c748f1a..7e28aa5c4 100644
--- a/src/lib/audio_mapping.cc
+++ b/src/lib/audio_mapping.cc
@@ -115,7 +115,7 @@ AudioMapping::set_from_xml (ContentList const & content, shared_ptr<const cxml::
continue;
}
- shared_ptr<const AudioContent> ac = dynamic_pointer_cast<AudioContent> (*j);
+ shared_ptr<const AudioContent> ac = dynamic_pointer_cast<const AudioContent> (*j);
assert (ac);
add (AudioMapping::Channel (ac, (*i)->number_child<int> ("ContentIndex")), static_cast<libdcp::Channel> ((*i)->number_child<int> ("DCP")));
diff --git a/src/lib/config.cc b/src/lib/config.cc
index e6f657a39..4f90581f6 100644
--- a/src/lib/config.cc
+++ b/src/lib/config.cc
@@ -37,6 +37,7 @@ using std::string;
using std::ofstream;
using std::list;
using boost::shared_ptr;
+using boost::lexical_cast;
using boost::optional;
Config* Config::_instance = 0;
@@ -48,6 +49,7 @@ Config::Config ()
, _reference_scaler (Scaler::from_id (N_("bicubic")))
, _tms_path (N_("."))
, _sound_processor (SoundProcessor::from_id (N_("dolby_cp750")))
+ , _default_still_length (10)
{
_allowed_dcp_frame_rates.push_back (24);
_allowed_dcp_frame_rates.push_back (25);
@@ -94,6 +96,7 @@ Config::Config ()
_language = f.optional_string_child ("Language");
_default_dci_metadata = DCIMetadata (f.node_child ("DCIMetadata"));
+ _default_still_length = f.optional_number_child<int>("DefaultStillLength").get_value_or (10);
}
void
@@ -180,9 +183,9 @@ Config::write () const
xmlpp::Document doc;
xmlpp::Element* root = doc.create_root_node ("Config");
- root->add_child("NumLocalEncodingThreads")->add_child_text (boost::lexical_cast<string> (_num_local_encoding_threads));
+ root->add_child("NumLocalEncodingThreads")->add_child_text (lexical_cast<string> (_num_local_encoding_threads));
root->add_child("DefaultDirectory")->add_child_text (_default_directory);
- root->add_child("ServerPort")->add_child_text (boost::lexical_cast<string> (_server_port));
+ root->add_child("ServerPort")->add_child_text (lexical_cast<string> (_server_port));
if (_reference_scaler) {
root->add_child("ReferenceScaler")->add_child_text (_reference_scaler->id ());
}
@@ -208,6 +211,8 @@ Config::write () const
_default_dci_metadata.as_xml (root->add_child ("DCIMetadata"));
+ root->add_child("DefaultStillLength")->add_child_text (lexical_cast<string> (_default_still_length));
+
doc.write_to_file_formatted (file (false));
}
diff --git a/src/lib/config.h b/src/lib/config.h
index 57f4fb8a9..91926750b 100644
--- a/src/lib/config.h
+++ b/src/lib/config.h
@@ -107,6 +107,10 @@ public:
return _language;
}
+ int default_still_length () const {
+ return _default_still_length;
+ }
+
/** @param n New number of local encoding threads */
void set_num_local_encoding_threads (int n) {
_num_local_encoding_threads = n;
@@ -169,7 +173,11 @@ public:
void unset_language () {
_language = boost::none;
}
-
+
+ void set_default_still_length (int s) {
+ _default_still_length = s;
+ }
+
void write () const;
static Config* instance ();
@@ -207,6 +215,7 @@ private:
/** Default DCI metadata for newly-created Films */
DCIMetadata _default_dci_metadata;
boost::optional<std::string> _language;
+ int _default_still_length;
/** Singleton instance, or 0 */
static Config* _instance;
diff --git a/src/lib/film.cc b/src/lib/film.cc
index 98c6c0610..5481bd012 100644
--- a/src/lib/film.cc
+++ b/src/lib/film.cc
@@ -113,7 +113,8 @@ Film::Film (string d, bool must_exist)
{
set_dci_date_today ();
- _playlist->ContentChanged.connect (bind (&Film::content_changed, this, _1, _2));
+ _playlist->Changed.connect (bind (&Film::playlist_changed, this));
+ _playlist->ContentChanged.connect (bind (&Film::playlist_content_changed, this, _1, _2));
/* Make state.directory a complete path without ..s (where possible)
(Code swiped from Adam Bowen on stackoverflow)
@@ -156,7 +157,7 @@ Film::Film (Film const & o)
: boost::enable_shared_from_this<Film> (o)
/* note: the copied film shares the original's log */
, _log (o._log)
- , _playlist (new Playlist)
+ , _playlist (new Playlist (o._playlist))
, _directory (o._directory)
, _name (o._name)
, _use_dci_name (o._use_dci_name)
@@ -182,13 +183,7 @@ Film::Film (Film const & o)
, _dci_date (o._dci_date)
, _dirty (o._dirty)
{
- for (ContentList::const_iterator i = o._content.begin(); i != o._content.end(); ++i) {
- _content.push_back ((*i)->clone ());
- }
-
- _playlist->ContentChanged.connect (bind (&Film::content_changed, this, _1, _2));
-
- _playlist->setup (_content);
+ _playlist->ContentChanged.connect (bind (&Film::playlist_content_changed, this, _1, _2));
}
string
@@ -320,7 +315,7 @@ Film::make_dcp ()
throw MissingSettingError (_("format"));
}
- if (content().empty ()) {
+ if (_playlist->content().empty ()) {
throw MissingSettingError (_("content"));
}
@@ -405,8 +400,6 @@ Film::encoded_frames () const
void
Film::write_metadata () const
{
- ContentList the_content = content ();
-
boost::mutex::scoped_lock lm (_state_mutex);
LocaleGuard lg;
@@ -460,10 +453,7 @@ Film::write_metadata () const
root->add_child("DCPFrameRate")->add_child_text (boost::lexical_cast<string> (_dcp_frame_rate));
root->add_child("DCIDate")->add_child_text (boost::gregorian::to_iso_string (_dci_date));
_audio_mapping.as_xml (root->add_child("AudioMapping"));
-
- for (ContentList::iterator i = the_content.begin(); i != the_content.end(); ++i) {
- (*i)->as_xml (root->add_child ("Content"));
- }
+ _playlist->as_xml (root->add_child ("Playlist"));
doc.write_to_file_formatted (file ("metadata.xml"));
@@ -537,29 +527,10 @@ Film::read_metadata ()
_dcp_frame_rate = f.number_child<int> ("DCPFrameRate");
_dci_date = boost::gregorian::from_undelimited_string (f.string_child ("DCIDate"));
- list<shared_ptr<cxml::Node> > c = f.node_children ("Content");
- for (list<shared_ptr<cxml::Node> >::iterator i = c.begin(); i != c.end(); ++i) {
-
- string const type = (*i)->string_child ("Type");
- boost::shared_ptr<Content> c;
-
- if (type == "FFmpeg") {
- c.reset (new FFmpegContent (*i));
- } else if (type == "ImageMagick") {
- c.reset (new ImageMagickContent (*i));
- } else if (type == "Sndfile") {
- c.reset (new SndfileContent (*i));
- }
-
- _content.push_back (c);
- }
-
- /* This must come after we've loaded the content, as we're looking things up in _content */
- _audio_mapping.set_from_xml (_content, f.node_child ("AudioMapping"));
+ _playlist->set_from_xml (f.node_child ("Playlist"));
+ _audio_mapping.set_from_xml (_playlist->content(), f.node_child ("AudioMapping"));
_dirty = false;
-
- _playlist->setup (_content);
}
libdcp::Size
@@ -766,10 +737,11 @@ Film::set_trust_content_headers (bool t)
signal_changed (TRUST_CONTENT_HEADERS);
- if (!_trust_content_headers && !content().empty()) {
+
+ ContentList content = _playlist->content ();
+ if (!_trust_content_headers && !content.empty()) {
/* We just said that we don't trust the content's header */
- ContentList c = content ();
- for (ContentList::iterator i = c.begin(); i != c.end(); ++i) {
+ for (ContentList::iterator i = content.begin(); i != content.end(); ++i) {
examine_content (*i);
}
}
@@ -1023,7 +995,6 @@ Film::signal_changed (Property p)
switch (p) {
case Film::CONTENT:
- _playlist->setup (content ());
set_dcp_frame_rate (best_dcp_frame_rate (video_frame_rate ()));
set_audio_mapping (_playlist->default_audio_mapping ());
break;
@@ -1104,73 +1075,35 @@ Film::player () const
return shared_ptr<Player> (new Player (shared_from_this (), _playlist));
}
+ContentList
+Film::content () const
+{
+ return _playlist->content ();
+}
+
void
Film::add_content (shared_ptr<Content> c)
{
- {
- boost::mutex::scoped_lock lm (_state_mutex);
- _content.push_back (c);
- }
-
- signal_changed (CONTENT);
-
+ _playlist->add (c);
examine_content (c);
}
void
Film::remove_content (shared_ptr<Content> c)
{
- {
- boost::mutex::scoped_lock lm (_state_mutex);
- ContentList::iterator i = find (_content.begin(), _content.end(), c);
- if (i != _content.end ()) {
- _content.erase (i);
- }
- }
-
- signal_changed (CONTENT);
+ _playlist->remove (c);
}
void
Film::move_content_earlier (shared_ptr<Content> c)
{
- {
- boost::mutex::scoped_lock lm (_state_mutex);
- ContentList::iterator i = find (_content.begin(), _content.end(), c);
- if (i == _content.begin () || i == _content.end()) {
- return;
- }
-
- ContentList::iterator j = i;
- --j;
-
- swap (*i, *j);
- }
-
- signal_changed (CONTENT);
+ _playlist->move_earlier (c);
}
void
Film::move_content_later (shared_ptr<Content> c)
{
- {
- boost::mutex::scoped_lock lm (_state_mutex);
- ContentList::iterator i = find (_content.begin(), _content.end(), c);
- if (i == _content.end()) {
- return;
- }
-
- ContentList::iterator j = i;
- ++j;
- if (j == _content.end ()) {
- return;
- }
-
- swap (*i, *j);
- }
-
- signal_changed (CONTENT);
-
+ _playlist->move_later (c);
}
ContentAudioFrame
@@ -1221,26 +1154,10 @@ Film::content_length () const
return _playlist->content_length ();
}
-/** Unfortunately this is needed as the GUI has FFmpeg-specific controls */
-shared_ptr<FFmpegContent>
-Film::ffmpeg () const
-{
- boost::mutex::scoped_lock lm (_state_mutex);
-
- for (ContentList::const_iterator i = _content.begin (); i != _content.end(); ++i) {
- shared_ptr<FFmpegContent> f = boost::dynamic_pointer_cast<FFmpegContent> (*i);
- if (f) {
- return f;
- }
- }
-
- return shared_ptr<FFmpegContent> ();
-}
-
vector<FFmpegSubtitleStream>
Film::ffmpeg_subtitle_streams () const
{
- shared_ptr<FFmpegContent> f = ffmpeg ();
+ shared_ptr<FFmpegContent> f = _playlist->ffmpeg ();
if (f) {
return f->subtitle_streams ();
}
@@ -1251,7 +1168,7 @@ Film::ffmpeg_subtitle_streams () const
boost::optional<FFmpegSubtitleStream>
Film::ffmpeg_subtitle_stream () const
{
- shared_ptr<FFmpegContent> f = ffmpeg ();
+ shared_ptr<FFmpegContent> f = _playlist->ffmpeg ();
if (f) {
return f->subtitle_stream ();
}
@@ -1262,7 +1179,7 @@ Film::ffmpeg_subtitle_stream () const
vector<FFmpegAudioStream>
Film::ffmpeg_audio_streams () const
{
- shared_ptr<FFmpegContent> f = ffmpeg ();
+ shared_ptr<FFmpegContent> f = _playlist->ffmpeg ();
if (f) {
return f->audio_streams ();
}
@@ -1273,7 +1190,7 @@ Film::ffmpeg_audio_streams () const
boost::optional<FFmpegAudioStream>
Film::ffmpeg_audio_stream () const
{
- shared_ptr<FFmpegContent> f = ffmpeg ();
+ shared_ptr<FFmpegContent> f = _playlist->ffmpeg ();
if (f) {
return f->audio_stream ();
}
@@ -1284,7 +1201,7 @@ Film::ffmpeg_audio_stream () const
void
Film::set_ffmpeg_subtitle_stream (FFmpegSubtitleStream s)
{
- shared_ptr<FFmpegContent> f = ffmpeg ();
+ shared_ptr<FFmpegContent> f = _playlist->ffmpeg ();
if (f) {
f->set_subtitle_stream (s);
}
@@ -1293,7 +1210,7 @@ Film::set_ffmpeg_subtitle_stream (FFmpegSubtitleStream s)
void
Film::set_ffmpeg_audio_stream (FFmpegAudioStream s)
{
- shared_ptr<FFmpegContent> f = ffmpeg ();
+ shared_ptr<FFmpegContent> f = _playlist->ffmpeg ();
if (f) {
f->set_audio_stream (s);
}
@@ -1311,7 +1228,7 @@ Film::set_audio_mapping (AudioMapping m)
}
void
-Film::content_changed (boost::weak_ptr<Content> c, int p)
+Film::playlist_content_changed (boost::weak_ptr<Content> c, int p)
{
if (p == VideoContentProperty::VIDEO_FRAME_RATE) {
set_dcp_frame_rate (best_dcp_frame_rate (video_frame_rate ()));
@@ -1323,3 +1240,21 @@ Film::content_changed (boost::weak_ptr<Content> c, int p)
ui_signaller->emit (boost::bind (boost::ref (ContentChanged), c, p));
}
}
+
+void
+Film::playlist_changed ()
+{
+ signal_changed (CONTENT);
+}
+
+int
+Film::loop () const
+{
+ return _playlist->loop ();
+}
+
+void
+Film::set_loop (int c)
+{
+ _playlist->set_loop (c);
+}
diff --git a/src/lib/film.h b/src/lib/film.h
index 43b5d1a17..f4d7cde67 100644
--- a/src/lib/film.h
+++ b/src/lib/film.h
@@ -106,6 +106,8 @@ public:
/* Proxies for some Playlist methods */
+ ContentList content () const;
+
ContentAudioFrame audio_length () const;
int audio_channels () const;
int audio_frame_rate () const;
@@ -125,6 +127,9 @@ public:
void set_ffmpeg_subtitle_stream (FFmpegSubtitleStream);
void set_ffmpeg_audio_stream (FFmpegAudioStream);
+ void set_loop (int);
+ int loop () const;
+
enum TrimType {
CPL,
ENCODE
@@ -138,8 +143,9 @@ public:
NAME,
USE_DCI_NAME,
TRUST_CONTENT_HEADERS,
- /** The content list has changed (i.e. content has been added, moved around or removed) */
+ /** The playlist's content list has changed (i.e. content has been added, moved around or removed) */
CONTENT,
+ LOOP,
DCP_CONTENT_TYPE,
FORMAT,
CROP,
@@ -184,11 +190,6 @@ public:
return _trust_content_headers;
}
- ContentList content () const {
- boost::mutex::scoped_lock lm (_state_mutex);
- return _content;
- }
-
DCPContentType const * dcp_content_type () const {
boost::mutex::scoped_lock lm (_state_mutex);
return _dcp_content_type;
@@ -336,8 +337,8 @@ private:
void analyse_audio_finished ();
std::string video_state_identifier () const;
void read_metadata ();
- void content_changed (boost::weak_ptr<Content>, int);
- boost::shared_ptr<FFmpegContent> ffmpeg () const;
+ void playlist_changed ();
+ void playlist_content_changed (boost::weak_ptr<Content>, int);
void setup_default_audio_mapping ();
std::string filename_safe_name () const;
@@ -359,7 +360,6 @@ private:
/** True if a auto-generated DCI-compliant name should be used for our DCP */
bool _use_dci_name;
bool _trust_content_headers;
- ContentList _content;
/** The type of content that this Film represents (feature, trailer etc.) */
DCPContentType const * _dcp_content_type;
/** The format to present this Film in (flat, scope, etc.) */
diff --git a/src/lib/imagemagick_content.cc b/src/lib/imagemagick_content.cc
index 24f6d338d..9e5f00ba0 100644
--- a/src/lib/imagemagick_content.cc
+++ b/src/lib/imagemagick_content.cc
@@ -20,6 +20,7 @@
#include <libcxml/cxml.h>
#include "imagemagick_content.h"
#include "imagemagick_decoder.h"
+#include "config.h"
#include "compose.hpp"
#include "i18n.h"
@@ -73,7 +74,7 @@ ImageMagickContent::examine (shared_ptr<Film> film, shared_ptr<Job> job, bool qu
{
boost::mutex::scoped_lock lm (_mutex);
/* Initial length */
- _video_length = 10 * 24;
+ _video_length = Config::instance()->default_still_length() * 24;
}
take_from_video_decoder (decoder);
diff --git a/src/lib/player.cc b/src/lib/player.cc
index 09f1f55a3..a3d52f43e 100644
--- a/src/lib/player.cc
+++ b/src/lib/player.cc
@@ -229,67 +229,69 @@ Player::setup_decoders ()
double video_so_far = 0;
double audio_so_far = 0;
-
- list<shared_ptr<const VideoContent> > vc = _playlist->video ();
- for (list<shared_ptr<const VideoContent> >::iterator i = vc.begin(); i != vc.end(); ++i) {
-
- shared_ptr<const VideoContent> video_content;
- shared_ptr<const AudioContent> audio_content;
- shared_ptr<VideoDecoder> video_decoder;
- shared_ptr<AudioDecoder> audio_decoder;
-
- /* XXX: into content? */
-
- shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
- if (fc) {
- shared_ptr<FFmpegDecoder> fd (
- new FFmpegDecoder (
- _film, fc, _video,
- _audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG,
- _subtitles
- )
- );
+
+ for (int l = 0; l < _playlist->loop(); ++l) {
+ list<shared_ptr<const VideoContent> > vc = _playlist->video ();
+ for (list<shared_ptr<const VideoContent> >::iterator i = vc.begin(); i != vc.end(); ++i) {
- video_content = fc;
- audio_content = fc;
- video_decoder = fd;
- audio_decoder = fd;
- }
-
- shared_ptr<const ImageMagickContent> ic = dynamic_pointer_cast<const ImageMagickContent> (*i);
- if (ic) {
- video_content = ic;
- video_decoder.reset (new ImageMagickDecoder (_film, ic));
+ shared_ptr<const VideoContent> video_content;
+ shared_ptr<const AudioContent> audio_content;
+ shared_ptr<VideoDecoder> video_decoder;
+ shared_ptr<AudioDecoder> audio_decoder;
+
+ /* XXX: into content? */
+
+ shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
+ if (fc) {
+ shared_ptr<FFmpegDecoder> fd (
+ new FFmpegDecoder (
+ _film, fc, _video,
+ _audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG,
+ _subtitles
+ )
+ );
+
+ video_content = fc;
+ audio_content = fc;
+ video_decoder = fd;
+ audio_decoder = fd;
+ }
+
+ shared_ptr<const ImageMagickContent> ic = dynamic_pointer_cast<const ImageMagickContent> (*i);
+ if (ic) {
+ video_content = ic;
+ video_decoder.reset (new ImageMagickDecoder (_film, ic));
+ }
+
+ video_decoder->connect_video (shared_from_this ());
+ _video_decoders.push_back (video_decoder);
+ _video_start.push_back (video_so_far);
+ video_so_far += video_content->video_length() / video_content->video_frame_rate();
+
+ if (audio_decoder && _playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
+ audio_decoder->Audio.connect (bind (&Player::process_audio, this, audio_content, _1, _2));
+ _audio_decoders.push_back (audio_decoder);
+ _audio_start.push_back (audio_so_far);
+ audio_so_far += double(audio_content->audio_length()) / audio_content->audio_frame_rate();
+ }
}
- video_decoder->connect_video (shared_from_this ());
- _video_decoders.push_back (video_decoder);
- _video_start.push_back (video_so_far);
- video_so_far += video_content->video_length() / video_content->video_frame_rate();
-
- if (audio_decoder && _playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
- audio_decoder->Audio.connect (bind (&Player::process_audio, this, audio_content, _1, _2));
- _audio_decoders.push_back (audio_decoder);
- _audio_start.push_back (audio_so_far);
- audio_so_far += double(audio_content->audio_length()) / audio_content->audio_frame_rate();
- }
- }
-
- _video_decoder = 0;
- _sequential_audio_decoder = 0;
-
- if (_playlist->audio_from() == Playlist::AUDIO_SNDFILE) {
+ _video_decoder = 0;
+ _sequential_audio_decoder = 0;
- list<shared_ptr<const AudioContent> > ac = _playlist->audio ();
- for (list<shared_ptr<const AudioContent> >::iterator i = ac.begin(); i != ac.end(); ++i) {
-
- shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
- assert (sc);
+ if (_playlist->audio_from() == Playlist::AUDIO_SNDFILE) {
- shared_ptr<AudioDecoder> d (new SndfileDecoder (_film, sc));
- d->Audio.connect (bind (&Player::process_audio, this, sc, _1, _2));
- _audio_decoders.push_back (d);
- _audio_start.push_back (audio_so_far);
+ list<shared_ptr<const AudioContent> > ac = _playlist->audio ();
+ for (list<shared_ptr<const AudioContent> >::iterator i = ac.begin(); i != ac.end(); ++i) {
+
+ shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
+ assert (sc);
+
+ shared_ptr<AudioDecoder> d (new SndfileDecoder (_film, sc));
+ d->Audio.connect (bind (&Player::process_audio, this, sc, _1, _2));
+ _audio_decoders.push_back (d);
+ _audio_start.push_back (audio_so_far);
+ }
}
}
}
@@ -297,6 +299,10 @@ Player::setup_decoders ()
double
Player::last_video_time () const
{
+ if (_video_decoder >= _video_decoders.size ()) {
+ return 0;
+ }
+
return _video_start[_video_decoder] + _video_decoders[_video_decoder]->last_content_time ();
}
@@ -309,10 +315,7 @@ Player::content_changed (weak_ptr<Content> w, int p)
}
if (p == VideoContentProperty::VIDEO_LENGTH) {
- if (dynamic_pointer_cast<FFmpegContent> (c)) {
- /* FFmpeg content length changes are serious; we need new decoders */
- _have_valid_decoders = false;
- }
+ _have_valid_decoders = false;
}
}
diff --git a/src/lib/playlist.cc b/src/lib/playlist.cc
index 3c69ae15f..72745f220 100644
--- a/src/lib/playlist.cc
+++ b/src/lib/playlist.cc
@@ -17,6 +17,7 @@
*/
+#include <libcxml/cxml.h>
#include <boost/shared_ptr.hpp>
#include <boost/lexical_cast.hpp>
#include "playlist.h"
@@ -26,6 +27,7 @@
#include "ffmpeg_decoder.h"
#include "ffmpeg_content.h"
#include "imagemagick_decoder.h"
+#include "imagemagick_content.h"
#include "job.h"
using std::list;
@@ -41,12 +43,24 @@ using boost::lexical_cast;
Playlist::Playlist ()
: _audio_from (AUDIO_FFMPEG)
+ , _loop (1)
{
}
+Playlist::Playlist (shared_ptr<const Playlist> other)
+ : _audio_from (other->_audio_from)
+ , _loop (other->_loop)
+{
+ for (ContentList::const_iterator i = other->_content.begin(); i != other->_content.end(); ++i) {
+ _content.push_back ((*i)->clone ());
+ }
+
+ setup ();
+}
+
void
-Playlist::setup (ContentList content)
+Playlist::setup ()
{
_audio_from = AUDIO_FFMPEG;
@@ -59,7 +73,7 @@ Playlist::setup (ContentList content)
_content_connections.clear ();
- for (ContentList::const_iterator i = content.begin(); i != content.end(); ++i) {
+ for (ContentList::const_iterator i = _content.begin(); i != _content.end(); ++i) {
/* Video is video */
shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (*i);
@@ -89,8 +103,6 @@ Playlist::setup (ContentList content)
_content_connections.push_back ((*i)->Changed.connect (bind (&Playlist::content_changed, this, _1, _2)));
}
-
- Changed ();
}
/** @return Length of our audio */
@@ -114,7 +126,7 @@ Playlist::audio_length () const
break;
}
- return len;
+ return len * _loop;
}
/** @return number of audio channels */
@@ -182,7 +194,7 @@ Playlist::video_length () const
len += (*i)->video_length ();
}
- return len;
+ return len * _loop;
}
bool
@@ -258,6 +270,8 @@ Playlist::audio_digest () const
}
}
+ t += lexical_cast<string> (_loop);
+
return md5_digest (t.c_str(), t.length());
}
@@ -274,6 +288,8 @@ Playlist::video_digest () const
}
}
+ t += lexical_cast<string> (_loop);
+
return md5_digest (t.c_str(), t.length());
}
@@ -288,3 +304,115 @@ Playlist::content_length () const
ContentVideoFrame (audio_length() * vfr / afr)
);
}
+
+void
+Playlist::set_from_xml (shared_ptr<const cxml::Node> node)
+{
+ list<shared_ptr<cxml::Node> > c = node->node_children ("Content");
+ for (list<shared_ptr<cxml::Node> >::iterator i = c.begin(); i != c.end(); ++i) {
+
+ string const type = (*i)->string_child ("Type");
+ boost::shared_ptr<Content> c;
+
+ if (type == "FFmpeg") {
+ c.reset (new FFmpegContent (*i));
+ } else if (type == "ImageMagick") {
+ c.reset (new ImageMagickContent (*i));
+ } else if (type == "Sndfile") {
+ c.reset (new SndfileContent (*i));
+ }
+
+ _content.push_back (c);
+ }
+
+ _loop = node->number_child<int> ("Loop");
+
+ setup ();
+}
+
+void
+Playlist::as_xml (xmlpp::Node* node)
+{
+ for (ContentList::iterator i = _content.begin(); i != _content.end(); ++i) {
+ (*i)->as_xml (node->add_child ("Content"));
+ }
+
+ node->add_child("Loop")->add_child_text(lexical_cast<string> (_loop));
+}
+
+void
+Playlist::add (shared_ptr<Content> c)
+{
+ _content.push_back (c);
+ setup ();
+ Changed ();
+}
+
+void
+Playlist::remove (shared_ptr<Content> c)
+{
+ ContentList::iterator i = find (_content.begin(), _content.end(), c);
+ if (i != _content.end ()) {
+ _content.erase (i);
+ }
+
+ setup ();
+ Changed ();
+}
+
+void
+Playlist::move_earlier (shared_ptr<Content> c)
+{
+ ContentList::iterator i = find (_content.begin(), _content.end(), c);
+ if (i == _content.begin () || i == _content.end()) {
+ return;
+ }
+
+ ContentList::iterator j = i;
+ --j;
+
+ swap (*i, *j);
+
+ setup ();
+ Changed ();
+}
+
+void
+Playlist::move_later (shared_ptr<Content> c)
+{
+ ContentList::iterator i = find (_content.begin(), _content.end(), c);
+ if (i == _content.end()) {
+ return;
+ }
+
+ ContentList::iterator j = i;
+ ++j;
+ if (j == _content.end ()) {
+ return;
+ }
+
+ swap (*i, *j);
+
+ setup ();
+ Changed ();
+}
+
+void
+Playlist::set_loop (int l)
+{
+ _loop = l;
+ Changed ();
+}
+
+shared_ptr<FFmpegContent>
+Playlist::ffmpeg () const
+{
+ for (ContentList::const_iterator i = _content.begin(); i != _content.end(); ++i) {
+ shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (*i);
+ if (fc) {
+ return fc;
+ }
+ }
+
+ return shared_ptr<FFmpegContent> ();
+}
diff --git a/src/lib/playlist.h b/src/lib/playlist.h
index 85bde64ff..935bbb2bd 100644
--- a/src/lib/playlist.h
+++ b/src/lib/playlist.h
@@ -51,8 +51,15 @@ class Playlist
{
public:
Playlist ();
+ Playlist (boost::shared_ptr<const Playlist>);
- void setup (ContentList);
+ void as_xml (xmlpp::Node *);
+ void set_from_xml (boost::shared_ptr<const cxml::Node>);
+
+ void add (boost::shared_ptr<Content>);
+ void remove (boost::shared_ptr<Content>);
+ void move_earlier (boost::shared_ptr<Content>);
+ void move_later (boost::shared_ptr<Content>);
ContentAudioFrame audio_length () const;
int audio_channels () const;
@@ -75,6 +82,12 @@ public:
return _audio_from;
}
+ ContentList content () const {
+ return _content;
+ }
+
+ boost::shared_ptr<FFmpegContent> ffmpeg () const;
+
std::list<boost::shared_ptr<const VideoContent> > video () const {
return _video;
}
@@ -86,15 +99,24 @@ public:
std::string audio_digest () const;
std::string video_digest () const;
+ int loop () const {
+ return _loop;
+ }
+
+ void set_loop (int l);
+
mutable boost::signals2::signal<void ()> Changed;
mutable boost::signals2::signal<void (boost::weak_ptr<Content>, int)> ContentChanged;
private:
+ void setup ();
void content_changed (boost::weak_ptr<Content>, int);
/** where we should get our audio from */
AudioFrom _audio_from;
+ /** all our content */
+ ContentList _content;
/** all our content which contains video */
std::list<boost::shared_ptr<const VideoContent> > _video;
/** all our content which contains audio. This may contain the same objects
@@ -102,5 +124,7 @@ private:
*/
std::list<boost::shared_ptr<const AudioContent> > _audio;
+ int _loop;
+
std::list<boost::signals2::connection> _content_connections;
};
diff --git a/src/lib/po/it_IT.po b/src/lib/po/it_IT.po
index 1d7f57536..bd22412fc 100644
--- a/src/lib/po/it_IT.po
+++ b/src/lib/po/it_IT.po
@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: IT VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-04-22 15:06+0100\n"
-"PO-Revision-Date: 2013-04-03 15:04+0100\n"
+"PO-Revision-Date: 2013-04-28 10:26+0100\n"
"Last-Translator: Maci <macibro@gmail.com>\n"
"Language-Team: \n"
"Language: Italiano\n"
@@ -46,9 +46,8 @@ msgid "16:9 within Flat"
msgstr "16:9 all'interno di Flat"
#: src/lib/format.cc:115
-#, fuzzy
msgid "16:9 within Scope"
-msgstr "16:9 all'interno di Flat"
+msgstr "16:9 all'interno di Scope"
#: src/lib/filter.cc:88
msgid "3D denoiser"
@@ -56,7 +55,7 @@ msgstr "Riduttore di rumore 3D"
#: src/lib/format.cc:79
msgid "4:3"
-msgstr ""
+msgstr "4:3"
#: src/lib/format.cc:87
msgid "4:3 within Flat"
@@ -183,7 +182,7 @@ msgstr "Esamino il contenuto"
#: src/lib/examine_content_job.cc:58
msgid "Examine content of %1"
-msgstr "Esamo il contenuto di %1"
+msgstr "Esamino il contenuto di %1"
#: src/lib/filter.cc:72
msgid "Experimental horizontal deblocking filter 1"
@@ -301,7 +300,7 @@ msgstr "Riduzione del rumore"
#: src/lib/job.cc:302
msgid "OK (ran for %1)"
-msgstr "OK (procede al %1)"
+msgstr "OK (eseguito in %1)"
#: src/lib/filter.cc:91
msgid "Overcomplete wavelet denoiser"
@@ -473,7 +472,7 @@ msgstr "non riesco ad aprire il file dell'audio esterno per leggerlo"
#: src/lib/exceptions.cc:29
msgid "could not open file %1"
-msgstr "non riesco ad aprire il file per leggerlo"
+msgstr "non riesco ad aprire %1"
#: src/lib/dcp_video_frame.cc:388
msgid "could not open file for reading"
@@ -481,11 +480,11 @@ msgstr "non riesco ad aprire il file per leggerlo"
#: src/lib/exceptions.cc:44
msgid "could not read from file %1 (%2)"
-msgstr "Non posso creare la directory remota %1 (%2)"
+msgstr "non posso leggere dal file %1 (%2)"
#: src/lib/encoder.cc:137 src/lib/encoder.cc:314
msgid "could not run sample-rate converter"
-msgstr "non riesco a lanciare il convertitore della frequenza di campionamento"
+msgstr "non riesco a eseguire il convertitore della frequenza di campionamento"
#: src/lib/scp_dcp_job.cc:86
msgid "could not start SCP session (%1)"
@@ -497,7 +496,7 @@ msgstr "non posso avviare la sessione SSH"
#: src/lib/exceptions.cc:50
msgid "could not write to file %1 (%2)"
-msgstr "Non posso scrivere il file remoto (%1)"
+msgstr "non posso scrivere il file (%1)"
#: src/lib/sndfile_decoder.cc:94
msgid "external audio files have differing lengths"
@@ -549,7 +548,7 @@ msgstr "nome"
#: src/lib/imagemagick_decoder.cc:60
msgid "no still image files found"
-msgstr "file del fermo immagine non trovati"
+msgstr "file immagini statiche non trovati"
#: src/lib/subtitle.cc:58
msgid "non-bitmap subtitles not yet supported"
diff --git a/src/lib/sndfile_decoder.cc b/src/lib/sndfile_decoder.cc
index 4db45f1d4..9ba972e56 100644
--- a/src/lib/sndfile_decoder.cc
+++ b/src/lib/sndfile_decoder.cc
@@ -48,9 +48,7 @@ SndfileDecoder::SndfileDecoder (shared_ptr<const Film> f, shared_ptr<const Sndfi
SndfileDecoder::~SndfileDecoder ()
{
- if (_sndfile) {
- sf_close (_sndfile);
- }
+ sf_close (_sndfile);
}
bool
diff --git a/src/lib/sndfile_decoder.h b/src/lib/sndfile_decoder.h
index b999a66d1..1d212cc9b 100644
--- a/src/lib/sndfile_decoder.h
+++ b/src/lib/sndfile_decoder.h
@@ -36,9 +36,6 @@ public:
int audio_frame_rate () const;
private:
- SNDFILE* open_file (sf_count_t &);
- void close_file (SNDFILE*);
-
boost::shared_ptr<const SndfileContent> _sndfile_content;
SNDFILE* _sndfile;
SF_INFO _info;