diff options
| author | Carl Hetherington <cth@carlh.net> | 2013-11-11 12:53:26 +0000 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2013-11-11 12:53:26 +0000 |
| commit | cb83eb7b209054da2f81b456a0fbda6ea9d03844 (patch) | |
| tree | 214f5ebeaefdbeb20129b541dfe9715588999aeb /src | |
| parent | deafd62ea410aa23b6b4c87989e8bc7e95db46e3 (diff) | |
Basic multiple selection for cropping.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/types.h | 2 | ||||
| -rw-r--r-- | src/lib/video_content.h | 20 | ||||
| -rw-r--r-- | src/wx/audio_panel.cc | 103 | ||||
| -rw-r--r-- | src/wx/audio_panel.h | 3 | ||||
| -rw-r--r-- | src/wx/film_editor.cc | 99 | ||||
| -rw-r--r-- | src/wx/film_editor.h | 3 | ||||
| -rw-r--r-- | src/wx/film_editor_panel.h | 5 | ||||
| -rw-r--r-- | src/wx/multiple_widget.h | 125 | ||||
| -rw-r--r-- | src/wx/subtitle_panel.cc | 65 | ||||
| -rw-r--r-- | src/wx/subtitle_panel.h | 4 | ||||
| -rw-r--r-- | src/wx/timing_panel.cc | 50 | ||||
| -rw-r--r-- | src/wx/timing_panel.h | 3 | ||||
| -rw-r--r-- | src/wx/video_panel.cc | 203 | ||||
| -rw-r--r-- | src/wx/video_panel.h | 13 |
14 files changed, 449 insertions, 249 deletions
diff --git a/src/lib/types.h b/src/lib/types.h index ad706270e..448b6c154 100644 --- a/src/lib/types.h +++ b/src/lib/types.h @@ -29,6 +29,7 @@ class Content; class VideoContent; class AudioContent; class SubtitleContent; +class FFmpegContent; class AudioBuffers; /** The version number of the protocol used to communicate @@ -46,6 +47,7 @@ typedef std::vector<boost::shared_ptr<Content> > ContentList; typedef std::vector<boost::shared_ptr<VideoContent> > VideoContentList; typedef std::vector<boost::shared_ptr<AudioContent> > AudioContentList; typedef std::vector<boost::shared_ptr<SubtitleContent> > SubtitleContentList; +typedef std::vector<boost::shared_ptr<FFmpegContent> > FFmpegContentList; template<class T> struct TimedAudioBuffers diff --git a/src/lib/video_content.h b/src/lib/video_content.h index 6f80536fe..106adf959 100644 --- a/src/lib/video_content.h +++ b/src/lib/video_content.h @@ -85,6 +85,26 @@ public: return _crop; } + int left_crop () const { + boost::mutex::scoped_lock lm (_mutex); + return _crop.left; + } + + int right_crop () const { + boost::mutex::scoped_lock lm (_mutex); + return _crop.right; + } + + int top_crop () const { + boost::mutex::scoped_lock lm (_mutex); + return _crop.top; + } + + int bottom_crop () const { + boost::mutex::scoped_lock lm (_mutex); + return _crop.bottom; + } + void set_ratio (Ratio const *); /** @return ratio to scale to, or 0 if the content's own ratio should be preserved. */ diff --git a/src/wx/audio_panel.cc b/src/wx/audio_panel.cc index f96eeec2b..e2ea15f64 100644 --- a/src/wx/audio_panel.cc +++ b/src/wx/audio_panel.cc @@ -112,35 +112,40 @@ AudioPanel::film_changed (Film::Property property) } void -AudioPanel::film_content_changed (shared_ptr<Content> c, int property) +AudioPanel::film_content_changed (int property) { - shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> (c); - shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (c); - - if (_audio_dialog && _editor->selected_audio_content()) { - _audio_dialog->set_content (_editor->selected_audio_content ()); + AudioContentList ac = _editor->selected_audio_content (); + shared_ptr<AudioContent> acs; + shared_ptr<FFmpegContent> fcs; + if (ac.size() == 1) { + acs = ac.front (); + fcs = dynamic_pointer_cast<FFmpegContent> (acs); + } + + if (_audio_dialog && acs) { + _audio_dialog->set_content (acs); } if (property == AudioContentProperty::AUDIO_GAIN) { - checked_set (_gain, ac ? ac->audio_gain() : 0); + checked_set (_gain, acs ? acs->audio_gain() : 0); } else if (property == AudioContentProperty::AUDIO_DELAY) { - checked_set (_delay, ac ? ac->audio_delay() : 0); + checked_set (_delay, acs ? acs->audio_delay() : 0); } else if (property == AudioContentProperty::AUDIO_MAPPING) { - _mapping->set (ac ? ac->audio_mapping () : AudioMapping ()); + _mapping->set (acs ? acs->audio_mapping () : AudioMapping ()); _sizer->Layout (); } else if (property == FFmpegContentProperty::AUDIO_STREAM) { setup_stream_description (); - _mapping->set (ac ? ac->audio_mapping () : AudioMapping ()); + _mapping->set (acs ? acs->audio_mapping () : AudioMapping ()); } else if (property == FFmpegContentProperty::AUDIO_STREAMS) { _stream->Clear (); - if (fc) { - vector<shared_ptr<FFmpegAudioStream> > a = fc->audio_streams (); + if (fcs) { + vector<shared_ptr<FFmpegAudioStream> > a = fcs->audio_streams (); for (vector<shared_ptr<FFmpegAudioStream> >::iterator i = a.begin(); i != a.end(); ++i) { _stream->Append (std_to_wx ((*i)->name), new wxStringClientData (std_to_wx (lexical_cast<string> ((*i)->id)))); } - if (fc->audio_stream()) { - checked_set (_stream, lexical_cast<string> (fc->audio_stream()->id)); + if (fcs->audio_stream()) { + checked_set (_stream, lexical_cast<string> (fcs->audio_stream()->id)); setup_stream_description (); } } @@ -150,23 +155,23 @@ AudioPanel::film_content_changed (shared_ptr<Content> c, int property) void AudioPanel::gain_changed () { - shared_ptr<AudioContent> ac = _editor->selected_audio_content (); - if (!ac) { + AudioContentList ac = _editor->selected_audio_content (); + if (ac.size() != 1) { return; } - ac->set_audio_gain (_gain->GetValue ()); + ac.front()->set_audio_gain (_gain->GetValue ()); } void AudioPanel::delay_changed () { - shared_ptr<AudioContent> ac = _editor->selected_audio_content (); - if (!ac) { + AudioContentList ac = _editor->selected_audio_content (); + if (ac.size() != 1) { return; } - ac->set_audio_delay (_delay->GetValue ()); + ac.front()->set_audio_delay (_delay->GetValue ()); } void @@ -203,39 +208,31 @@ AudioPanel::show_clicked () _audio_dialog = 0; } - shared_ptr<Content> c = _editor->selected_content (); - if (!c) { - return; - } - - shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> (c); - if (!ac) { + AudioContentList ac = _editor->selected_audio_content (); + if (ac.size() != 1) { return; } _audio_dialog = new AudioDialog (this); _audio_dialog->Show (); - _audio_dialog->set_content (ac); + _audio_dialog->set_content (ac.front ()); } void AudioPanel::stream_changed () { - shared_ptr<Content> c = _editor->selected_content (); - if (!c) { - return; - } - - shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (c); - if (!fc) { + FFmpegContentList fc = _editor->selected_ffmpeg_content (); + if (fc.size() != 1) { return; } + shared_ptr<FFmpegContent> fcs = fc.front (); + if (_stream->GetSelection() == -1) { return; } - vector<shared_ptr<FFmpegAudioStream> > a = fc->audio_streams (); + vector<shared_ptr<FFmpegAudioStream> > a = fcs->audio_streams (); vector<shared_ptr<FFmpegAudioStream> >::iterator i = a.begin (); string const s = string_client_data (_stream->GetClientObject (_stream->GetSelection ())); while (i != a.end() && lexical_cast<string> ((*i)->id) != s) { @@ -243,7 +240,7 @@ AudioPanel::stream_changed () } if (i != a.end ()) { - fc->set_audio_stream (*i); + fcs->set_audio_stream (*i); } setup_stream_description (); @@ -252,26 +249,23 @@ AudioPanel::stream_changed () void AudioPanel::setup_stream_description () { - shared_ptr<Content> c = _editor->selected_content (); - if (!c) { - return; - } - - shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (c); - if (!fc) { + FFmpegContentList fc = _editor->selected_ffmpeg_content (); + if (fc.size() != 1) { return; } - if (!fc->audio_stream ()) { + shared_ptr<FFmpegContent> fcs = fc.front (); + + if (!fcs->audio_stream ()) { _description->SetLabel (wxT ("")); } else { wxString s; - if (fc->audio_channels() == 1) { + if (fcs->audio_channels() == 1) { s << _("1 channel"); } else { - s << fc->audio_channels() << wxT (" ") << _("channels"); + s << fcs->audio_channels() << wxT (" ") << _("channels"); } - s << wxT (", ") << fc->content_audio_frame_rate() << _("Hz"); + s << wxT (", ") << fcs->content_audio_frame_rate() << _("Hz"); _description->SetLabel (s); } } @@ -279,11 +273,14 @@ AudioPanel::setup_stream_description () void AudioPanel::mapping_changed (AudioMapping m) { - shared_ptr<AudioContent> c = _editor->selected_audio_content (); - if (!c) { - return; + AudioContentList c = _editor->selected_audio_content (); + if (c.size() == 1) { + c.front()->set_audio_mapping (m); } - - c->set_audio_mapping (m); } +void +AudioPanel::content_selection_changed () +{ + +} diff --git a/src/wx/audio_panel.h b/src/wx/audio_panel.h index e1dc283e2..8cb94f0fa 100644 --- a/src/wx/audio_panel.h +++ b/src/wx/audio_panel.h @@ -33,7 +33,8 @@ public: AudioPanel (FilmEditor *); void film_changed (Film::Property); - void film_content_changed (boost::shared_ptr<Content>, int); + void film_content_changed (int); + void content_selection_changed (); private: void gain_changed (); diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc index 99b3c59a5..fd1dd2b33 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -470,7 +470,7 @@ FilmEditor::film_changed (Film::Property p) } void -FilmEditor::film_content_changed (weak_ptr<Content> weak_content, int property) +FilmEditor::film_content_changed (int property) { ensure_ui_thread (); @@ -481,13 +481,8 @@ FilmEditor::film_content_changed (weak_ptr<Content> weak_content, int property) return; } - shared_ptr<Content> content = weak_content.lock (); - if (!content || content != selected_content ()) { - return; - } - for (list<FilmEditorPanel*>::iterator i = _panels.begin(); i != _panels.end(); ++i) { - (*i)->film_content_changed (content, property); + (*i)->film_content_changed (property); } if (property == FFmpegContentProperty::AUDIO_STREAM) { @@ -561,7 +556,7 @@ FilmEditor::set_film (shared_ptr<Film> f) if (_film) { _film->Changed.connect (bind (&FilmEditor::film_changed, this, _1)); - _film->ContentChanged.connect (bind (&FilmEditor::film_content_changed, this, _1, _2)); + _film->ContentChanged.connect (bind (&FilmEditor::film_content_changed, this, _2)); } if (_film) { @@ -775,9 +770,9 @@ FilmEditor::content_add_folder_clicked () void FilmEditor::content_remove_clicked () { - shared_ptr<Content> c = selected_content (); - if (c) { - _film->remove_content (c); + ContentList c = selected_content (); + if (c.size() == 1) { + _film->remove_content (c.front ()); } content_selection_changed (); @@ -787,29 +782,10 @@ void FilmEditor::content_selection_changed () { setup_content_sensitivity (); - shared_ptr<Content> s = selected_content (); - - /* All other sensitivity in content panels should be triggered by - one of these. - */ - film_content_changed (s, ContentProperty::POSITION); - film_content_changed (s, ContentProperty::LENGTH); - film_content_changed (s, ContentProperty::TRIM_START); - film_content_changed (s, ContentProperty::TRIM_END); - film_content_changed (s, VideoContentProperty::VIDEO_CROP); - film_content_changed (s, VideoContentProperty::VIDEO_RATIO); - film_content_changed (s, VideoContentProperty::VIDEO_FRAME_TYPE); - film_content_changed (s, VideoContentProperty::COLOUR_CONVERSION); - film_content_changed (s, AudioContentProperty::AUDIO_GAIN); - film_content_changed (s, AudioContentProperty::AUDIO_DELAY); - film_content_changed (s, AudioContentProperty::AUDIO_MAPPING); - film_content_changed (s, FFmpegContentProperty::AUDIO_STREAM); - film_content_changed (s, FFmpegContentProperty::AUDIO_STREAMS); - film_content_changed (s, FFmpegContentProperty::SUBTITLE_STREAM); - film_content_changed (s, FFmpegContentProperty::SUBTITLE_STREAMS); - film_content_changed (s, FFmpegContentProperty::FILTERS); - film_content_changed (s, SubtitleContentProperty::SUBTITLE_OFFSET); - film_content_changed (s, SubtitleContentProperty::SUBTITLE_SCALE); + + for (list<FilmEditorPanel*>::iterator i = _panels.begin(); i != _panels.end(); ++i) { + (*i)->content_selection_changed (); + } } /** Set up broad sensitivity based on the type of content that is selected */ @@ -819,17 +795,18 @@ FilmEditor::setup_content_sensitivity () _content_add_file->Enable (_generally_sensitive); _content_add_folder->Enable (_generally_sensitive); - shared_ptr<Content> selection = selected_content (); + ContentList selection = selected_content (); + VideoContentList video_selection = selected_video_content (); - _content_remove->Enable (selection && _generally_sensitive); - _content_earlier->Enable (selection && _generally_sensitive); - _content_later->Enable (selection && _generally_sensitive); + _content_remove->Enable (selection.size() == 1 && _generally_sensitive); + _content_earlier->Enable (selection.size() == 1 && _generally_sensitive); + _content_later->Enable (selection.size() == 1 && _generally_sensitive); _content_timeline->Enable (_generally_sensitive); - _video_panel->Enable (selection && dynamic_pointer_cast<VideoContent> (selection) && _generally_sensitive); - _audio_panel->Enable (selection && dynamic_pointer_cast<AudioContent> (selection) && _generally_sensitive); - _subtitle_panel->Enable (selection && dynamic_pointer_cast<FFmpegContent> (selection) && _generally_sensitive); - _timing_panel->Enable (selection && _generally_sensitive); + _video_panel->Enable (video_selection.size() > 0 && _generally_sensitive); + _audio_panel->Enable (selection.size() == 1 && dynamic_pointer_cast<AudioContent> (selection.front()) && _generally_sensitive); + _subtitle_panel->Enable (selection.size() == 1 && dynamic_pointer_cast<FFmpegContent> (selection.front()) && _generally_sensitive); + _timing_panel->Enable (selection.size() == 1 && _generally_sensitive); } ContentList @@ -843,7 +820,7 @@ FilmEditor::selected_content () break; } - sel.push_back (_film->content[s]); + sel.push_back (_film->content()[s]); } return sel; @@ -897,6 +874,22 @@ FilmEditor::selected_subtitle_content () return sc; } +FFmpegContentList +FilmEditor::selected_ffmpeg_content () +{ + ContentList c = selected_content (); + FFmpegContentList sc; + + for (ContentList::iterator i = c.begin(); i != c.end(); ++i) { + shared_ptr<FFmpegContent> t = dynamic_pointer_cast<FFmpegContent> (*i); + if (t) { + sc.push_back (t); + } + } + + return sc; +} + void FilmEditor::content_timeline_clicked () { @@ -935,11 +928,7 @@ FilmEditor::sequence_video_changed () void FilmEditor::content_right_click (wxListEvent& ev) { - ContentList cl; - if (selected_content ()) { - cl.push_back (selected_content ()); - } - _menu.popup (cl, ev.GetPoint ()); + _menu.popup (selected_content (), ev.GetPoint ()); } void @@ -955,13 +944,19 @@ FilmEditor::three_d_changed () void FilmEditor::content_earlier_clicked () { - _film->move_content_earlier (selected_content ()); - content_selection_changed (); + ContentList sel = selected_content (); + if (sel.size() == 1) { + _film->move_content_earlier (sel.front ()); + content_selection_changed (); + } } void FilmEditor::content_later_clicked () { - _film->move_content_later (selected_content ()); - content_selection_changed (); + ContentList sel = selected_content (); + if (sel.size() == 1) { + _film->move_content_later (sel.front ()); + content_selection_changed (); + } } diff --git a/src/wx/film_editor.h b/src/wx/film_editor.h index 9808e0d2f..7fd61e5fc 100644 --- a/src/wx/film_editor.h +++ b/src/wx/film_editor.h @@ -66,6 +66,7 @@ public: VideoContentList selected_video_content (); AudioContentList selected_audio_content (); SubtitleContentList selected_subtitle_content (); + FFmpegContentList selected_ffmpeg_content (); private: void make_dcp_panel (); @@ -99,7 +100,7 @@ private: /* Handle changes to the model */ void film_changed (Film::Property); - void film_content_changed (boost::weak_ptr<Content>, int); + void film_content_changed (int); void set_general_sensitivity (bool); void setup_dcp_name (); diff --git a/src/wx/film_editor_panel.h b/src/wx/film_editor_panel.h index 8acb3efb6..e0514ba99 100644 --- a/src/wx/film_editor_panel.h +++ b/src/wx/film_editor_panel.h @@ -33,7 +33,10 @@ public: FilmEditorPanel (FilmEditor *, wxString); virtual void film_changed (Film::Property) {} - virtual void film_content_changed (boost::shared_ptr<Content>, int) = 0; + /** Called when a given property of one of the selected Contents changes */ + virtual void film_content_changed (int) = 0; + /** Called when the list of selected Contents changes */ + virtual void content_selection_changed () = 0; protected: FilmEditor* _editor; diff --git a/src/wx/multiple_widget.h b/src/wx/multiple_widget.h new file mode 100644 index 000000000..7c0b4a614 --- /dev/null +++ b/src/wx/multiple_widget.h @@ -0,0 +1,125 @@ +/* + 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. + +*/ + +#ifndef DCPOMATIC_MULTIPLE_WIDGET_H +#define DCPOMATIC_MULTIPLE_WIDGET_H + +#include <vector> +#include <wx/wx.h> +#include <wx/gbsizer.h> +#include <boost/function.hpp> +#include "wx_util.h" + +template <class T> +class MultipleWidget +{ +public: + MultipleWidget (wxWindow* parent, T* wrapped) + : _wrapped (wrapped) + , _sizer (0) + , _button (new wxButton (parent, wxID_ANY, _("Multiple values"))) + { + _button->SetToolTip (_("Click the button to set all selections to the same value")); + _button->Hide (); + _button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&MultipleWidget::button_clicked, this)); + } + + T* wrapped () const + { + return _wrapped; + } + + void add (wxGridBagSizer* sizer, wxGBPosition position) + { + _sizer = sizer; + _position = position; + _sizer->Add (_wrapped, _position); + } + + void set_single () + { + if (_wrapped->IsShown ()) { + return; + } + + _sizer->Detach (_button); + _button->Hide (); + _sizer->Add (_wrapped, _position); + _wrapped->Show (); + _sizer->Layout (); + } + + void set_multiple () + { + if (_button->IsShown ()) { + return; + } + + _wrapped->Hide (); + _sizer->Detach (_wrapped); + _button->Show (); + _sizer->Add (_button, _position); + _sizer->Layout (); + } + + boost::signals2::signal<void (void)> SetAllSame; + +private: + void button_clicked () + { + SetAllSame (); + } + + T* _wrapped; + wxGridBagSizer* _sizer; + wxGBPosition _position; + wxButton* _button; +}; + + +/** Set up some MultipleWidget<SpinCtrl> using a (possibly) multiple selection of objects of type T. + * The value is obtained from the T objects using getter. + */ +template <class T> +void +set_multiple (std::vector<boost::shared_ptr<T> > data, MultipleWidget<wxSpinCtrl>* widget, boost::function<int (T*)> getter) +{ + if (data.empty ()) { + widget->set_single (); + widget->wrapped()->SetValue (0); + return; + } + + typename std::vector<boost::shared_ptr<T> >::iterator i = data.begin(); + int first = boost::bind (getter, data.front().get()) (); + while (i != data.end() && boost::bind (getter, i->get())() == first) { + ++i; + } + + if (i == data.end ()) { + /* All values are the same */ + widget->set_single (); + checked_set (widget->wrapped(), first); + } else { + /* At least one different value */ + widget->set_multiple (); + } +} + +#endif diff --git a/src/wx/subtitle_panel.cc b/src/wx/subtitle_panel.cc index 8f2b08af5..c820220d4 100644 --- a/src/wx/subtitle_panel.cc +++ b/src/wx/subtitle_panel.cc @@ -89,32 +89,41 @@ SubtitlePanel::film_changed (Film::Property property) } void -SubtitlePanel::film_content_changed (shared_ptr<Content> c, int property) +SubtitlePanel::film_content_changed (int property) { - shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (c); - shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (c); + FFmpegContentList fc = _editor->selected_ffmpeg_content (); + SubtitleContentList sc = _editor->selected_subtitle_content (); + + shared_ptr<FFmpegContent> fcs; + if (fc.size() == 1) { + fcs = fc.front (); + } + + shared_ptr<SubtitleContent> scs; + if (sc.size() == 1) { + scs = sc.front (); + } if (property == FFmpegContentProperty::SUBTITLE_STREAMS) { _stream->Clear (); - if (fc) { - vector<shared_ptr<FFmpegSubtitleStream> > s = fc->subtitle_streams (); + if (fcs) { + vector<shared_ptr<FFmpegSubtitleStream> > s = fcs->subtitle_streams (); for (vector<shared_ptr<FFmpegSubtitleStream> >::iterator i = s.begin(); i != s.end(); ++i) { _stream->Append (std_to_wx ((*i)->name), new wxStringClientData (std_to_wx (lexical_cast<string> ((*i)->id)))); } - if (fc->subtitle_stream()) { - checked_set (_stream, lexical_cast<string> (fc->subtitle_stream()->id)); + if (fcs->subtitle_stream()) { + checked_set (_stream, lexical_cast<string> (fcs->subtitle_stream()->id)); } else { _stream->SetSelection (wxNOT_FOUND); } } setup_sensitivity (); } else if (property == SubtitleContentProperty::SUBTITLE_OFFSET) { - checked_set (_offset, sc ? (sc->subtitle_offset() * 100) : 0); + checked_set (_offset, scs ? (scs->subtitle_offset() * 100) : 0); } else if (property == SubtitleContentProperty::SUBTITLE_SCALE) { - checked_set (_scale, sc ? (sc->subtitle_scale() * 100) : 100); + checked_set (_scale, scs ? (scs->subtitle_scale() * 100) : 100); } - } void @@ -146,17 +155,14 @@ SubtitlePanel::setup_sensitivity () void SubtitlePanel::stream_changed () { - shared_ptr<Content> c = _editor->selected_content (); - if (!c) { - return; - } - - shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (c); - if (!fc) { + FFmpegContentList fc = _editor->selected_ffmpeg_content (); + if (fc.size() != 1) { return; } + + shared_ptr<FFmpegContent> fcs = fc.front (); - vector<shared_ptr<FFmpegSubtitleStream> > a = fc->subtitle_streams (); + vector<shared_ptr<FFmpegSubtitleStream> > a = fcs->subtitle_streams (); vector<shared_ptr<FFmpegSubtitleStream> >::iterator i = a.begin (); string const s = string_client_data (_stream->GetClientObject (_stream->GetSelection ())); while (i != a.end() && lexical_cast<string> ((*i)->id) != s) { @@ -164,29 +170,32 @@ SubtitlePanel::stream_changed () } if (i != a.end ()) { - fc->set_subtitle_stream (*i); + fcs->set_subtitle_stream (*i); } } void SubtitlePanel::offset_changed () { - shared_ptr<SubtitleContent> c = _editor->selected_subtitle_content (); - if (!c) { - return; + SubtitleContentList c = _editor->selected_subtitle_content (); + if (c.size() == 1) { + c.front()->set_subtitle_offset (_offset->GetValue() / 100.0); } - - c->set_subtitle_offset (_offset->GetValue() / 100.0); } void SubtitlePanel::scale_changed () { - shared_ptr<SubtitleContent> c = _editor->selected_subtitle_content (); - if (!c) { - return; + SubtitleContentList c = _editor->selected_subtitle_content (); + if (c.size() == 1) { + c.front()->set_subtitle_scale (_scale->GetValue() / 100.0); } +} + +void +SubtitlePanel::content_selection_changed () +{ - c->set_subtitle_scale (_scale->GetValue() / 100.0); } + diff --git a/src/wx/subtitle_panel.h b/src/wx/subtitle_panel.h index 3f7951895..19df26436 100644 --- a/src/wx/subtitle_panel.h +++ b/src/wx/subtitle_panel.h @@ -28,8 +28,8 @@ public: SubtitlePanel (FilmEditor *); void film_changed (Film::Property); - void film_content_changed (boost::shared_ptr<Content>, int); - + void film_content_changed (int); + void content_selection_changed (); private: void with_subtitles_toggled (); diff --git a/src/wx/timing_panel.cc b/src/wx/timing_panel.cc index ba645cf32..512a83cd9 100644 --- a/src/wx/timing_panel.cc +++ b/src/wx/timing_panel.cc @@ -54,8 +54,14 @@ TimingPanel::TimingPanel (FilmEditor* e) } void -TimingPanel::film_content_changed (shared_ptr<Content> content, int property) +TimingPanel::film_content_changed (int property) { + ContentList cl = _editor->selected_content (); + shared_ptr<Content> content; + if (cl.size() == 1) { + content = cl.front (); + } + if (property == ContentProperty::POSITION) { if (content) { _position->set (content->position (), _editor->film()->video_frame_rate ()); @@ -88,47 +94,45 @@ TimingPanel::film_content_changed (shared_ptr<Content> content, int property) void TimingPanel::position_changed () { - shared_ptr<Content> c = _editor->selected_content (); - if (!c) { - return; + ContentList c = _editor->selected_content (); + if (c.size() == 1) { + c.front()->set_position (_position->get (_editor->film()->video_frame_rate ())); } - - c->set_position (_position->get (_editor->film()->video_frame_rate ())); } void TimingPanel::length_changed () { - shared_ptr<Content> c = _editor->selected_content (); - if (!c) { - return; - } - - shared_ptr<StillImageContent> ic = dynamic_pointer_cast<StillImageContent> (c); - if (ic) { - ic->set_video_length (rint (_length->get (_editor->film()->video_frame_rate()) * ic->video_frame_rate() / TIME_HZ)); + ContentList c = _editor->selected_content (); + if (c.size() == 1) { + shared_ptr<StillImageContent> ic = dynamic_pointer_cast<StillImageContent> (c.front ()); + if (ic) { + ic->set_video_length (rint (_length->get (_editor->film()->video_frame_rate()) * ic->video_frame_rate() / TIME_HZ)); + } } } void TimingPanel::trim_start_changed () { - shared_ptr<Content> c = _editor->selected_content (); - if (!c) { - return; + ContentList c = _editor->selected_content (); + if (c.size() == 1) { + c.front()->set_trim_start (_trim_start->get (_editor->film()->video_frame_rate ())); } - - c->set_trim_start (_trim_start->get (_editor->film()->video_frame_rate ())); } void TimingPanel::trim_end_changed () { - shared_ptr<Content> c = _editor->selected_content (); - if (!c) { - return; + ContentList c = _editor->selected_content (); + if (c.size() == 1) { + c.front()->set_trim_end (_trim_end->get (_editor->film()->video_frame_rate ())); } +} + +void +TimingPanel::content_selection_changed () +{ - c->set_trim_end (_trim_end->get (_editor->film()->video_frame_rate ())); } diff --git a/src/wx/timing_panel.h b/src/wx/timing_panel.h index b84ea52be..8c519bcbe 100644 --- a/src/wx/timing_panel.h +++ b/src/wx/timing_panel.h @@ -26,7 +26,8 @@ class TimingPanel : public FilmEditorPanel public: TimingPanel (FilmEditor *); - void film_content_changed (boost::shared_ptr<Content>, int); + void film_content_changed (int); + void content_selection_changed (); private: void position_changed (); diff --git a/src/wx/video_panel.cc b/src/wx/video_panel.cc index a643832e8..3b4dc7e46 100644 --- a/src/wx/video_panel.cc +++ b/src/wx/video_panel.cc @@ -29,6 +29,7 @@ #include "wx_util.h" #include "film_editor.h" #include "content_colour_conversion_dialog.h" +#include "multiple_widget.h" using std::vector; using std::string; @@ -54,23 +55,23 @@ VideoPanel::VideoPanel (FilmEditor* e) ++r; add_label_to_grid_bag_sizer (grid, this, _("Left crop"), true, wxGBPosition (r, 0)); - _left_crop = new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1)); - grid->Add (_left_crop, wxGBPosition (r, 1)); + _left_crop = new MultipleWidget<wxSpinCtrl> (this, new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1))); + _left_crop->add (grid, wxGBPosition (r, 1)); ++r; add_label_to_grid_bag_sizer (grid, this, _("Right crop"), true, wxGBPosition (r, 0)); - _right_crop = new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1)); - grid->Add (_right_crop, wxGBPosition (r, 1)); + _right_crop = new MultipleWidget<wxSpinCtrl> (this, new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1))); + _right_crop->add (grid, wxGBPosition (r, 1)); ++r; add_label_to_grid_bag_sizer (grid, this, _("Top crop"), true, wxGBPosition (r, 0)); - _top_crop = new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1)); - grid->Add (_top_crop, wxGBPosition (r, 1)); + _top_crop = new MultipleWidget<wxSpinCtrl> (this, new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1))); + _top_crop->add (grid, wxGBPosition (r,1 )); ++r; add_label_to_grid_bag_sizer (grid, this, _("Bottom crop"), true, wxGBPosition (r, 0)); - _bottom_crop = new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1)); - grid->Add (_bottom_crop, wxGBPosition (r, 1)); + _bottom_crop = new MultipleWidget<wxSpinCtrl> (this, new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1))); + _bottom_crop->add (grid, wxGBPosition (r, 1)); ++r; add_label_to_grid_bag_sizer (grid, this, _("Scale to"), true, wxGBPosition (r, 0)); @@ -119,10 +120,10 @@ VideoPanel::VideoPanel (FilmEditor* e) _description->SetFont(font); ++r; - _left_crop->SetRange (0, 1024); - _top_crop->SetRange (0, 1024); - _right_crop->SetRange (0, 1024); - _bottom_crop->SetRange (0, 1024); + _left_crop->wrapped()->SetRange (0, 1024); + _top_crop->wrapped()->SetRange (0, 1024); + _right_crop->wrapped()->SetRange (0, 1024); + _bottom_crop->wrapped()->SetRange (0, 1024); vector<Ratio const *> ratios = Ratio::all (); _ratio->Clear (); @@ -135,10 +136,11 @@ VideoPanel::VideoPanel (FilmEditor* e) _frame_type->Append (_("3D left/right")); _frame_type->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&VideoPanel::frame_type_changed, this)); - _left_crop->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&VideoPanel::left_crop_changed, this)); - _right_crop->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&VideoPanel::right_crop_changed, this)); - _top_crop->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&VideoPanel::top_crop_changed, this)); - _bottom_crop->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&VideoPanel::bottom_crop_changed, this)); + _left_crop->SetAllSame.connect (boost::bind (&VideoPanel::set_left_crop_same, this)); + _left_crop->wrapped()->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&VideoPanel::left_crop_changed, this)); + _right_crop->wrapped()->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&VideoPanel::right_crop_changed, this)); + _top_crop->wrapped()->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&VideoPanel::top_crop_changed, this)); + _bottom_crop->wrapped()->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&VideoPanel::bottom_crop_changed, this)); _ratio->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&VideoPanel::ratio_changed, this)); _filters_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&VideoPanel::edit_filters_clicked, this)); _colour_conversion_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&VideoPanel::edit_colour_conversion_clicked, this)); @@ -149,48 +151,40 @@ VideoPanel::VideoPanel (FilmEditor* e) void VideoPanel::left_crop_changed () { - shared_ptr<VideoContent> c = _editor->selected_video_content (); - if (!c) { - return; + VideoContentList c = _editor->selected_video_content (); + for (VideoContentList::iterator i = c.begin(); i != c.end(); ++i) { + (*i)->set_left_crop (_left_crop->wrapped()->GetValue ()); } - - c->set_left_crop (_left_crop->GetValue ()); } /** Called when the right crop widget has been changed */ void VideoPanel::right_crop_changed () { - shared_ptr<VideoContent> c = _editor->selected_video_content (); - if (!c) { - return; + VideoContentList c = _editor->selected_video_content (); + for (VideoContentList::iterator i = c.begin(); i != c.end(); ++i) { + (*i)->set_right_crop (_right_crop->wrapped()->GetValue ()); } - - c->set_right_crop (_right_crop->GetValue ()); } /** Called when the top crop widget has been changed */ void VideoPanel::top_crop_changed () { - shared_ptr<VideoContent> c = _editor->selected_video_content (); - if (!c) { - return; + VideoContentList c = _editor->selected_video_content (); + for (VideoContentList::iterator i = c.begin(); i != c.end(); ++i) { + (*i)->set_top_crop (_top_crop->wrapped()->GetValue ()); } - - c->set_top_crop (_top_crop->GetValue ()); } /** Called when the bottom crop value has been changed */ void VideoPanel::bottom_crop_changed () { - shared_ptr<VideoContent> c = _editor->selected_video_content (); - if (!c) { - return; + VideoContentList c = _editor->selected_video_content (); + for (VideoContentList::iterator i = c.begin(); i != c.end(); ++i) { + (*i)->set_bottom_crop (_bottom_crop->wrapped()->GetValue ()); } - - c->set_bottom_crop (_bottom_crop->GetValue ()); } void @@ -207,26 +201,31 @@ VideoPanel::film_changed (Film::Property property) } void -VideoPanel::film_content_changed (shared_ptr<Content> c, int property) +VideoPanel::film_content_changed (int property) { - shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (c); - shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (c); - + VideoContentList vc = _editor->selected_video_content (); + shared_ptr<VideoContent> vcs; + shared_ptr<FFmpegContent> fcs; + if (!vc.empty ()) { + vcs = vc.front (); + fcs = dynamic_pointer_cast<FFmpegContent> (vcs); + } + if (property == VideoContentProperty::VIDEO_FRAME_TYPE) { - checked_set (_frame_type, vc ? vc->video_frame_type () : VIDEO_FRAME_TYPE_2D); + checked_set (_frame_type, vcs ? vcs->video_frame_type () : VIDEO_FRAME_TYPE_2D); setup_description (); } else if (property == VideoContentProperty::VIDEO_CROP) { - checked_set (_left_crop, vc ? vc->crop().left : 0); - checked_set (_right_crop, vc ? vc->crop().right : 0); - checked_set (_top_crop, vc ? vc->crop().top : 0); - checked_set (_bottom_crop, vc ? vc->crop().bottom : 0); + set_multiple<VideoContent> (vc, _left_crop, &VideoContent::left_crop); + set_multiple<VideoContent> (vc, _right_crop, &VideoContent::right_crop); + set_multiple<VideoContent> (vc, _top_crop, &VideoContent::top_crop); + set_multiple<VideoContent> (vc, _bottom_crop, &VideoContent::bottom_crop); setup_description (); } else if (property == VideoContentProperty::VIDEO_RATIO) { - if (vc) { + if (vcs) { int n = 0; vector<Ratio const *> ratios = Ratio::all (); vector<Ratio const *>::iterator i = ratios.begin (); - while (i != ratios.end() && *i != vc->ratio()) { + while (i != ratios.end() && *i != vcs->ratio()) { ++i; ++n; } @@ -243,12 +242,12 @@ VideoPanel::film_content_changed (shared_ptr<Content> c, int property) } else if (property == VideoContentProperty::VIDEO_FRAME_RATE) { setup_description (); } else if (property == VideoContentProperty::COLOUR_CONVERSION) { - optional<size_t> preset = vc ? vc->colour_conversion().preset () : optional<size_t> (); + optional<size_t> preset = vcs ? vcs->colour_conversion().preset () : optional<size_t> (); vector<PresetColourConversion> cc = Config::instance()->colour_conversions (); _colour_conversion->SetLabel (preset ? std_to_wx (cc[preset.get()].name) : _("Custom")); } else if (property == FFmpegContentProperty::FILTERS) { - if (fc) { - pair<string, string> p = Filter::ffmpeg_strings (fc->filters ()); + if (fcs) { + pair<string, string> p = Filter::ffmpeg_strings (fcs->filters ()); if (p.first.empty () && p.second.empty ()) { _filters->SetLabel (_("None")); } else { @@ -263,18 +262,13 @@ VideoPanel::film_content_changed (shared_ptr<Content> c, int property) void VideoPanel::edit_filters_clicked () { - shared_ptr<Content> c = _editor->selected_content (); - if (!c) { + FFmpegContentList c = _editor->selected_ffmpeg_content (); + if (c.size() != 1) { return; } - shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (c); - if (!fc) { - return; - } - - FilterDialog* d = new FilterDialog (this, fc->filters()); - d->ActiveChanged.connect (bind (&FFmpegContent::set_filters, fc, _1)); + FilterDialog* d = new FilterDialog (this, c.front()->filters()); + d->ActiveChanged.connect (bind (&FFmpegContent::set_filters, c.front(), _1)); d->ShowModal (); d->Destroy (); } @@ -282,29 +276,34 @@ VideoPanel::edit_filters_clicked () void VideoPanel::setup_description () { - shared_ptr<VideoContent> vc = _editor->selected_video_content (); - if (!vc) { + FFmpegContentList vc = _editor->selected_ffmpeg_content (); + if (vc.empty ()) { _description->SetLabel (""); return; + } else if (vc.size() > 1) { + _description->SetLabel (_("Multiple content selected")); + return; } + shared_ptr<FFmpegContent> vcs = vc.front (); + wxString d; int lines = 0; - if (vc->video_size().width && vc->video_size().height) { + if (vcs->video_size().width && vcs->video_size().height) { d << wxString::Format ( _("Content video is %dx%d (%.2f:1)\n"), - vc->video_size_after_3d_split().width, - vc->video_size_after_3d_split().height, - vc->video_size_after_3d_split().ratio () + vcs->video_size_after_3d_split().width, + vcs->video_size_after_3d_split().height, + vcs->video_size_after_3d_split().ratio () ); ++lines; } - Crop const crop = vc->crop (); - if ((crop.left || crop.right || crop.top || crop.bottom) && vc->video_size() != libdcp::Size (0, 0)) { - libdcp::Size cropped = vc->video_size_after_crop (); + Crop const crop = vcs->crop (); + if ((crop.left || crop.right || crop.top || crop.bottom) && vcs->video_size() != libdcp::Size (0, 0)) { + libdcp::Size cropped = vcs->video_size_after_crop (); d << wxString::Format ( _("Cropped to %dx%d (%.2f:1)\n"), cropped.width, cropped.height, @@ -313,9 +312,9 @@ VideoPanel::setup_description () ++lines; } - Ratio const * ratio = vc->ratio (); + Ratio const * ratio = vcs->ratio (); libdcp::Size container_size = fit_ratio_within (_editor->film()->container()->ratio (), _editor->film()->full_frame ()); - float const ratio_value = ratio ? ratio->ratio() : vc->video_size_after_crop().ratio (); + float const ratio_value = ratio ? ratio->ratio() : vcs->video_size_after_crop().ratio (); /* We have a specified ratio to scale to */ libdcp::Size const scaled = fit_ratio_within (ratio_value, container_size); @@ -336,9 +335,9 @@ VideoPanel::setup_description () ++lines; } - d << wxString::Format (_("Content frame rate %.4f\n"), vc->video_frame_rate ()); + d << wxString::Format (_("Content frame rate %.4f\n"), vcs->video_frame_rate ()); ++lines; - FrameRateConversion frc (vc->video_frame_rate(), _editor->film()->video_frame_rate ()); + FrameRateConversion frc (vcs->video_frame_rate(), _editor->film()->video_frame_rate ()); d << frc.description << "\n"; ++lines; @@ -358,15 +357,18 @@ VideoPanel::ratio_changed () return; } - shared_ptr<VideoContent> vc = _editor->selected_video_content (); + VideoContentList vc = _editor->selected_video_content (); + if (vc.size() != 1) { + return; + } int const n = _ratio->GetSelection (); if (n >= 0) { vector<Ratio const *> ratios = Ratio::all (); if (n < int (ratios.size ())) { - vc->set_ratio (ratios[n]); + vc.front()->set_ratio (ratios[n]); } else { - vc->set_ratio (0); + vc.front()->set_ratio (0); } } } @@ -374,25 +376,62 @@ VideoPanel::ratio_changed () void VideoPanel::frame_type_changed () { - shared_ptr<VideoContent> vc = _editor->selected_video_content (); - if (vc) { - vc->set_video_frame_type (static_cast<VideoFrameType> (_frame_type->GetSelection ())); + VideoContentList vc = _editor->selected_video_content (); + if (vc.size() == 1) { + vc.front()->set_video_frame_type (static_cast<VideoFrameType> (_frame_type->GetSelection ())); } } void VideoPanel::edit_colour_conversion_clicked () { - shared_ptr<VideoContent> vc = _editor->selected_video_content (); - if (!vc) { + VideoContentList vc = _editor->selected_video_content (); + if (vc.size() != 1) { return; } - ColourConversion conversion = vc->colour_conversion (); + ColourConversion conversion = vc.front()->colour_conversion (); ContentColourConversionDialog* d = new ContentColourConversionDialog (this); d->set (conversion); d->ShowModal (); - vc->set_colour_conversion (d->get ()); + vc.front()->set_colour_conversion (d->get ()); d->Destroy (); } + +void +VideoPanel::content_selection_changed () +{ + VideoContentList sel = _editor->selected_video_content (); + bool const single = sel.size() == 1; + bool const multiple = sel.size() > 1; + + /* Things that are allowed with multiple selections */ + _left_crop->wrapped()->Enable (single || multiple); + _right_crop->wrapped()->Enable (single || multiple); + _top_crop->wrapped()->Enable (single || multiple); + _bottom_crop->wrapped()->Enable (single || multiple); + + /* Things that are only allowed with single selections */ + _frame_type->Enable (single); + _ratio->Enable (single); + _filters_button->Enable (single); + _colour_conversion_button->Enable (single); + + film_content_changed (VideoContentProperty::VIDEO_FRAME_TYPE); + film_content_changed (VideoContentProperty::VIDEO_CROP); + film_content_changed (VideoContentProperty::VIDEO_RATIO); + film_content_changed (VideoContentProperty::VIDEO_FRAME_RATE); + film_content_changed (VideoContentProperty::COLOUR_CONVERSION); + film_content_changed (FFmpegContentProperty::FILTERS); +} + +void +VideoPanel::set_left_crop_same () +{ + VideoContentList sel = _editor->selected_video_content (); + for (VideoContentList::iterator i = sel.begin(); i != sel.end(); ++i) { + (*i)->set_left_crop (sel.front()->left_crop ()); + } +} + diff --git a/src/wx/video_panel.h b/src/wx/video_panel.h index 2ecf3c87f..5b0c95880 100644 --- a/src/wx/video_panel.h +++ b/src/wx/video_panel.h @@ -19,6 +19,7 @@ #include "lib/film.h" #include "film_editor_panel.h" +#include "multiple_widget.h" class wxChoice; class wxStaticText; @@ -31,9 +32,11 @@ public: VideoPanel (FilmEditor *); void film_changed (Film::Property); - void film_content_changed (boost::shared_ptr<Content>, int); + void film_content_changed (int); + void content_selection_changed (); private: + void set_left_crop_same (); void left_crop_changed (); void right_crop_changed (); void top_crop_changed (); @@ -46,10 +49,10 @@ private: void setup_description (); wxChoice* _frame_type; - wxSpinCtrl* _left_crop; - wxSpinCtrl* _right_crop; - wxSpinCtrl* _top_crop; - wxSpinCtrl* _bottom_crop; + MultipleWidget<wxSpinCtrl>* _left_crop; + MultipleWidget<wxSpinCtrl>* _right_crop; + MultipleWidget<wxSpinCtrl>* _top_crop; + MultipleWidget<wxSpinCtrl>* _bottom_crop; wxChoice* _ratio; wxStaticText* _ratio_description; wxStaticText* _description; |
