diff options
| author | Carl Hetherington <cth@carlh.net> | 2013-04-29 14:46:27 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2013-04-29 14:46:27 +0100 |
| commit | 2cc2dc2aeaec62a4983991170fc5368e10d21748 (patch) | |
| tree | fe7ac759c5c4bd8b08ad656298542affcdc2964e /src | |
| parent | dbc43b6e3021e34875d7d5bba04abf7ad1fc8633 (diff) | |
| parent | fca4842c205bc2fa74af94955100ca873bffc5d0 (diff) | |
Merge branch '1.0' of /home/carl/git/dvdomatic into 1.0
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/audio_mapping.cc | 2 | ||||
| -rw-r--r-- | src/lib/config.cc | 9 | ||||
| -rw-r--r-- | src/lib/config.h | 11 | ||||
| -rw-r--r-- | src/lib/film.cc | 159 | ||||
| -rw-r--r-- | src/lib/film.h | 18 | ||||
| -rw-r--r-- | src/lib/imagemagick_content.cc | 3 | ||||
| -rw-r--r-- | src/lib/player.cc | 123 | ||||
| -rw-r--r-- | src/lib/playlist.cc | 140 | ||||
| -rw-r--r-- | src/lib/playlist.h | 26 | ||||
| -rw-r--r-- | src/lib/po/it_IT.po | 21 | ||||
| -rw-r--r-- | src/lib/sndfile_decoder.cc | 4 | ||||
| -rw-r--r-- | src/lib/sndfile_decoder.h | 3 | ||||
| -rw-r--r-- | src/tools/po/it_IT.po | 2 | ||||
| -rw-r--r-- | src/wx/config_dialog.cc | 263 | ||||
| -rw-r--r-- | src/wx/config_dialog.h | 13 | ||||
| -rw-r--r-- | src/wx/film_editor.cc | 64 | ||||
| -rw-r--r-- | src/wx/film_editor.h | 5 | ||||
| -rw-r--r-- | src/wx/po/it_IT.po | 27 |
18 files changed, 566 insertions, 327 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; diff --git a/src/tools/po/it_IT.po b/src/tools/po/it_IT.po index 13732129b..b4c1a6e66 100644 --- a/src/tools/po/it_IT.po +++ b/src/tools/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 13:00+0100\n" +"PO-Revision-Date: 2013-04-28 10:31+0100\n" "Last-Translator: Maci <macibro@gmail.com>\n" "Language-Team: \n" "Language: Italiano\n" diff --git a/src/wx/config_dialog.cc b/src/wx/config_dialog.cc index c3eebc015..e1fc7a20f 100644 --- a/src/wx/config_dialog.cc +++ b/src/wx/config_dialog.cc @@ -25,6 +25,7 @@ #include <boost/lexical_cast.hpp> #include <boost/filesystem.hpp> #include <wx/stdpaths.h> +#include <wx/notebook.h> #include "lib/config.h" #include "lib/server.h" #include "lib/format.h" @@ -43,12 +44,46 @@ using boost::bind; ConfigDialog::ConfigDialog (wxWindow* parent) : wxDialog (parent, wxID_ANY, _("DCP-o-matic Preferences"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { + wxBoxSizer* s = new wxBoxSizer (wxVERTICAL); + _notebook = new wxNotebook (this, wxID_ANY); + s->Add (_notebook, 1); + + make_misc_panel (); + _notebook->AddPage (_misc_panel, _("Miscellaneous"), true); + make_servers_panel (); + _notebook->AddPage (_servers_panel, _("Encoding servers"), false); + make_tms_panel (); + _notebook->AddPage (_tms_panel, _("TMS"), false); + make_ab_panel (); + _notebook->AddPage (_ab_panel, _("A/B mode"), false); + + wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL); + overall_sizer->Add (s, 1, wxEXPAND | wxALL, 6); + + wxSizer* buttons = CreateSeparatedButtonSizer (wxOK); + if (buttons) { + overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder()); + } + + SetSizer (overall_sizer); + overall_sizer->Layout (); + overall_sizer->SetSizeHints (this); +} + +void +ConfigDialog::make_misc_panel () +{ + _misc_panel = new wxPanel (_notebook); + wxBoxSizer* s = new wxBoxSizer (wxVERTICAL); + _misc_panel->SetSizer (s); + wxFlexGridSizer* table = new wxFlexGridSizer (3, 6, 6); table->AddGrowableCol (1, 1); + s->Add (table, 1, wxALL | wxEXPAND, 8); - _set_language = new wxCheckBox (this, wxID_ANY, _("Set language")); + _set_language = new wxCheckBox (_misc_panel, wxID_ANY, _("Set language")); table->Add (_set_language, 1, wxEXPAND); - _language = new wxChoice (this, wxID_ANY); + _language = new wxChoice (_misc_panel, wxID_ANY); _language->Append (wxT ("English")); _language->Append (wxT ("Français")); _language->Append (wxT ("Italiano")); @@ -57,98 +92,38 @@ ConfigDialog::ConfigDialog (wxWindow* parent) table->Add (_language, 1, wxEXPAND); table->AddSpacer (0); - table->AddSpacer (0); - wxStaticText* restart = add_label_to_sizer (table, this, _("(restart DCP-o-matic to see language changes)")); + wxStaticText* restart = add_label_to_sizer (table, _misc_panel, _("(restart DCP-o-matic to see language changes)")); wxFont font = restart->GetFont(); font.SetStyle (wxFONTSTYLE_ITALIC); font.SetPointSize (font.GetPointSize() - 1); restart->SetFont (font); table->AddSpacer (0); - - add_label_to_sizer (table, this, _("TMS IP address")); - _tms_ip = new wxTextCtrl (this, wxID_ANY); - table->Add (_tms_ip, 1, wxEXPAND); - table->AddSpacer (0); - - add_label_to_sizer (table, this, _("TMS target path")); - _tms_path = new wxTextCtrl (this, wxID_ANY); - table->Add (_tms_path, 1, wxEXPAND); - table->AddSpacer (0); - - add_label_to_sizer (table, this, _("TMS user name")); - _tms_user = new wxTextCtrl (this, wxID_ANY); - table->Add (_tms_user, 1, wxEXPAND); table->AddSpacer (0); - add_label_to_sizer (table, this, _("TMS password")); - _tms_password = new wxTextCtrl (this, wxID_ANY); - table->Add (_tms_password, 1, wxEXPAND); - table->AddSpacer (0); - - add_label_to_sizer (table, this, _("Threads to use for encoding on this host")); - _num_local_encoding_threads = new wxSpinCtrl (this); + add_label_to_sizer (table, _misc_panel, _("Threads to use for encoding on this host")); + _num_local_encoding_threads = new wxSpinCtrl (_misc_panel); table->Add (_num_local_encoding_threads, 1, wxEXPAND); table->AddSpacer (0); - add_label_to_sizer (table, this, _("Default directory for new films")); + add_label_to_sizer (table, _misc_panel, _("Default duration of still images")); + _default_still_length = new wxSpinCtrl (_misc_panel); + table->Add (_default_still_length, 1, wxEXPAND); + add_label_to_sizer (table, _misc_panel, _("s")); + + add_label_to_sizer (table, _misc_panel, _("Default directory for new films")); #ifdef __WXMSW__ - _default_directory = new DirPickerCtrl (this); + _default_directory = new DirPickerCtrl (_misc_panel); #else - _default_directory = new wxDirPickerCtrl (this, wxDD_DIR_MUST_EXIST); + _default_directory = new wxDirPickerCtrl (_misc_panel, wxDD_DIR_MUST_EXIST); #endif table->Add (_default_directory, 1, wxEXPAND); table->AddSpacer (0); - add_label_to_sizer (table, this, _("Default DCI name details")); - _default_dci_metadata_button = new wxButton (this, wxID_ANY, _("Edit...")); + add_label_to_sizer (table, _misc_panel, _("Default DCI name details")); + _default_dci_metadata_button = new wxButton (_misc_panel, wxID_ANY, _("Edit...")); table->Add (_default_dci_metadata_button); table->AddSpacer (1); - add_label_to_sizer (table, this, _("Reference scaler for A/B")); - _reference_scaler = new wxChoice (this, wxID_ANY); - vector<Scaler const *> const sc = Scaler::all (); - for (vector<Scaler const *>::const_iterator i = sc.begin(); i != sc.end(); ++i) { - _reference_scaler->Append (std_to_wx ((*i)->name ())); - } - - table->Add (_reference_scaler, 1, wxEXPAND); - table->AddSpacer (0); - - { - add_label_to_sizer (table, this, _("Reference filters for A/B")); - wxSizer* s = new wxBoxSizer (wxHORIZONTAL); - _reference_filters = new wxStaticText (this, wxID_ANY, wxT ("")); - s->Add (_reference_filters, 1, wxEXPAND); - _reference_filters_button = new wxButton (this, wxID_ANY, _("Edit...")); - s->Add (_reference_filters_button, 0); - table->Add (s, 1, wxEXPAND); - table->AddSpacer (0); - } - - add_label_to_sizer (table, this, _("Encoding Servers")); - _servers = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (220, 100), wxLC_REPORT | wxLC_SINGLE_SEL); - wxListItem ip; - ip.SetId (0); - ip.SetText (_("IP address")); - ip.SetWidth (120); - _servers->InsertColumn (0, ip); - ip.SetId (1); - ip.SetText (_("Threads")); - ip.SetWidth (80); - _servers->InsertColumn (1, ip); - table->Add (_servers, 1, wxEXPAND | wxALL); - - { - wxSizer* s = new wxBoxSizer (wxVERTICAL); - _add_server = new wxButton (this, wxID_ANY, _("Add")); - s->Add (_add_server); - _edit_server = new wxButton (this, wxID_ANY, _("Edit")); - s->Add (_edit_server); - _remove_server = new wxButton (this, wxID_ANY, _("Remove")); - s->Add (_remove_server); - table->Add (s, 0); - } - Config* config = Config::instance (); _set_language->SetValue (config->language ()); @@ -169,6 +144,51 @@ ConfigDialog::ConfigDialog (wxWindow* parent) _set_language->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (ConfigDialog::set_language_changed), 0, this); _language->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (ConfigDialog::language_changed), 0, this); + + _num_local_encoding_threads->SetRange (1, 128); + _num_local_encoding_threads->SetValue (config->num_local_encoding_threads ()); + _num_local_encoding_threads->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (ConfigDialog::num_local_encoding_threads_changed), 0, this); + + _default_still_length->SetRange (1, 3600); + _default_still_length->SetValue (config->default_still_length ()); + _default_still_length->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (ConfigDialog::default_still_length_changed), 0, this); + + _default_directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())))); + _default_directory->Connect (wxID_ANY, wxEVT_COMMAND_DIRPICKER_CHANGED, wxCommandEventHandler (ConfigDialog::default_directory_changed), 0, this); + + _default_dci_metadata_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (ConfigDialog::edit_default_dci_metadata_clicked), 0, this); + +} + +void +ConfigDialog::make_tms_panel () +{ + _tms_panel = new wxPanel (_notebook); + wxBoxSizer* s = new wxBoxSizer (wxVERTICAL); + _tms_panel->SetSizer (s); + + wxFlexGridSizer* table = new wxFlexGridSizer (2, 6, 6); + table->AddGrowableCol (1, 1); + s->Add (table, 1, wxALL | wxEXPAND, 8); + + add_label_to_sizer (table, _tms_panel, _("IP address")); + _tms_ip = new wxTextCtrl (_tms_panel, wxID_ANY); + table->Add (_tms_ip, 1, wxEXPAND); + + add_label_to_sizer (table, _tms_panel, _("Target path")); + _tms_path = new wxTextCtrl (_tms_panel, wxID_ANY); + table->Add (_tms_path, 1, wxEXPAND); + + add_label_to_sizer (table, _tms_panel, _("User name")); + _tms_user = new wxTextCtrl (_tms_panel, wxID_ANY); + table->Add (_tms_user, 1, wxEXPAND); + + add_label_to_sizer (table, _tms_panel, _("Password")); + _tms_password = new wxTextCtrl (_tms_panel, wxID_ANY); + table->Add (_tms_password, 1, wxEXPAND); + + Config* config = Config::instance (); + _tms_ip->SetValue (std_to_wx (config->tms_ip ())); _tms_ip->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (ConfigDialog::tms_ip_changed), 0, this); _tms_path->SetValue (std_to_wx (config->tms_path ())); @@ -177,22 +197,85 @@ ConfigDialog::ConfigDialog (wxWindow* parent) _tms_user->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (ConfigDialog::tms_user_changed), 0, this); _tms_password->SetValue (std_to_wx (config->tms_password ())); _tms_password->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (ConfigDialog::tms_password_changed), 0, this); +} - _num_local_encoding_threads->SetRange (1, 128); - _num_local_encoding_threads->SetValue (config->num_local_encoding_threads ()); - _num_local_encoding_threads->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (ConfigDialog::num_local_encoding_threads_changed), 0, this); +void +ConfigDialog::make_ab_panel () +{ + _ab_panel = new wxPanel (_notebook); + wxBoxSizer* s = new wxBoxSizer (wxVERTICAL); + _ab_panel->SetSizer (s); - _default_directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())))); - _default_directory->Connect (wxID_ANY, wxEVT_COMMAND_DIRPICKER_CHANGED, wxCommandEventHandler (ConfigDialog::default_directory_changed), 0, this); + wxFlexGridSizer* table = new wxFlexGridSizer (3, 6, 6); + table->AddGrowableCol (1, 1); + s->Add (table, 1, wxALL, 8); + + add_label_to_sizer (table, _ab_panel, _("Reference scaler")); + _reference_scaler = new wxChoice (_ab_panel, wxID_ANY); + vector<Scaler const *> const sc = Scaler::all (); + for (vector<Scaler const *>::const_iterator i = sc.begin(); i != sc.end(); ++i) { + _reference_scaler->Append (std_to_wx ((*i)->name ())); + } - _default_dci_metadata_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (ConfigDialog::edit_default_dci_metadata_clicked), 0, this); + table->Add (_reference_scaler, 1, wxEXPAND); + table->AddSpacer (0); + + { + add_label_to_sizer (table, _ab_panel, _("Reference filters")); + wxSizer* s = new wxBoxSizer (wxHORIZONTAL); + _reference_filters = new wxStaticText (_ab_panel, wxID_ANY, wxT ("")); + s->Add (_reference_filters, 1, wxEXPAND); + _reference_filters_button = new wxButton (_ab_panel, wxID_ANY, _("Edit...")); + s->Add (_reference_filters_button, 0); + table->Add (s, 1, wxEXPAND); + table->AddSpacer (0); + } + Config* config = Config::instance (); + _reference_scaler->SetSelection (Scaler::as_index (config->reference_scaler ())); _reference_scaler->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (ConfigDialog::reference_scaler_changed), 0, this); pair<string, string> p = Filter::ffmpeg_strings (config->reference_filters ()); _reference_filters->SetLabel (std_to_wx (p.first) + N_(" ") + std_to_wx (p.second)); _reference_filters_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (ConfigDialog::edit_reference_filters_clicked), 0, this); +} + +void +ConfigDialog::make_servers_panel () +{ + _servers_panel = new wxPanel (_notebook); + wxBoxSizer* s = new wxBoxSizer (wxVERTICAL); + _servers_panel->SetSizer (s); + + wxFlexGridSizer* table = new wxFlexGridSizer (2, 6, 6); + table->AddGrowableCol (0, 1); + s->Add (table, 1, wxALL | wxEXPAND, 8); + + Config* config = Config::instance (); + + _servers = new wxListCtrl (_servers_panel, wxID_ANY, wxDefaultPosition, wxSize (220, 100), wxLC_REPORT | wxLC_SINGLE_SEL); + wxListItem ip; + ip.SetId (0); + ip.SetText (_("IP address")); + ip.SetWidth (120); + _servers->InsertColumn (0, ip); + ip.SetId (1); + ip.SetText (_("Threads")); + ip.SetWidth (80); + _servers->InsertColumn (1, ip); + table->Add (_servers, 1, wxEXPAND | wxALL); + + { + wxSizer* s = new wxBoxSizer (wxVERTICAL); + _add_server = new wxButton (_servers_panel, wxID_ANY, _("Add")); + s->Add (_add_server); + _edit_server = new wxButton (_servers_panel, wxID_ANY, _("Edit")); + s->Add (_edit_server); + _remove_server = new wxButton (_servers_panel, wxID_ANY, _("Remove")); + s->Add (_remove_server); + table->Add (s, 0); + } vector<ServerDescription*> servers = config->servers (); for (vector<ServerDescription*>::iterator i = servers.begin(); i != servers.end(); ++i) { @@ -207,18 +290,6 @@ ConfigDialog::ConfigDialog (wxWindow* parent) _servers->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler (ConfigDialog::server_selection_changed), 0, this); wxListEvent ev; server_selection_changed (ev); - - wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL); - overall_sizer->Add (table, 1, wxEXPAND | wxALL, 6); - - wxSizer* buttons = CreateSeparatedButtonSizer (wxOK); - if (buttons) { - overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder()); - } - - SetSizer (overall_sizer); - overall_sizer->Layout (); - overall_sizer->SetSizeHints (this); } void @@ -400,3 +471,9 @@ ConfigDialog::setup_language_sensitivity () { _language->Enable (_set_language->GetValue ()); } + +void +ConfigDialog::default_still_length_changed (wxCommandEvent &) +{ + Config::instance()->set_default_still_length (_default_still_length->GetValue ()); +} diff --git a/src/wx/config_dialog.h b/src/wx/config_dialog.h index a2fc1f4b1..852925e1d 100644 --- a/src/wx/config_dialog.h +++ b/src/wx/config_dialog.h @@ -27,6 +27,7 @@ #include <wx/filepicker.h> class DirPickerCtrl; +class wxNotebook; class ServerDescription; @@ -46,6 +47,7 @@ private: void tms_user_changed (wxCommandEvent &); void tms_password_changed (wxCommandEvent &); void num_local_encoding_threads_changed (wxCommandEvent &); + void default_still_length_changed (wxCommandEvent &); void default_directory_changed (wxCommandEvent &); void edit_default_dci_metadata_clicked (wxCommandEvent &); void reference_scaler_changed (wxCommandEvent &); @@ -59,6 +61,16 @@ private: void add_server_to_control (ServerDescription *); void setup_language_sensitivity (); + void make_misc_panel (); + void make_tms_panel (); + void make_ab_panel (); + void make_servers_panel (); + + wxNotebook* _notebook; + wxPanel* _misc_panel; + wxPanel* _tms_panel; + wxPanel* _ab_panel; + wxPanel* _servers_panel; wxCheckBox* _set_language; wxChoice* _language; wxTextCtrl* _tms_ip; @@ -66,6 +78,7 @@ private: wxTextCtrl* _tms_user; wxTextCtrl* _tms_password; wxSpinCtrl* _num_local_encoding_threads; + wxSpinCtrl* _default_still_length; #ifdef __WXMSW__ DirPickerCtrl* _default_directory; #else diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc index f909a8e2e..4f08953b9 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -214,6 +214,8 @@ FilmEditor::connect_to_widgets () _content_edit->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_edit_clicked), 0, this); _content_earlier->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_earlier_clicked), 0, this); _content_later->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_later_clicked), 0, this); + _loop_content->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::loop_content_toggled), 0, this); + _loop_count->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::loop_count_changed), 0, this); _left_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::left_crop_changed), 0, this); _right_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::right_crop_changed), 0, this); _top_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::top_crop_changed), 0, this); @@ -369,8 +371,18 @@ FilmEditor::make_content_panel () _content_sizer->Add (s, 1, wxEXPAND | wxALL, 6); } + wxBoxSizer* h = new wxBoxSizer (wxHORIZONTAL); + _loop_content = new wxCheckBox (_content_panel, wxID_ANY, _("Loop everything")); + h->Add (_loop_content, 0, wxALL, 6); + _loop_count = new wxSpinCtrl (_content_panel, wxID_ANY); + h->Add (_loop_count, 0, wxALL, 6); + add_label_to_sizer (h, _content_panel, _("times")); + _content_sizer->Add (h, 0, wxALL, 6); + _content_information = new wxTextCtrl (_content_panel, wxID_ANY, wxT ("\n\n\n\n"), wxDefaultPosition, wxDefaultSize, wxTE_READONLY | wxTE_MULTILINE); _content_sizer->Add (_content_information, 1, wxEXPAND | wxALL, 6); + + _loop_count->SetRange (2, 1024); } void @@ -620,6 +632,11 @@ FilmEditor::film_changed (Film::Property p) setup_show_audio_sensitivity (); setup_length (); break; + case Film::LOOP: + checked_set (_loop_content, _film->loop() > 1); + checked_set (_loop_count, _film->loop()); + setup_loop_sensitivity (); + break; case Film::TRUST_CONTENT_HEADERS: checked_set (_trust_content_headers, _film->trust_content_headers ()); break; @@ -890,6 +907,7 @@ FilmEditor::set_film (shared_ptr<Film> f) film_changed (Film::NAME); film_changed (Film::USE_DCI_NAME); film_changed (Film::CONTENT); + film_changed (Film::LOOP); film_changed (Film::TRUST_CONTENT_HEADERS); film_changed (Film::DCP_CONTENT_TYPE); film_changed (Film::FORMAT); @@ -1298,7 +1316,7 @@ FilmEditor::setup_content () void FilmEditor::content_add_clicked (wxCommandEvent &) { - wxFileDialog* d = new wxFileDialog (this); + wxFileDialog* d = new wxFileDialog (this, _("Choose a file or files"), wxT (""), wxT (""), wxT ("*.*"), wxFD_MULTIPLE); int const r = d->ShowModal (); d->Destroy (); @@ -1306,16 +1324,20 @@ FilmEditor::content_add_clicked (wxCommandEvent &) return; } - boost::filesystem::path p (wx_to_std (d->GetPath())); + wxArrayString paths; + d->GetPaths (paths); - if (ImageMagickContent::valid_file (p)) { - _film->add_content (shared_ptr<ImageMagickContent> (new ImageMagickContent (p))); - } else if (SndfileContent::valid_file (p)) { - _film->add_content (shared_ptr<SndfileContent> (new SndfileContent (p))); - } else { - _film->add_content (shared_ptr<FFmpegContent> (new FFmpegContent (p))); + for (unsigned int i = 0; i < paths.GetCount(); ++i) { + boost::filesystem::path p (wx_to_std (paths[i])); + + if (ImageMagickContent::valid_file (p)) { + _film->add_content (shared_ptr<ImageMagickContent> (new ImageMagickContent (p))); + } else if (SndfileContent::valid_file (p)) { + _film->add_content (shared_ptr<SndfileContent> (new SndfileContent (p))); + } else { + _film->add_content (shared_ptr<FFmpegContent> (new FFmpegContent (p))); + } } - } void @@ -1487,3 +1509,27 @@ FilmEditor::trim_type_changed (wxCommandEvent &) { _film->set_trim_type (_trim_type->GetSelection () == 0 ? Film::CPL : Film::ENCODE); } + +void +FilmEditor::loop_content_toggled (wxCommandEvent &) +{ + if (_loop_content->GetValue ()) { + _film->set_loop (_loop_count->GetValue ()); + } else { + _film->set_loop (1); + } + + setup_loop_sensitivity (); +} + +void +FilmEditor::loop_count_changed (wxCommandEvent &) +{ + _film->set_loop (_loop_count->GetValue ()); +} + +void +FilmEditor::setup_loop_sensitivity () +{ + _loop_count->Enable (_loop_content->GetValue ()); +} diff --git a/src/wx/film_editor.h b/src/wx/film_editor.h index ffffc1e76..5944633a8 100644 --- a/src/wx/film_editor.h +++ b/src/wx/film_editor.h @@ -93,6 +93,8 @@ private: void dcp_frame_rate_changed (wxCommandEvent &); void best_dcp_frame_rate_clicked (wxCommandEvent &); void edit_filters_clicked (wxCommandEvent &); + void loop_content_toggled (wxCommandEvent &); + void loop_count_changed (wxCommandEvent &); /* Handle changes to the model */ void film_changed (Film::Property); @@ -113,6 +115,7 @@ private: void setup_length (); void setup_content_information (); void setup_content_button_sensitivity (); + void setup_loop_sensitivity (); void active_jobs_changed (bool); boost::shared_ptr<Content> selected_content (); @@ -143,6 +146,8 @@ private: wxButton* _content_earlier; wxButton* _content_later; wxTextCtrl* _content_information; + wxCheckBox* _loop_content; + wxSpinCtrl* _loop_count; wxButton* _edit_dci_button; wxChoice* _format; wxStaticText* _format_description; diff --git a/src/wx/po/it_IT.po b/src/wx/po/it_IT.po index f53c40b97..2c6c67868 100644 --- a/src/wx/po/it_IT.po +++ b/src/wx/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 12:37+0100\n" +"PO-Revision-Date: 2013-04-28 10:27+0100\n" "Last-Translator: Maci <macibro@gmail.com>\n" "Language-Team: \n" "Language: Italiano\n" @@ -27,7 +27,7 @@ msgstr "(riavviare DCP-o-matic per vedere i cambiamenti di lingua)" #: src/wx/film_editor.cc:1276 msgid "1 channel" -msgstr "Canale 1" +msgstr "1 canale" #: src/wx/film_editor.cc:184 msgid "A/B" @@ -56,7 +56,7 @@ msgstr "Lingua dell'audio (es. EN)" #: src/wx/film_editor.cc:824 #, c-format msgid "Audio will be resampled from %dHz to %dHz\n" -msgstr "" +msgstr "L'Audio sarà ricampionato da %dHz a %dHz\n" #: src/wx/job_wrapper.cc:38 #, c-format @@ -126,7 +126,7 @@ msgstr "Crea nella cartella" #: src/wx/film_editor.cc:1371 #, c-format msgid "Cropped to %dx%d (%.2f:1)\n" -msgstr "" +msgstr "Tagliato da %dx%d (%.2f:1)\n" #: src/wx/dci_metadata_dialog.cc:28 msgid "DCI name" @@ -224,7 +224,7 @@ msgstr "Fotogrammi già codificati" #: src/wx/gain_calculator_dialog.cc:27 msgid "Gain Calculator" -msgstr "Calcola il guadagno audio" +msgstr "Calcolatore del guadagno audio" #: src/wx/properties_dialog.cc:59 msgid "Gb" @@ -285,7 +285,7 @@ msgstr "Frequenza fotogrammi originale" #: src/wx/film_editor.cc:1360 #, c-format msgid "Original video is %dx%d (%.2f:1)\n" -msgstr "" +msgstr "Il video originale è %dx%d (%.2f:1)\n" #: src/wx/dci_metadata_dialog.cc:57 msgid "Package Type (e.g. OV)" @@ -294,7 +294,7 @@ msgstr "Tipo di Package (es. OV)" #: src/wx/film_editor.cc:1392 #, c-format msgid "Padded with black to %dx%d (%.2f:1)\n" -msgstr "" +msgstr "Riempito con nero a %dx%d (%.2f:1)\n" #: src/wx/audio_dialog.cc:60 msgid "Peak" @@ -339,7 +339,7 @@ msgstr "In corso" #: src/wx/film_editor.cc:1384 #, c-format msgid "Scaled to %dx%d (%.2f:1)\n" -msgstr "" +msgstr "Scalato a %dx%d (%.2f:1)\n" #: src/wx/film_editor.cc:319 msgid "Scaler" @@ -438,9 +438,8 @@ msgid "Trim frames" msgstr "Taglia fotogrammi" #: src/wx/film_editor.cc:179 -#, fuzzy msgid "Trim method" -msgstr "Taglia fotogrammi" +msgstr "Metodo di taglio" #: src/wx/film_editor.cc:125 msgid "Trust content's header" @@ -472,7 +471,7 @@ msgstr "Video" #: src/wx/film_editor.cc:428 msgid "With Subtitles" -msgstr "Con Sottotitoli" +msgstr "Con sottotitoli" #: src/wx/film_editor.cc:1278 msgid "channels" @@ -488,11 +487,11 @@ msgstr "dB" #: src/wx/film_editor.cc:212 msgid "encode all frames and play the subset" -msgstr "" +msgstr "Codifica tutti i fotogrammi e riproduci la selezione" #: src/wx/film_editor.cc:213 msgid "encode only the subset" -msgstr "" +msgstr "codifica solo la selezione" #: src/wx/film_editor.cc:694 src/wx/film_editor.cc:697 msgid "frames" @@ -505,7 +504,7 @@ msgstr "ms" #: src/wx/film_editor.cc:440 msgid "pixels" -msgstr "" +msgstr "pizels" #. / TRANSLATORS: `s' here is an abbreviation for seconds, the unit of time #: src/wx/film_editor.cc:197 |
