diff options
| author | Carl Hetherington <cth@carlh.net> | 2013-04-06 14:42:08 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2013-04-06 14:42:08 +0100 |
| commit | 8750efb9e072cf3b42e6c3c29521c7031c0b5dfd (patch) | |
| tree | 0f0dd00b0413763b678ed2388b849cfe45a88468 /src | |
| parent | 1bff0990433ab0ce588acaef7c589fa623bd998b (diff) | |
Basics of content dialogs.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/audio_content.cc | 4 | ||||
| -rw-r--r-- | src/lib/audio_content.h | 8 | ||||
| -rw-r--r-- | src/lib/audio_mapping.cc | 103 | ||||
| -rw-r--r-- | src/lib/audio_mapping.h | 53 | ||||
| -rw-r--r-- | src/lib/encoder.cc | 3 | ||||
| -rw-r--r-- | src/lib/sndfile_content.cc | 84 | ||||
| -rw-r--r-- | src/lib/sndfile_content.h | 32 | ||||
| -rw-r--r-- | src/lib/sndfile_decoder.cc | 65 | ||||
| -rw-r--r-- | src/lib/sndfile_decoder.h | 8 | ||||
| -rw-r--r-- | src/lib/util.cc | 52 | ||||
| -rw-r--r-- | src/lib/util.h | 13 | ||||
| -rw-r--r-- | src/lib/writer.cc | 3 | ||||
| -rw-r--r-- | src/lib/wscript | 1 | ||||
| -rw-r--r-- | src/wx/audio_dialog.cc | 7 | ||||
| -rw-r--r-- | src/wx/film_editor.cc | 79 | ||||
| -rw-r--r-- | src/wx/film_editor.h | 5 | ||||
| -rw-r--r-- | src/wx/imagemagick_content_dialog.cc | 62 | ||||
| -rw-r--r-- | src/wx/imagemagick_content_dialog.h | 34 | ||||
| -rw-r--r-- | src/wx/sndfile_content_dialog.cc | 67 | ||||
| -rw-r--r-- | src/wx/sndfile_content_dialog.h | 36 | ||||
| -rw-r--r-- | src/wx/wscript | 2 |
21 files changed, 536 insertions, 185 deletions
diff --git a/src/lib/audio_content.cc b/src/lib/audio_content.cc index 8ca1e83c9..9968f4725 100644 --- a/src/lib/audio_content.cc +++ b/src/lib/audio_content.cc @@ -22,6 +22,10 @@ using boost::shared_ptr; +int const AudioContentProperty::AUDIO_CHANNELS = 200; +int const AudioContentProperty::AUDIO_LENGTH = 201; +int const AudioContentProperty::AUDIO_FRAME_RATE = 202; + AudioContent::AudioContent (boost::filesystem::path f) : Content (f) { diff --git a/src/lib/audio_content.h b/src/lib/audio_content.h index 2bfc20656..d5dbf266b 100644 --- a/src/lib/audio_content.h +++ b/src/lib/audio_content.h @@ -27,6 +27,14 @@ namespace cxml { class Node; } +class AudioContentProperty +{ +public: + static int const AUDIO_CHANNELS; + static int const AUDIO_LENGTH; + static int const AUDIO_FRAME_RATE; +}; + class AudioContent : public virtual Content { public: diff --git a/src/lib/audio_mapping.cc b/src/lib/audio_mapping.cc new file mode 100644 index 000000000..3fc423e10 --- /dev/null +++ b/src/lib/audio_mapping.cc @@ -0,0 +1,103 @@ +/* + Copyright (C) 2013 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "audio_mapping.h" + +using std::map; +using boost::optional; + +AutomaticAudioMapping::AutomaticAudioMapping (int c) + : _source_channels (c) +{ + +} + +optional<libdcp::Channel> +AutomaticAudioMapping::source_to_dcp (int c) const +{ + if (c >= _source_channels) { + return optional<libdcp::Channel> (); + } + + if (_source_channels == 1) { + /* mono sources to centre */ + return libdcp::CENTRE; + } + + return static_cast<libdcp::Channel> (c); +} + +optional<int> +AutomaticAudioMapping::dcp_to_source (libdcp::Channel c) const +{ + if (_source_channels == 1) { + if (c == libdcp::CENTRE) { + return 0; + } else { + return optional<int> (); + } + } + + if (static_cast<int> (c) >= _source_channels) { + return optional<int> (); + } + + return static_cast<int> (c); +} + +int +AutomaticAudioMapping::dcp_channels () const +{ + if (_source_channels == 1) { + /* The source is mono, so to put the mono channel into + the centre we need to generate a 5.1 soundtrack. + */ + return 6; + } + + return _source_channels; +} + +optional<int> +ConfiguredAudioMapping::dcp_to_source (libdcp::Channel c) const +{ + map<int, libdcp::Channel>::const_iterator i = _source_to_dcp.begin (); + while (i != _source_to_dcp.end() && i->second != c) { + ++i; + } + + if (i == _source_to_dcp.end ()) { + return boost::none; + } + + return i->first; +} + +optional<libdcp::Channel> +ConfiguredAudioMapping::source_to_dcp (int c) const +{ + map<int, libdcp::Channel>::const_iterator i = _source_to_dcp.find (c); + if (i == _source_to_dcp.end ()) { + return boost::none; + } + + return i->second; +} + + diff --git a/src/lib/audio_mapping.h b/src/lib/audio_mapping.h new file mode 100644 index 000000000..8804bde06 --- /dev/null +++ b/src/lib/audio_mapping.h @@ -0,0 +1,53 @@ +/* + Copyright (C) 2013 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include <vector> +#include <map> +#include <boost/optional.hpp> +#include <libdcp/types.h> + +class AudioMapping +{ +public: + virtual boost::optional<libdcp::Channel> source_to_dcp (int c) const = 0; + virtual boost::optional<int> dcp_to_source (libdcp::Channel c) const = 0; +}; + +class AutomaticAudioMapping : public AudioMapping +{ +public: + AutomaticAudioMapping (int); + + boost::optional<libdcp::Channel> source_to_dcp (int c) const; + boost::optional<int> dcp_to_source (libdcp::Channel c) const; + int dcp_channels () const; + +private: + int _source_channels; +}; + +class ConfiguredAudioMapping : public AudioMapping +{ +public: + boost::optional<libdcp::Channel> source_to_dcp (int c) const; + boost::optional<int> dcp_to_source (libdcp::Channel c) const; + +private: + std::map<int, libdcp::Channel> _source_to_dcp; +}; diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc index 568307462..a0b88e33e 100644 --- a/src/lib/encoder.cc +++ b/src/lib/encoder.cc @@ -38,6 +38,7 @@ #include "cross.h" #include "writer.h" #include "player.h" +#include "audio_mapping.h" #include "i18n.h" @@ -426,7 +427,7 @@ Encoder::encoder_thread (ServerDescription* server) void Encoder::write_audio (shared_ptr<const AudioBuffers> data) { - AudioMapping m (_film->audio_channels ()); + AutomaticAudioMapping m (_film->audio_channels ()); if (m.dcp_channels() != _film->audio_channels()) { /* Remap (currently just for mono -> 5.1) */ diff --git a/src/lib/sndfile_content.cc b/src/lib/sndfile_content.cc index 684405efb..ee4f21eef 100644 --- a/src/lib/sndfile_content.cc +++ b/src/lib/sndfile_content.cc @@ -17,13 +17,18 @@ */ +#include <libcxml/cxml.h> #include "sndfile_content.h" +#include "sndfile_decoder.h" #include "compose.hpp" +#include "job.h" #include "i18n.h" using std::string; +using std::stringstream; using boost::shared_ptr; +using boost::lexical_cast; SndfileContent::SndfileContent (boost::filesystem::path f) : Content (f) @@ -35,9 +40,10 @@ SndfileContent::SndfileContent (boost::filesystem::path f) SndfileContent::SndfileContent (shared_ptr<const cxml::Node> node) : Content (node) , AudioContent (node) - { - + _audio_channels = node->number_child<int> ("AudioChannels"); + _audio_length = node->number_child<ContentAudioFrame> ("AudioLength"); + _audio_frame_rate = node->number_child<int> ("AudioFrameRate"); } string @@ -49,37 +55,21 @@ SndfileContent::summary () const string SndfileContent::information () const { - return ""; -} - -int -SndfileContent::audio_channels () const -{ - /* XXX */ - return 0; -} - -ContentAudioFrame -SndfileContent::audio_length () const -{ - /* XXX */ - return 0; -} - -int -SndfileContent::audio_frame_rate () const -{ - /* XXX */ - return 0; -} - -int64_t -SndfileContent::audio_channel_layout () const -{ - /* XXX */ - return 0; -} + if (_audio_frame_rate == 0) { + return ""; + } + + stringstream s; + + s << String::compose ( + _("%1 channels, %2kHz, %3 samples"), + audio_channels(), + audio_frame_rate() / 1000.0, + audio_length() + ); + return s.str (); +} bool SndfileContent::valid_file (boost::filesystem::path f) @@ -95,3 +85,33 @@ SndfileContent::clone () const { return shared_ptr<Content> (new SndfileContent (*this)); } + +void +SndfileContent::examine (shared_ptr<Film> film, shared_ptr<Job> job, bool quick) +{ + job->set_progress_unknown (); + Content::examine (film, job, quick); + + SndfileDecoder dec (film, shared_from_this()); + + { + boost::mutex::scoped_lock lm (_mutex); + _audio_channels = dec.audio_channels (); + _audio_length = dec.audio_length (); + _audio_frame_rate = dec.audio_frame_rate (); + } + + signal_changed (AudioContentProperty::AUDIO_CHANNELS); + signal_changed (AudioContentProperty::AUDIO_LENGTH); + signal_changed (AudioContentProperty::AUDIO_FRAME_RATE); +} + +void +SndfileContent::as_xml (xmlpp::Node* node) const +{ + node->add_child("Type")->add_child_text ("Sndfile"); + Content::as_xml (node); + node->add_child("AudioChannels")->add_child_text (lexical_cast<string> (_audio_channels)); + node->add_child("AudioLength")->add_child_text (lexical_cast<string> (_audio_length)); + node->add_child("AudioFrameRate")->add_child_text (lexical_cast<string> (_audio_frame_rate)); +} diff --git a/src/lib/sndfile_content.h b/src/lib/sndfile_content.h index b696b57a5..27c5f3615 100644 --- a/src/lib/sndfile_content.h +++ b/src/lib/sndfile_content.h @@ -17,6 +17,9 @@ */ +extern "C" { +#include <libavutil/audioconvert.h> +} #include "audio_content.h" namespace cxml { @@ -33,15 +36,36 @@ public: return boost::dynamic_pointer_cast<SndfileContent> (Content::shared_from_this ()); } + void examine (boost::shared_ptr<Film>, boost::shared_ptr<Job>, bool); std::string summary () const; std::string information () const; + void as_xml (xmlpp::Node *) const; boost::shared_ptr<Content> clone () const; /* AudioContent */ - int audio_channels () const; - ContentAudioFrame audio_length () const; - int audio_frame_rate () const; - int64_t audio_channel_layout () const; + int audio_channels () const { + boost::mutex::scoped_lock lm (_mutex); + return _audio_channels; + } + + ContentAudioFrame audio_length () const { + boost::mutex::scoped_lock lm (_mutex); + return _audio_length; + } + + int audio_frame_rate () const { + boost::mutex::scoped_lock lm (_mutex); + return _audio_frame_rate; + } + + int64_t audio_channel_layout () const { + return av_get_default_channel_layout (audio_channels ()); + } static bool valid_file (boost::filesystem::path); + +private: + int _audio_channels; + ContentAudioFrame _audio_length; + int _audio_frame_rate; }; diff --git a/src/lib/sndfile_decoder.cc b/src/lib/sndfile_decoder.cc index 1f97e5c41..c7311112a 100644 --- a/src/lib/sndfile_decoder.cc +++ b/src/lib/sndfile_decoder.cc @@ -28,59 +28,62 @@ using std::vector; using std::string; -using std::stringstream; using std::min; using std::cout; using boost::shared_ptr; -using boost::optional; - -/* XXX */ SndfileDecoder::SndfileDecoder (shared_ptr<const Film> f, shared_ptr<const SndfileContent> c) : Decoder (f) , AudioDecoder (f) + , _sndfile_content (c) { - sf_count_t frames; - SNDFILE* sf = open_file (frames); - sf_close (sf); + _sndfile = sf_open (_sndfile_content->file().string().c_str(), SFM_READ, &_info); + if (!_sndfile) { + throw DecodeError (_("could not open audio file for reading")); + } + + _remaining = _info.frames; } -SNDFILE* -SndfileDecoder::open_file (sf_count_t & frames) +SndfileDecoder::~SndfileDecoder () { - frames = 0; - - SF_INFO info; - SNDFILE* s = sf_open (_sndfile_content->file().string().c_str(), SFM_READ, &info); - if (!s) { - throw DecodeError (_("could not open external audio file for reading")); + if (_sndfile) { + sf_close (_sndfile); } - - frames = info.frames; - return s; } bool SndfileDecoder::pass () { - sf_count_t frames; - SNDFILE* sndfile = open_file (frames); - /* 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_frame_rate() / 2; + sf_count_t const this_time = min (block, _remaining); + + shared_ptr<AudioBuffers> audio (new AudioBuffers (_sndfile_content->audio_channels(), this_time)); + sf_read_float (_sndfile, audio->data(0), this_time); + audio->set_frames (this_time); + Audio (audio); + _remaining -= this_time; - shared_ptr<AudioBuffers> audio (new AudioBuffers (_sndfile_content->audio_channels(), block)); - while (frames > 0) { - sf_count_t const this_time = min (block, frames); - sf_read_float (sndfile, audio->data(0), this_time); - audio->set_frames (this_time); - Audio (audio); - frames -= this_time; - } + return (_remaining == 0); +} - sf_close (sndfile); +int +SndfileDecoder::audio_channels () const +{ + return _info.channels; +} - return true; +ContentAudioFrame +SndfileDecoder::audio_length () const +{ + return _info.frames; +} + +int +SndfileDecoder::audio_frame_rate () const +{ + return _info.samplerate; } diff --git a/src/lib/sndfile_decoder.h b/src/lib/sndfile_decoder.h index 56fc3a9f0..2900afea0 100644 --- a/src/lib/sndfile_decoder.h +++ b/src/lib/sndfile_decoder.h @@ -27,12 +27,20 @@ class SndfileDecoder : public AudioDecoder { public: SndfileDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<const SndfileContent>); + ~SndfileDecoder (); bool pass (); + int audio_channels () const; + ContentAudioFrame audio_length () const; + 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; + ContentAudioFrame _remaining; }; diff --git a/src/lib/util.cc b/src/lib/util.cc index e0de82c64..1e60b43fc 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -914,58 +914,6 @@ audio_channel_name (int c) return channels[c]; } -AudioMapping::AudioMapping (int c) - : _source_channels (c) -{ - -} - -optional<libdcp::Channel> -AudioMapping::source_to_dcp (int c) const -{ - if (c >= _source_channels) { - return optional<libdcp::Channel> (); - } - - if (_source_channels == 1) { - /* mono sources to centre */ - return libdcp::CENTRE; - } - - return static_cast<libdcp::Channel> (c); -} - -optional<int> -AudioMapping::dcp_to_source (libdcp::Channel c) const -{ - if (_source_channels == 1) { - if (c == libdcp::CENTRE) { - return 0; - } else { - return optional<int> (); - } - } - - if (static_cast<int> (c) >= _source_channels) { - return optional<int> (); - } - - return static_cast<int> (c); -} - -int -AudioMapping::dcp_channels () const -{ - if (_source_channels == 1) { - /* The source is mono, so to put the mono channel into - the centre we need to generate a 5.1 soundtrack. - */ - return 6; - } - - return _source_channels; -} - FrameRateConversion::FrameRateConversion (float source, int dcp) : skip (false) , repeat (false) diff --git a/src/lib/util.h b/src/lib/util.h index 23ebd52bc..1fe6212e4 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -194,19 +194,6 @@ private: float** _data; }; -class AudioMapping -{ -public: - AudioMapping (int); - - boost::optional<libdcp::Channel> source_to_dcp (int c) const; - boost::optional<int> dcp_to_source (libdcp::Channel c) const; - int dcp_channels () const; - -private: - int _source_channels; -}; - extern int64_t video_frames_to_audio_frames (ContentVideoFrame v, float audio_sample_rate, float frames_per_second); extern std::pair<std::string, int> cpu_info (); diff --git a/src/lib/writer.cc b/src/lib/writer.cc index 5d38860e7..6df1a1f21 100644 --- a/src/lib/writer.cc +++ b/src/lib/writer.cc @@ -31,6 +31,7 @@ #include "dcp_video_frame.h" #include "dcp_content_type.h" #include "player.h" +#include "audio_mapping.h" #include "i18n.h" @@ -77,7 +78,7 @@ Writer::Writer (shared_ptr<Film> f) _picture_asset_writer = _picture_asset->start_write (_first_nonexistant_frame > 0); - AudioMapping m (_film->audio_channels ()); + AutomaticAudioMapping m (_film->audio_channels ()); if (m.dcp_channels() > 0) { _sound_asset.reset ( diff --git a/src/lib/wscript b/src/lib/wscript index 32a2cde23..896598a0e 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -8,6 +8,7 @@ sources = """ audio_analysis.cc audio_content.cc audio_decoder.cc + audio_mapping.cc audio_source.cc config.cc combiner.cc diff --git a/src/wx/audio_dialog.cc b/src/wx/audio_dialog.cc index 1241c2e76..f53ea7c19 100644 --- a/src/wx/audio_dialog.cc +++ b/src/wx/audio_dialog.cc @@ -20,6 +20,7 @@ #include <boost/filesystem.hpp> #include "lib/audio_analysis.h" #include "lib/film.h" +#include "lib/audio_mapping.h" #include "audio_dialog.h" #include "audio_plot.h" #include "wx_util.h" @@ -108,7 +109,7 @@ AudioDialog::setup_channels () return; } - AudioMapping m (_film->audio_channels ()); + AutomaticAudioMapping m (_film->audio_channels ()); for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) { if (m.dcp_to_source(static_cast<libdcp::Channel>(i))) { @@ -134,7 +135,7 @@ AudioDialog::try_to_load_analysis () _plot->set_analysis (a); - AudioMapping m (_film->audio_channels ()); + AutomaticAudioMapping m (_film->audio_channels ()); optional<libdcp::Channel> c = m.source_to_dcp (0); if (c) { _channel_checkbox[c.get()]->SetValue (true); @@ -157,7 +158,7 @@ AudioDialog::channel_clicked (wxCommandEvent& ev) assert (c < MAX_AUDIO_CHANNELS); - AudioMapping m (_film->audio_channels ()); + AutomaticAudioMapping m (_film->audio_channels ()); optional<int> s = m.dcp_to_source (static_cast<libdcp::Channel> (c)); if (s) { _plot->set_channel_visible (s.get(), _channel_checkbox[c]->GetValue ()); diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc index 58fc077a3..6c42359fb 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -49,6 +49,8 @@ #include "dci_metadata_dialog.h" #include "scaler.h" #include "audio_dialog.h" +#include "imagemagick_content_dialog.h" +#include "sndfile_content_dialog.h" using std::string; using std::cout; @@ -198,9 +200,9 @@ FilmEditor::connect_to_widgets () _content->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler (FilmEditor::content_item_selected), 0, this); _content_add->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_add_clicked), 0, this); _content_remove->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_remove_clicked), 0, this); + _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); - _imagemagick_video_length->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::imagemagick_video_length_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); @@ -343,6 +345,8 @@ FilmEditor::make_content_panel () b->Add (_content_add); _content_remove = new wxButton (_content_panel, wxID_ANY, _("Remove")); b->Add (_content_remove); + _content_edit = new wxButton (_content_panel, wxID_ANY, _("Edit...")); + b->Add (_content_edit); _content_earlier = new wxButton (_content_panel, wxID_ANY, _("Earlier")); b->Add (_content_earlier); _content_later = new wxButton (_content_panel, wxID_ANY, _("Later")); @@ -355,21 +359,6 @@ FilmEditor::make_content_panel () _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); - - wxFlexGridSizer* grid = new wxFlexGridSizer (2, 4, 4); - _content_sizer->Add (grid, 0, wxEXPAND | wxALL, 6); - - { - add_label_to_sizer (grid, _content_panel, (_("Duration"))); - wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); - _imagemagick_video_length = new wxSpinCtrl (_content_panel); - s->Add (_imagemagick_video_length); - /// TRANSLATORS: this is an abbreviation for seconds, the unit of time - add_label_to_sizer (s, _content_panel, _("s")); - grid->Add (s); - } - - _imagemagick_video_length->SetRange (1, 3600); } void @@ -723,14 +712,9 @@ FilmEditor::film_content_changed (weak_ptr<Content> content, int property) setup_show_audio_sensitivity (); } else if (property == VideoContentProperty::VIDEO_LENGTH) { setup_length (); - boost::shared_ptr<Content> c = content.lock (); if (c && c == selected_content()) { setup_content_information (); - shared_ptr<ImageMagickContent> im = dynamic_pointer_cast<ImageMagickContent> (c); - if (im) { - checked_set (_imagemagick_video_length, im->video_length() / 24); - } } } else if (property == FFmpegContentProperty::AUDIO_STREAM) { if (_film->ffmpeg_audio_stream()) { @@ -1259,6 +1243,33 @@ FilmEditor::content_remove_clicked (wxCommandEvent &) } void +FilmEditor::content_edit_clicked (wxCommandEvent &) +{ + shared_ptr<Content> c = selected_content (); + if (!c) { + return; + } + + shared_ptr<ImageMagickContent> im = dynamic_pointer_cast<ImageMagickContent> (c); + if (im) { + ImageMagickContentDialog* d = new ImageMagickContentDialog (this, im); + int const r = d->ShowModal (); + d->Destroy (); + + if (r == wxID_OK) { + im->set_video_length (d->video_length() * 24); + } + } + + shared_ptr<SndfileContent> sf = dynamic_pointer_cast<SndfileContent> (c); + if (sf) { + SndfileContentDialog* d = new SndfileContentDialog (this, sf); + d->ShowModal (); + d->Destroy (); + } +} + +void FilmEditor::content_earlier_clicked (wxCommandEvent &) { shared_ptr<Content> c = selected_content (); @@ -1281,15 +1292,6 @@ FilmEditor::content_item_selected (wxListEvent &) { setup_content_button_sensitivity (); setup_content_information (); - - shared_ptr<Content> c = selected_content (); - if (c) { - shared_ptr<ImageMagickContent> im = dynamic_pointer_cast<ImageMagickContent> (c); - _imagemagick_video_length->Enable (im); - if (im) { - checked_set (_imagemagick_video_length, im->video_length() / 24); - } - } } void @@ -1310,27 +1312,12 @@ FilmEditor::setup_content_button_sensitivity () _content_add->Enable (_generally_sensitive); bool const have_selection = _content->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1; + _content_edit->Enable (have_selection && _generally_sensitive); _content_remove->Enable (have_selection && _generally_sensitive); _content_earlier->Enable (have_selection && _generally_sensitive); _content_later->Enable (have_selection && _generally_sensitive); } -void -FilmEditor::imagemagick_video_length_changed (wxCommandEvent &) -{ - shared_ptr<Content> c = selected_content (); - if (!c) { - return; - } - - shared_ptr<ImageMagickContent> im = dynamic_pointer_cast<ImageMagickContent> (c); - if (!im) { - return; - } - - im->set_video_length (_imagemagick_video_length->GetValue() * 24); -} - shared_ptr<Content> FilmEditor::selected_content () { diff --git a/src/wx/film_editor.h b/src/wx/film_editor.h index 2870714f9..b6f6a24ee 100644 --- a/src/wx/film_editor.h +++ b/src/wx/film_editor.h @@ -16,7 +16,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - + /** @file src/film_editor.h * @brief A wx widget to edit a film's metadata, and perform various functions. */ @@ -66,6 +66,7 @@ private: void content_item_selected (wxListEvent &); void content_add_clicked (wxCommandEvent &); void content_remove_clicked (wxCommandEvent &); + void content_edit_clicked (wxCommandEvent &); void content_earlier_clicked (wxCommandEvent &); void content_later_clicked (wxCommandEvent &); void imagemagick_video_length_changed (wxCommandEvent &); @@ -131,10 +132,10 @@ private: wxListCtrl* _content; wxButton* _content_add; wxButton* _content_remove; + wxButton* _content_edit; wxButton* _content_earlier; wxButton* _content_later; wxTextCtrl* _content_information; - wxSpinCtrl* _imagemagick_video_length; wxButton* _edit_dci_button; wxChoice* _format; wxStaticText* _format_description; diff --git a/src/wx/imagemagick_content_dialog.cc b/src/wx/imagemagick_content_dialog.cc new file mode 100644 index 000000000..726e4b8e2 --- /dev/null +++ b/src/wx/imagemagick_content_dialog.cc @@ -0,0 +1,62 @@ +/* + Copyright (C) 2013 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include <wx/spinctrl.h> +#include "lib/imagemagick_content.h" +#include "imagemagick_content_dialog.h" +#include "wx_util.h" + +using boost::shared_ptr; + +ImageMagickContentDialog::ImageMagickContentDialog (wxWindow* parent, shared_ptr<ImageMagickContent> content) + : wxDialog (parent, wxID_ANY, _("Image")) +{ + wxFlexGridSizer* grid = new wxFlexGridSizer (3, 6, 6); + grid->AddGrowableCol (1, 1); + + { + add_label_to_sizer (grid, this, (_("Duration"))); + wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); + _video_length = new wxSpinCtrl (this); + s->Add (_video_length); + /// TRANSLATORS: this is an abbreviation for seconds, the unit of time + add_label_to_sizer (s, this, _("s")); + grid->Add (s); + } + + wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL); + overall_sizer->Add (grid, 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); + + checked_set (_video_length, content->video_length () / 24); +} + +int +ImageMagickContentDialog::video_length () const +{ + return _video_length->GetValue (); +} diff --git a/src/wx/imagemagick_content_dialog.h b/src/wx/imagemagick_content_dialog.h new file mode 100644 index 000000000..2fa955929 --- /dev/null +++ b/src/wx/imagemagick_content_dialog.h @@ -0,0 +1,34 @@ +/* + Copyright (C) 2013 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include <wx/wx.h> + +class wxSpinCtrl; +class ImageMagickContent; + +class ImageMagickContentDialog : public wxDialog +{ +public: + ImageMagickContentDialog (wxWindow *, boost::shared_ptr<ImageMagickContent>); + + int video_length () const; + +private: + wxSpinCtrl* _video_length; +}; diff --git a/src/wx/sndfile_content_dialog.cc b/src/wx/sndfile_content_dialog.cc new file mode 100644 index 000000000..f305b158c --- /dev/null +++ b/src/wx/sndfile_content_dialog.cc @@ -0,0 +1,67 @@ +/* + Copyright (C) 2013 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "lib/util.h" +#include "lib/sndfile_content.h" +#include "sndfile_content_dialog.h" +#include "wx_util.h" + +using boost::shared_ptr; + +SndfileContentDialog::SndfileContentDialog (wxWindow* parent, shared_ptr<SndfileContent> content) + : wxDialog (parent, wxID_ANY, _("Sound file")) +{ + wxFlexGridSizer* grid = new wxFlexGridSizer (7, 6, 0); + + add_label_to_sizer (grid, this, wxT ("")); + add_label_to_sizer (grid, this, _("L")); + add_label_to_sizer (grid, this, _("R")); + add_label_to_sizer (grid, this, _("C")); + add_label_to_sizer (grid, this, _("Lfe")); + add_label_to_sizer (grid, this, _("Ls")); + add_label_to_sizer (grid, this, _("Rs")); + + _buttons.resize (content->audio_channels ()); + for (int i = 0; i < content->audio_channels(); ++i) { + + if (content->audio_channels() == 1) { + add_label_to_sizer (grid, this, _("Source")); + } else { + add_label_to_sizer (grid, this, wxString::Format (_("Source %d"), i + 1)); + } + + for (int j = 0; j < MAX_AUDIO_CHANNELS; ++j) { + wxRadioButton* b = new wxRadioButton (this, wxID_ANY, wxT (""), wxDefaultPosition, wxDefaultSize, j ? 0 : wxRB_GROUP); + _buttons[i].push_back (b); + grid->Add (b, wxSHRINK); + } + } + + wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL); + overall_sizer->Add (grid, 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); +} diff --git a/src/wx/sndfile_content_dialog.h b/src/wx/sndfile_content_dialog.h new file mode 100644 index 000000000..5a328892a --- /dev/null +++ b/src/wx/sndfile_content_dialog.h @@ -0,0 +1,36 @@ +/* + Copyright (C) 2013 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include <vector> +#include <boost/shared_ptr.hpp> +#include <wx/wx.h> +#include "lib/audio_mapping.h" + +class SndfileContent; + +class SndfileContentDialog : public wxDialog +{ +public: + SndfileContentDialog (wxWindow *, boost::shared_ptr<SndfileContent>); + + ConfiguredAudioMapping audio_mapping () const; + +private: + std::vector<std::vector<wxRadioButton *> > _buttons; +}; diff --git a/src/wx/wscript b/src/wx/wscript index 42bb8ca88..bd21af6ce 100644 --- a/src/wx/wscript +++ b/src/wx/wscript @@ -14,11 +14,13 @@ sources = """ filter_dialog.cc filter_view.cc gain_calculator_dialog.cc + imagemagick_content_dialog.cc job_manager_view.cc job_wrapper.cc new_film_dialog.cc properties_dialog.cc server_dialog.cc + sndfile_content_dialog.cc wx_util.cc wx_ui_signaller.cc """ |
