diff options
| author | Carl Hetherington <cth@carlh.net> | 2013-07-30 21:34:16 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2013-07-30 21:34:16 +0100 |
| commit | c57e92b12c64d4ad1a7f23876a97471565f9a252 (patch) | |
| tree | 008213d35e4be34c55caa51760ab7aef6fa33113 /src | |
| parent | e241b3d295fe4158239170f17391e08473e159c5 (diff) | |
Somewhat untested and sketchy basics of trimming.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/content.cc | 68 | ||||
| -rw-r--r-- | src/lib/content.h | 39 | ||||
| -rw-r--r-- | src/lib/ffmpeg_content.cc | 2 | ||||
| -rw-r--r-- | src/lib/ffmpeg_content.h | 2 | ||||
| -rw-r--r-- | src/lib/film.cc | 2 | ||||
| -rw-r--r-- | src/lib/moving_image_content.cc | 2 | ||||
| -rw-r--r-- | src/lib/moving_image_content.h | 2 | ||||
| -rw-r--r-- | src/lib/player.cc | 47 | ||||
| -rw-r--r-- | src/lib/playlist.cc | 11 | ||||
| -rw-r--r-- | src/lib/sndfile_content.cc | 2 | ||||
| -rw-r--r-- | src/lib/sndfile_content.h | 2 | ||||
| -rw-r--r-- | src/lib/still_image_content.cc | 2 | ||||
| -rw-r--r-- | src/lib/still_image_content.h | 2 | ||||
| -rw-r--r-- | src/wx/film_editor.cc | 4 | ||||
| -rw-r--r-- | src/wx/timeline.cc | 40 | ||||
| -rw-r--r-- | src/wx/timeline.h | 4 | ||||
| -rw-r--r-- | src/wx/timing_panel.cc | 67 | ||||
| -rw-r--r-- | src/wx/timing_panel.h | 8 |
18 files changed, 219 insertions, 87 deletions
diff --git a/src/lib/content.cc b/src/lib/content.cc index 372be3020..950814491 100644 --- a/src/lib/content.cc +++ b/src/lib/content.cc @@ -30,12 +30,16 @@ using std::set; using boost::shared_ptr; using boost::lexical_cast; -int const ContentProperty::START = 400; +int const ContentProperty::POSITION = 400; int const ContentProperty::LENGTH = 401; +int const ContentProperty::TRIM_START = 402; +int const ContentProperty::TRIM_END = 403; -Content::Content (shared_ptr<const Film> f, Time s) +Content::Content (shared_ptr<const Film> f, Time p) : _film (f) - , _start (s) + , _position (p) + , _trim_start (0) + , _trim_end (0) , _change_signals_frequent (false) { @@ -44,7 +48,9 @@ Content::Content (shared_ptr<const Film> f, Time s) Content::Content (shared_ptr<const Film> f, boost::filesystem::path p) : _film (f) , _path (p) - , _start (0) + , _position (0) + , _trim_start (0) + , _trim_end (0) , _change_signals_frequent (false) { @@ -56,7 +62,9 @@ Content::Content (shared_ptr<const Film> f, shared_ptr<const cxml::Node> node) { _path = node->string_child ("Path"); _digest = node->string_child ("Digest"); - _start = node->number_child<Time> ("Start"); + _position = node->number_child<Time> ("Position"); + _trim_start = node->number_child<Time> ("TrimStart"); + _trim_end = node->number_child<Time> ("TrimEnd"); } void @@ -65,7 +73,9 @@ Content::as_xml (xmlpp::Node* node) const boost::mutex::scoped_lock lm (_mutex); node->add_child("Path")->add_child_text (_path.string()); node->add_child("Digest")->add_child_text (_digest); - node->add_child("Start")->add_child_text (lexical_cast<string> (_start)); + node->add_child("Position")->add_child_text (lexical_cast<string> (_position)); + node->add_child("TrimStart")->add_child_text (lexical_cast<string> (_trim_start)); + node->add_child("TrimEnd")->add_child_text (lexical_cast<string> (_trim_end)); } void @@ -91,16 +101,39 @@ Content::signal_changed (int p) } void -Content::set_start (Time s) +Content::set_position (Time p) { { boost::mutex::scoped_lock lm (_mutex); - _start = s; + _position = p; } - signal_changed (ContentProperty::START); + signal_changed (ContentProperty::POSITION); } +void +Content::set_trim_start (Time t) +{ + { + boost::mutex::scoped_lock lm (_mutex); + _trim_start = t; + } + + signal_changed (ContentProperty::TRIM_START); +} + +void +Content::set_trim_end (Time t) +{ + { + boost::mutex::scoped_lock lm (_mutex); + _trim_end = t; + } + + signal_changed (ContentProperty::TRIM_END); +} + + shared_ptr<Content> Content::clone () const { @@ -119,5 +152,20 @@ Content::clone () const string Content::technical_summary () const { - return String::compose ("%1 %2 %3", path(), digest(), start()); + return String::compose ("%1 %2 %3", path(), digest(), position()); +} + +Time +Content::length_after_trim () const +{ + return full_length () - _trim_start - _trim_end; +} + +/** @param t A time relative to the start of this content (not the position). + * @return true if this time is trimmed by our trim settings. + */ +bool +Content::trimmed (Time t) const +{ + return (t < trim_start() || t > (full_length() - trim_end ())); } diff --git a/src/lib/content.h b/src/lib/content.h index 78b80e254..e3f559752 100644 --- a/src/lib/content.h +++ b/src/lib/content.h @@ -38,8 +38,10 @@ class Film; class ContentProperty { public: - static int const START; + static int const POSITION; static int const LENGTH; + static int const TRIM_START; + static int const TRIM_END; }; class Content : public boost::enable_shared_from_this<Content>, public boost::noncopyable @@ -55,7 +57,7 @@ public: virtual std::string technical_summary () const; virtual std::string information () const = 0; virtual void as_xml (xmlpp::Node *) const; - virtual Time length () const = 0; + virtual Time full_length () const = 0; boost::shared_ptr<Content> clone () const; @@ -70,21 +72,42 @@ public: return _digest; } - void set_start (Time); + void set_position (Time); - Time start () const { + /** Time that this content starts; i.e. the time that the first + * bit of the content (trimmed or not) will happen. + */ + Time position () const { boost::mutex::scoped_lock lm (_mutex); - return _start; + return _position; } + void set_trim_start (Time); + + Time trim_start () const { + boost::mutex::scoped_lock lm (_mutex); + return _trim_start; + } + + void set_trim_end (Time); + + Time trim_end () const { + boost::mutex::scoped_lock lm (_mutex); + return _trim_end; + } + Time end () const { - return start() + length(); + return position() + length_after_trim(); } + Time length_after_trim () const; + void set_change_signals_frequent (bool f) { _change_signals_frequent = f; } + bool trimmed (Time) const; + boost::signals2::signal<void (boost::weak_ptr<Content>, int, bool)> Changed; protected: @@ -97,7 +120,9 @@ private: /** Path of a file or a directory containing files */ boost::filesystem::path _path; std::string _digest; - Time _start; + Time _position; + Time _trim_start; + Time _trim_end; bool _change_signals_frequent; }; diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc index 84be76d27..de967c045 100644 --- a/src/lib/ffmpeg_content.cc +++ b/src/lib/ffmpeg_content.cc @@ -346,7 +346,7 @@ FFmpegSubtitleStream::as_xml (xmlpp::Node* root) const } Time -FFmpegContent::length () const +FFmpegContent::full_length () const { shared_ptr<const Film> film = _film.lock (); assert (film); diff --git a/src/lib/ffmpeg_content.h b/src/lib/ffmpeg_content.h index 96d8c1727..775cb9220 100644 --- a/src/lib/ffmpeg_content.h +++ b/src/lib/ffmpeg_content.h @@ -107,7 +107,7 @@ public: std::string technical_summary () const; std::string information () const; void as_xml (xmlpp::Node *) const; - Time length () const; + Time full_length () const; std::string identifier () const; diff --git a/src/lib/film.cc b/src/lib/film.cc index 13c1558e9..2f7e07873 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -806,7 +806,7 @@ Film::add_content (shared_ptr<Content> c) { /* Add video content after any existing content */ if (dynamic_pointer_cast<VideoContent> (c)) { - c->set_start (_playlist->video_end ()); + c->set_position (_playlist->video_end ()); } _playlist->add (c); diff --git a/src/lib/moving_image_content.cc b/src/lib/moving_image_content.cc index 30030d9fd..63b4b9f24 100644 --- a/src/lib/moving_image_content.cc +++ b/src/lib/moving_image_content.cc @@ -94,7 +94,7 @@ MovingImageContent::examine (shared_ptr<Job> job) } Time -MovingImageContent::length () const +MovingImageContent::full_length () const { shared_ptr<const Film> film = _film.lock (); assert (film); diff --git a/src/lib/moving_image_content.h b/src/lib/moving_image_content.h index 2b3c48dd1..1a64750fe 100644 --- a/src/lib/moving_image_content.h +++ b/src/lib/moving_image_content.h @@ -42,7 +42,7 @@ public: std::string summary () const; std::string technical_summary () const; void as_xml (xmlpp::Node *) const; - Time length () const; + Time full_length () const; std::string identifier () const; diff --git a/src/lib/player.cc b/src/lib/player.cc index 33a5bbfef..63cf4ee7f 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -55,15 +55,15 @@ class Piece public: Piece (shared_ptr<Content> c) : content (c) - , video_position (c->start ()) - , audio_position (c->start ()) + , video_position (c->position ()) + , audio_position (c->position ()) {} Piece (shared_ptr<Content> c, shared_ptr<Decoder> d) : content (c) , decoder (d) - , video_position (c->start ()) - , audio_position (c->start ()) + , video_position (c->position ()) + , audio_position (c->position ()) {} shared_ptr<Content> content; @@ -83,7 +83,7 @@ std::ostream& operator<<(std::ostream& s, Piece const & p) s << "\tsndfile "; } - s << " at " << p.content->start() << " until " << p.content->end(); + s << " at " << p.content->position() << " until " << p.content->end(); return s; } @@ -248,14 +248,19 @@ Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const Image> image return; } + Time const relative_time = (frame * frc.factor() * TIME_HZ / _film->video_frame_rate()); + if (content->trimmed (relative_time)) { + return; + } + shared_ptr<Image> work_image = image->crop (content->crop(), true); libdcp::Size const image_size = content->ratio()->size (_video_container_size); work_image = work_image->scale_and_convert_to_rgb (image_size, _film->scaler(), true); - Time time = content->start() + (frame * frc.factor() * TIME_HZ / _film->video_frame_rate()); - + Time time = content->position() + relative_time - content->trim_start (); + if (_film->with_subtitles () && _out_subtitle.image && time >= _out_subtitle.from && time <= _out_subtitle.to) { work_image->alpha_blend (_out_subtitle.image, _out_subtitle.position); } @@ -297,6 +302,15 @@ Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers shared_ptr<AudioContent> content = dynamic_pointer_cast<AudioContent> (piece->content); assert (content); + Time const relative_time = _film->audio_frames_to_time (frame) + + (content->audio_delay() * TIME_HZ / 1000); + + if (content->trimmed (relative_time)) { + return; + } + + Time time = content->position() + relative_time; + /* Resample */ if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) { shared_ptr<Resampler> r = resampler (content, true); @@ -317,10 +331,6 @@ Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers audio = dcp_mapped; - Time time = content->start() - + _film->audio_frames_to_time (frame) - + (content->audio_delay() * TIME_HZ / 1000); - /* We must cut off anything that comes before the start of all time */ if (time < 0) { int const frames = - time * _film->audio_frame_rate() / TIME_HZ; @@ -380,18 +390,18 @@ Player::seek (Time t, bool accurate) continue; } - Time s = t - vc->start (); + Time s = t - vc->position (); s = max (static_cast<Time> (0), s); - s = min (vc->length(), s); + s = min (vc->length_after_trim(), s); - (*i)->video_position = (*i)->audio_position = vc->start() + s; + (*i)->video_position = (*i)->audio_position = vc->position() + s; FrameRateConversion frc (vc->video_frame_rate(), _film->video_frame_rate()); /* Here we are converting from time (in the DCP) to a frame number in the content. Hence we need to use the DCP's frame rate and the double/skip correction, not the source's rate. */ - VideoContent::Frame f = s * _film->video_frame_rate() / (frc.factor() * TIME_HZ); + VideoContent::Frame f = (s + vc->trim_start ()) * _film->video_frame_rate() / (frc.factor() * TIME_HZ); dynamic_pointer_cast<VideoDecoder>((*i)->decoder)->seek (f, accurate); } @@ -487,7 +497,8 @@ Player::content_changed (weak_ptr<Content> w, int property, bool frequent) } if ( - property == ContentProperty::START || property == ContentProperty::LENGTH || + property == ContentProperty::POSITION || property == ContentProperty::LENGTH || + property == ContentProperty::TRIM_START || property == ContentProperty::TRIM_END || property == VideoContentProperty::VIDEO_CROP || property == VideoContentProperty::VIDEO_RATIO ) { @@ -622,6 +633,6 @@ Player::update_subtitle () _out_subtitle.position.y = rint (_video_container_size.height * (in_rect.y + (in_rect.height * (1 - sc->subtitle_scale ()) / 2))); _out_subtitle.image = _in_subtitle.image->scale (libdcp::Size (scaled_size.width, scaled_size.height), Scaler::from_id ("bicubic"), true); - _out_subtitle.from = _in_subtitle.from + piece->content->start (); - _out_subtitle.to = _in_subtitle.to + piece->content->start (); + _out_subtitle.from = _in_subtitle.from + piece->content->position (); + _out_subtitle.to = _in_subtitle.to + piece->content->position (); } diff --git a/src/lib/playlist.cc b/src/lib/playlist.cc index e9ea3e3c7..de48ff5f5 100644 --- a/src/lib/playlist.cc +++ b/src/lib/playlist.cc @@ -72,7 +72,6 @@ Playlist::content_changed (weak_ptr<Content> content, int property, bool frequen ContentChanged (content, property, frequent); } - void Playlist::maybe_sequence_video () { @@ -90,7 +89,7 @@ Playlist::maybe_sequence_video () continue; } - (*i)->set_start (last); + (*i)->set_position (last); last = (*i)->end (); } @@ -295,7 +294,7 @@ Playlist::set_sequence_video (bool s) bool ContentSorter::operator() (shared_ptr<Content> a, shared_ptr<Content> b) { - return a->start() < b->start(); + return a->position() < b->position(); } /** @return content in an undefined order */ @@ -310,8 +309,8 @@ Playlist::repeat (ContentList c, int n) { pair<Time, Time> range (TIME_MAX, 0); for (ContentList::iterator i = c.begin(); i != c.end(); ++i) { - range.first = min (range.first, (*i)->start ()); - range.second = max (range.second, (*i)->start ()); + range.first = min (range.first, (*i)->position ()); + range.second = max (range.second, (*i)->position ()); range.first = min (range.first, (*i)->end ()); range.second = max (range.second, (*i)->end ()); } @@ -320,7 +319,7 @@ Playlist::repeat (ContentList c, int n) for (int i = 0; i < n; ++i) { for (ContentList::iterator i = c.begin(); i != c.end(); ++i) { shared_ptr<Content> copy = (*i)->clone (); - copy->set_start (pos + copy->start() - range.first); + copy->set_position (pos + copy->position() - range.first); _content.push_back (copy); } pos += range.second - range.first; diff --git a/src/lib/sndfile_content.cc b/src/lib/sndfile_content.cc index 2ca00cf6d..fc6f45d00 100644 --- a/src/lib/sndfile_content.cc +++ b/src/lib/sndfile_content.cc @@ -136,7 +136,7 @@ SndfileContent::as_xml (xmlpp::Node* node) const } Time -SndfileContent::length () const +SndfileContent::full_length () const { shared_ptr<const Film> film = _film.lock (); assert (film); diff --git a/src/lib/sndfile_content.h b/src/lib/sndfile_content.h index 27e0ca21d..191d62527 100644 --- a/src/lib/sndfile_content.h +++ b/src/lib/sndfile_content.h @@ -44,7 +44,7 @@ public: std::string technical_summary () const; std::string information () const; void as_xml (xmlpp::Node *) const; - Time length () const; + Time full_length () const; /* AudioContent */ int audio_channels () const { diff --git a/src/lib/still_image_content.cc b/src/lib/still_image_content.cc index 5a3fed1b3..0cf80b546 100644 --- a/src/lib/still_image_content.cc +++ b/src/lib/still_image_content.cc @@ -94,7 +94,7 @@ StillImageContent::set_video_length (VideoContent::Frame len) } Time -StillImageContent::length () const +StillImageContent::full_length () const { shared_ptr<const Film> film = _film.lock (); assert (film); diff --git a/src/lib/still_image_content.h b/src/lib/still_image_content.h index 24d5174a0..ccd7fbc03 100644 --- a/src/lib/still_image_content.h +++ b/src/lib/still_image_content.h @@ -42,7 +42,7 @@ public: std::string summary () const; std::string technical_summary () const; void as_xml (xmlpp::Node *) const; - Time length () const; + Time full_length () const; std::string identifier () const; diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc index 914dc6136..c0e169835 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -733,8 +733,10 @@ FilmEditor::content_selection_changed () /* All other sensitivity in content panels should be triggered by one of these. */ - film_content_changed (s, ContentProperty::START); + 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); diff --git a/src/wx/timeline.cc b/src/wx/timeline.cc index f6e0dabb6..7c0690084 100644 --- a/src/wx/timeline.cc +++ b/src/wx/timeline.cc @@ -92,9 +92,9 @@ public: } return dcpomatic::Rect<int> ( - time_x (content->start ()) - 8, + time_x (content->position ()) - 8, y_pos (_track) - 8, - content->length () * _timeline.pixels_per_time_unit() + 16, + content->length_after_trim () * _timeline.pixels_per_time_unit() + 16, _timeline.track_height() + 16 ); } @@ -133,8 +133,8 @@ private: return; } - Time const start = cont->start (); - Time const len = cont->length (); + Time const position = cont->position (); + Time const len = cont->length_after_trim (); wxColour selected (colour().Red() / 2, colour().Green() / 2, colour().Blue() / 2); @@ -148,11 +148,11 @@ private: } wxGraphicsPath path = gc->CreatePath (); - path.MoveToPoint (time_x (start), y_pos (_track) + 4); - path.AddLineToPoint (time_x (start + len), y_pos (_track) + 4); - path.AddLineToPoint (time_x (start + len), y_pos (_track + 1) - 4); - path.AddLineToPoint (time_x (start), y_pos (_track + 1) - 4); - path.AddLineToPoint (time_x (start), y_pos (_track) + 4); + path.MoveToPoint (time_x (position), y_pos (_track) + 4); + path.AddLineToPoint (time_x (position + len), y_pos (_track) + 4); + path.AddLineToPoint (time_x (position + len), y_pos (_track + 1) - 4); + path.AddLineToPoint (time_x (position), y_pos (_track + 1) - 4); + path.AddLineToPoint (time_x (position), y_pos (_track) + 4); gc->StrokePath (path); gc->FillPath (path); @@ -163,8 +163,8 @@ private: wxDouble name_leading; gc->GetTextExtent (name, &name_width, &name_height, &name_descent, &name_leading); - gc->Clip (wxRegion (time_x (start), y_pos (_track), len * _timeline.pixels_per_time_unit(), _timeline.track_height())); - gc->DrawText (name, time_x (start) + 12, y_pos (_track + 1) - name_height - 4); + gc->Clip (wxRegion (time_x (position), y_pos (_track), len * _timeline.pixels_per_time_unit(), _timeline.track_height())); + gc->DrawText (name, time_x (position) + 12, y_pos (_track + 1) - name_height - 4); gc->ResetClip (); } @@ -177,7 +177,7 @@ private: { ensure_ui_thread (); - if (p == ContentProperty::START || p == ContentProperty::LENGTH) { + if (p == ContentProperty::POSITION || p == ContentProperty::LENGTH) { force_redraw (); } @@ -327,7 +327,7 @@ Timeline::Timeline (wxWindow* parent, FilmEditor* ed, shared_ptr<Film> film) , _tracks (0) , _pixels_per_time_unit (0) , _left_down (false) - , _down_view_start (0) + , _down_view_position (0) , _first_move (false) , _menu (film, this) { @@ -430,8 +430,8 @@ Timeline::assign_tracks () if (test && test->track() == t) { bool const no_overlap = - (acv_content->start() < test_content->start() && acv_content->end() < test_content->start()) || - (acv_content->start() > test_content->end() && acv_content->end() > test_content->end()); + (acv_content->position() < test_content->position() && acv_content->end() < test_content->position()) || + (acv_content->position() > test_content->end() && acv_content->end() > test_content->end()); if (!no_overlap) { /* we have an overlap on track `t' */ @@ -499,7 +499,7 @@ Timeline::left_down (wxMouseEvent& ev) if (content_view) { _down_view = content_view; - _down_view_start = content_view->content()->start (); + _down_view_position = content_view->content()->position (); } for (ViewList::iterator i = _views.begin(); i != _views.end(); ++i) { @@ -539,7 +539,7 @@ Timeline::left_up (wxMouseEvent& ev) _down_view->content()->set_change_signals_frequent (false); } - set_start_from_event (ev); + set_position_from_event (ev); } void @@ -549,7 +549,7 @@ Timeline::mouse_moved (wxMouseEvent& ev) return; } - set_start_from_event (ev); + set_position_from_event (ev); } void @@ -570,7 +570,7 @@ Timeline::right_down (wxMouseEvent& ev) } void -Timeline::set_start_from_event (wxMouseEvent& ev) +Timeline::set_position_from_event (wxMouseEvent& ev) { wxPoint const p = ev.GetPosition(); @@ -584,7 +584,7 @@ Timeline::set_start_from_event (wxMouseEvent& ev) Time const time_diff = (p.x - _down_point.x) / _pixels_per_time_unit; if (_down_view) { - _down_view->content()->set_start (max (static_cast<Time> (0), _down_view_start + time_diff)); + _down_view->content()->set_position (max (static_cast<Time> (0), _down_view_position + time_diff)); shared_ptr<Film> film = _film.lock (); assert (film); diff --git a/src/wx/timeline.h b/src/wx/timeline.h index db33dbbdc..0217373b9 100644 --- a/src/wx/timeline.h +++ b/src/wx/timeline.h @@ -73,7 +73,7 @@ private: void playlist_changed (); void resized (); void assign_tracks (); - void set_start_from_event (wxMouseEvent &); + void set_position_from_event (wxMouseEvent &); void clear_selection (); typedef std::vector<boost::shared_ptr<View> > ViewList; @@ -92,7 +92,7 @@ private: bool _left_down; wxPoint _down_point; boost::shared_ptr<ContentView> _down_view; - Time _down_view_start; + Time _down_view_position; bool _first_move; ContentMenu _menu; diff --git a/src/wx/timing_panel.cc b/src/wx/timing_panel.cc index 313543d2d..f11a4e5e6 100644 --- a/src/wx/timing_panel.cc +++ b/src/wx/timing_panel.cc @@ -34,46 +34,66 @@ TimingPanel::TimingPanel (FilmEditor* e) wxFlexGridSizer* grid = new wxFlexGridSizer (2, 4, 4); _sizer->Add (grid, 0, wxALL, 8); - add_label_to_sizer (grid, this, _("Start time"), true); - _start = new Timecode (this); - grid->Add (_start); + add_label_to_sizer (grid, this, _("Position"), true); + _position = new Timecode (this); + grid->Add (_position); add_label_to_sizer (grid, this, _("Length"), true); _length = new Timecode (this); grid->Add (_length); + add_label_to_sizer (grid, this, _("Trim from start"), true); + _trim_start = new Timecode (this); + grid->Add (_trim_start); + add_label_to_sizer (grid, this, _("Trim from end"), true); + _trim_end = new Timecode (this); + grid->Add (_trim_end); - _start->Changed.connect (boost::bind (&TimingPanel::start_changed, this)); - _length->Changed.connect (boost::bind (&TimingPanel::length_changed, this)); + _position->Changed.connect (boost::bind (&TimingPanel::position_changed, this)); + _length->Changed.connect (boost::bind (&TimingPanel::length_changed, this)); + _trim_start->Changed.connect (boost::bind (&TimingPanel::trim_start_changed, this)); + _trim_end->Changed.connect (boost::bind (&TimingPanel::trim_end_changed, this)); } void TimingPanel::film_content_changed (shared_ptr<Content> content, int property) { - if (property == ContentProperty::START) { + if (property == ContentProperty::POSITION) { if (content) { - _start->set (content->start (), _editor->film()->video_frame_rate ()); + _position->set (content->position (), _editor->film()->video_frame_rate ()); } else { - _start->set (0, 24); + _position->set (0, 24); } } else if (property == ContentProperty::LENGTH) { if (content) { - _length->set (content->length (), _editor->film()->video_frame_rate ()); + _length->set (content->full_length (), _editor->film()->video_frame_rate ()); } else { _length->set (0, 24); } - } + } else if (property == ContentProperty::TRIM_START) { + if (content) { + _trim_start->set (content->trim_start (), _editor->film()->video_frame_rate ()); + } else { + _trim_start->set (0, 24); + } + } else if (property == ContentProperty::TRIM_END) { + if (content) { + _trim_end->set (content->trim_end (), _editor->film()->video_frame_rate ()); + } else { + _trim_end->set (0, 24); + } + } _length->set_editable (dynamic_pointer_cast<StillImageContent> (content)); } void -TimingPanel::start_changed () +TimingPanel::position_changed () { shared_ptr<Content> c = _editor->selected_content (); if (!c) { return; } - c->set_start (_start->get (_editor->film()->video_frame_rate ())); + c->set_position (_position->get (_editor->film()->video_frame_rate ())); } void @@ -89,3 +109,26 @@ TimingPanel::length_changed () ic->set_video_length (_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; + } + + 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; + } + + 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 b5c9ef026..b84ea52be 100644 --- a/src/wx/timing_panel.h +++ b/src/wx/timing_panel.h @@ -29,9 +29,13 @@ public: void film_content_changed (boost::shared_ptr<Content>, int); private: - void start_changed (); + void position_changed (); void length_changed (); + void trim_start_changed (); + void trim_end_changed (); - Timecode* _start; + Timecode* _position; Timecode* _length; + Timecode* _trim_start; + Timecode* _trim_end; }; |
