diff options
| author | Carl Hetherington <cth@carlh.net> | 2013-05-26 00:21:53 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2013-05-26 00:21:53 +0100 |
| commit | c77dabbe4e6bb031edf4aa82f5e890fe605bafe1 (patch) | |
| tree | d3a3f2f34b44eecedabc0240ea82c741b49385ba /src | |
| parent | 996b0c06e23bcb6b300d7b8799df94993692e07d (diff) | |
Add unfinished timing tab; fix crash on reconstruction of timeline; fix lack of black / silence at end of films.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/content.cc | 2 | ||||
| -rw-r--r-- | src/lib/player.cc | 61 | ||||
| -rw-r--r-- | src/lib/player.h | 4 | ||||
| -rw-r--r-- | src/lib/sndfile_content.cc | 1 | ||||
| -rw-r--r-- | src/wx/film_editor.cc | 54 | ||||
| -rw-r--r-- | src/wx/film_editor.h | 8 | ||||
| -rw-r--r-- | src/wx/timecode.cc | 90 | ||||
| -rw-r--r-- | src/wx/timecode.h | 36 | ||||
| -rw-r--r-- | src/wx/timeline.cc | 20 | ||||
| -rw-r--r-- | src/wx/timeline.h | 5 | ||||
| -rw-r--r-- | src/wx/wscript | 1 |
11 files changed, 226 insertions, 56 deletions
diff --git a/src/lib/content.cc b/src/lib/content.cc index ad61f4d6c..aaf2e4f9c 100644 --- a/src/lib/content.cc +++ b/src/lib/content.cc @@ -1,5 +1,3 @@ -/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */ - /* Copyright (C) 2013 Carl Hetherington <cth@carlh.net> diff --git a/src/lib/player.cc b/src/lib/player.cc index ff13f95db..786180a6a 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -1,5 +1,3 @@ -/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */ - /* Copyright (C) 2013 Carl Hetherington <cth@carlh.net> @@ -103,18 +101,18 @@ Player::pass () shared_ptr<Piece> earliest; for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) { - cout << "check " << (*i)->content->file() << " start=" << (*i)->content->start() << ", next=" << (*i)->decoder->next() << ", end=" << (*i)->content->end() << "\n"; +// cout << "check " << (*i)->content->file() << " start=" << (*i)->content->start() << ", next=" << (*i)->decoder->next() << ", end=" << (*i)->content->end() << "\n"; if (((*i)->decoder->next() + (*i)->content->start()) >= (*i)->content->end()) { continue; } - if (!_audio && dynamic_pointer_cast<SndfileContent> ((*i)->content)) { + if (!_audio && dynamic_pointer_cast<AudioDecoder> ((*i)->decoder) && !dynamic_pointer_cast<VideoDecoder> ((*i)->decoder)) { continue; } Time const t = (*i)->content->start() + (*i)->decoder->next(); if (t < earliest_t) { - cout << "\t candidate; " << t << " " << (t / TIME_HZ) << ".\n"; +// cout << "\t candidate; " << t << " " << (t / TIME_HZ) << ".\n"; earliest_t = t; earliest = *i; } @@ -148,8 +146,6 @@ Player::pass () void Player::process_video (weak_ptr<Content> weak_content, shared_ptr<const Image> image, bool same, shared_ptr<Subtitle> sub, Time time) { - cout << "[V]\n"; - shared_ptr<Content> content = weak_content.lock (); if (!content) { return; @@ -208,13 +204,13 @@ Player::seek (Time t) return; } - cout << "seek to " << t << " " << (t / TIME_HZ) << "\n"; +// cout << "seek to " << t << " " << (t / TIME_HZ) << "\n"; for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) { Time s = t - (*i)->content->start (); s = max (static_cast<Time> (0), s); s = min ((*i)->content->length(), s); - cout << "seek [" << (*i)->content->file() << "," << (*i)->content->start() << "," << (*i)->content->end() << "] to " << s << "\n"; +// cout << "seek [" << (*i)->content->file() << "," << (*i)->content->start() << "," << (*i)->content->end() << "] to " << s << "\n"; (*i)->decoder->seek (s); } @@ -234,6 +230,27 @@ Player::seek_forward () } +void +Player::add_black_piece (Time s, Time len) +{ + shared_ptr<NullContent> nc (new NullContent (_film, s, len)); + shared_ptr<BlackDecoder> bd (new BlackDecoder (_film, nc)); + bd->Video.connect (bind (&Player::process_video, this, nc, _1, _2, _3, _4)); + _pieces.push_back (shared_ptr<Piece> (new Piece (nc, bd))); + cout << "\tblack @ " << s << " -- " << (s + len) << "\n"; +} + +void +Player::add_silent_piece (Time s, Time len) +{ + shared_ptr<NullContent> nc (new NullContent (_film, s, len)); + shared_ptr<SilenceDecoder> sd (new SilenceDecoder (_film, nc)); + sd->Audio.connect (bind (&Player::process_audio, this, nc, _1, _2)); + _pieces.push_back (shared_ptr<Piece> (new Piece (nc, sd))); + cout << "\tsilence @ " << s << " -- " << (s + len) << "\n"; +} + + struct ContentSorter { bool operator() (shared_ptr<Content> a, shared_ptr<Content> b) @@ -245,7 +262,7 @@ struct ContentSorter void Player::setup_pieces () { -// cout << "----- Player SETUP PIECES.\n"; + cout << "----- Player SETUP PIECES.\n"; list<shared_ptr<Piece> > old_pieces = _pieces; @@ -268,7 +285,7 @@ Player::setup_pieces () fd->Audio.connect (bind (&Player::process_audio, this, *i, _1, _2)); decoder = fd; -// cout << "\tFFmpeg @ " << fc->start() << " -- " << fc->end() << "\n"; + cout << "\tFFmpeg @ " << fc->start() << " -- " << fc->end() << "\n"; } shared_ptr<const ImageMagickContent> ic = dynamic_pointer_cast<const ImageMagickContent> (*i); @@ -289,7 +306,7 @@ Player::setup_pieces () } decoder = id; -// cout << "\tImageMagick @ " << ic->start() << " -- " << ic->end() << "\n"; + cout << "\tImageMagick @ " << ic->start() << " -- " << ic->end() << "\n"; } shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i); @@ -298,7 +315,7 @@ Player::setup_pieces () sd->Audio.connect (bind (&Player::process_audio, this, *i, _1, _2)); decoder = sd; -// cout << "\tSndfile @ " << sc->start() << " -- " << sc->end() << "\n"; + cout << "\tSndfile @ " << sc->start() << " -- " << sc->end() << "\n"; } _pieces.push_back (shared_ptr<Piece> (new Piece (*i, decoder))); @@ -313,26 +330,24 @@ Player::setup_pieces () if (dynamic_pointer_cast<VideoContent> ((*i)->content)) { Time const diff = (*i)->content->start() - video_pos; if (diff > 0) { - shared_ptr<NullContent> nc (new NullContent (_film, video_pos, diff)); - shared_ptr<BlackDecoder> bd (new BlackDecoder (_film, nc)); - bd->Video.connect (bind (&Player::process_video, this, nc, _1, _2, _3, _4)); - _pieces.push_back (shared_ptr<Piece> (new Piece (nc, bd))); -// cout << "\tblack @ " << video_pos << " -- " << (video_pos + diff) << "\n"; + add_black_piece (video_pos, diff); } video_pos = (*i)->content->end(); } else { Time const diff = (*i)->content->start() - audio_pos; if (diff > 0) { - shared_ptr<NullContent> nc (new NullContent (_film, audio_pos, diff)); - shared_ptr<SilenceDecoder> sd (new SilenceDecoder (_film, nc)); - sd->Audio.connect (bind (&Player::process_audio, this, nc, _1, _2)); - _pieces.push_back (shared_ptr<Piece> (new Piece (nc, sd))); -// cout << "\tsilence @ " << audio_pos << " -- " << (audio_pos + diff) << "\n"; + add_silent_piece (video_pos, diff); } audio_pos = (*i)->content->end(); } } + + if (video_pos < audio_pos) { + add_black_piece (video_pos, audio_pos - video_pos); + } else if (audio_pos < video_pos) { + add_silent_piece (audio_pos, video_pos - audio_pos); + } } void diff --git a/src/lib/player.h b/src/lib/player.h index 4d23d1951..cdedf1676 100644 --- a/src/lib/player.h +++ b/src/lib/player.h @@ -68,6 +68,8 @@ private: void playlist_changed (); void content_changed (boost::weak_ptr<Content>, int); void do_seek (Time, bool); + void add_black_piece (Time, Time); + void add_silent_piece (Time, Time); boost::shared_ptr<const Film> _film; boost::shared_ptr<const Playlist> _playlist; @@ -79,8 +81,6 @@ private: /** Our pieces are ready to go; if this is false the pieces must be (re-)created before they are used */ bool _have_valid_pieces; std::list<boost::shared_ptr<Piece> > _pieces; - - /** Time of the earliest thing not yet to have been emitted */ Time _position; AudioBuffers _audio_buffers; Time _next_audio; diff --git a/src/lib/sndfile_content.cc b/src/lib/sndfile_content.cc index 0f895c95e..a80c7dbe5 100644 --- a/src/lib/sndfile_content.cc +++ b/src/lib/sndfile_content.cc @@ -120,6 +120,7 @@ SndfileContent::as_xml (xmlpp::Node* node) const { node->add_child("Type")->add_child_text ("Sndfile"); Content::as_xml (node); + AudioContent::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/wx/film_editor.cc b/src/wx/film_editor.cc index 36d63b805..b67b47b4e 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -1,5 +1,3 @@ -/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */ - /* Copyright (C) 2012 Carl Hetherington <cth@carlh.net> @@ -55,6 +53,7 @@ #include "timeline_dialog.h" #include "audio_mapping_view.h" #include "container.h" +#include "timecode.h" using std::string; using std::cout; @@ -230,11 +229,11 @@ void FilmEditor::make_video_panel () { _video_panel = new wxPanel (_content_notebook); - _video_sizer = new wxBoxSizer (wxVERTICAL); - _video_panel->SetSizer (_video_sizer); + wxBoxSizer* video_sizer = new wxBoxSizer (wxVERTICAL); + _video_panel->SetSizer (video_sizer); wxGridBagSizer* grid = new wxGridBagSizer (4, 4); - _video_sizer->Add (grid, 0, wxALL, 8); + video_sizer->Add (grid, 0, wxALL, 8); int r = 0; add_label_to_grid_bag_sizer (grid, _video_panel, _("Left crop"), wxGBPosition (r, 0)); @@ -336,13 +335,15 @@ FilmEditor::make_content_panel () _content_notebook = new wxNotebook (_content_panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_LEFT); _content_sizer->Add (_content_notebook, 1, wxEXPAND | wxTOP, 6); - + make_video_panel (); _content_notebook->AddPage (_video_panel, _("Video"), false); make_audio_panel (); _content_notebook->AddPage (_audio_panel, _("Audio"), false); make_subtitle_panel (); _content_notebook->AddPage (_subtitle_panel, _("Subtitles"), false); + make_timing_panel (); + _content_notebook->AddPage (_timing_panel, _("Timing"), false); _loop_count->SetRange (2, 1024); } @@ -351,11 +352,11 @@ void FilmEditor::make_audio_panel () { _audio_panel = new wxPanel (_content_notebook); - _audio_sizer = new wxBoxSizer (wxVERTICAL); - _audio_panel->SetSizer (_audio_sizer); + wxBoxSizer* audio_sizer = new wxBoxSizer (wxVERTICAL); + _audio_panel->SetSizer (audio_sizer); wxFlexGridSizer* grid = new wxFlexGridSizer (3, 4, 4); - _audio_sizer->Add (grid, 0, wxALL, 8); + audio_sizer->Add (grid, 0, wxALL, 8); _show_audio = new wxButton (_audio_panel, wxID_ANY, _("Show Audio...")); grid->Add (_show_audio, 1); @@ -397,7 +398,7 @@ FilmEditor::make_audio_panel () grid->AddSpacer (0); _audio_mapping = new AudioMappingView (_audio_panel); - _audio_sizer->Add (_audio_mapping, 1, wxEXPAND | wxALL, 6); + audio_sizer->Add (_audio_mapping, 1, wxEXPAND | wxALL, 6); _audio_gain->SetRange (-60, 60); _audio_delay->SetRange (-1000, 1000); @@ -407,10 +408,10 @@ void FilmEditor::make_subtitle_panel () { _subtitle_panel = new wxPanel (_content_notebook); - _subtitle_sizer = new wxBoxSizer (wxVERTICAL); - _subtitle_panel->SetSizer (_subtitle_sizer); + wxBoxSizer* subtitle_sizer = new wxBoxSizer (wxVERTICAL); + _subtitle_panel->SetSizer (subtitle_sizer); wxFlexGridSizer* grid = new wxFlexGridSizer (2, 4, 4); - _subtitle_sizer->Add (grid, 0, wxALL, 8); + subtitle_sizer->Add (grid, 0, wxALL, 8); _with_subtitles = new wxCheckBox (_subtitle_panel, wxID_ANY, _("With Subtitles")); grid->Add (_with_subtitles, 1); @@ -443,6 +444,24 @@ FilmEditor::make_subtitle_panel () _subtitle_scale->SetRange (1, 1000); } +void +FilmEditor::make_timing_panel () +{ + _timing_panel = new wxPanel (_content_notebook); + wxBoxSizer* timing_sizer = new wxBoxSizer (wxVERTICAL); + _timing_panel->SetSizer (timing_sizer); + wxFlexGridSizer* grid = new wxFlexGridSizer (2, 4, 4); + timing_sizer->Add (grid, 0, wxALL, 8); + + add_label_to_sizer (grid, _timing_panel, _("Start time")); + _start = new Timecode (_timing_panel); + grid->Add (_start); + add_label_to_sizer (grid, _timing_panel, _("Length")); + _length = new Timecode (_timing_panel); + grid->Add (_length); +} + + /** Called when the left crop widget has been changed */ void FilmEditor::left_crop_changed (wxCommandEvent &) @@ -666,7 +685,13 @@ FilmEditor::film_content_changed (weak_ptr<Content> weak_content, int property) ffmpeg_content = dynamic_pointer_cast<FFmpegContent> (content); } - if (property == VideoContentProperty::VIDEO_CROP) { + if (property == ContentProperty::START) { + if (content) { + _start->set (content->start (), _film->dcp_video_frame_rate ()); + } else { + _start->set (0, 24); + } + } else if (property == VideoContentProperty::VIDEO_CROP) { checked_set (_left_crop, video_content ? video_content->crop().left : 0); checked_set (_right_crop, video_content ? video_content->crop().right : 0); checked_set (_top_crop, video_content ? video_content->crop().top : 0); @@ -817,6 +842,7 @@ FilmEditor::set_film (shared_ptr<Film> f) film_changed (Film::DCI_METADATA); film_changed (Film::DCP_VIDEO_FRAME_RATE); + film_content_changed (boost::shared_ptr<Content> (), ContentProperty::START); film_content_changed (boost::shared_ptr<Content> (), VideoContentProperty::VIDEO_CROP); film_content_changed (boost::shared_ptr<Content> (), AudioContentProperty::AUDIO_GAIN); film_content_changed (boost::shared_ptr<Content> (), AudioContentProperty::AUDIO_DELAY); diff --git a/src/wx/film_editor.h b/src/wx/film_editor.h index 89065c97d..b169aee7f 100644 --- a/src/wx/film_editor.h +++ b/src/wx/film_editor.h @@ -36,6 +36,7 @@ class AudioDialog; class TimelineDialog; class AudioMappingView; class Format; +class Timecode; /** @class FilmEditor * @brief A wx widget to edit a film's metadata, and perform various functions. @@ -55,6 +56,7 @@ private: void make_video_panel (); void make_audio_panel (); void make_subtitle_panel (); + void make_timing_panel (); void connect_to_widgets (); /* Handle changes to the view */ @@ -120,11 +122,9 @@ private: wxPanel* _content_panel; wxSizer* _content_sizer; wxPanel* _video_panel; - wxSizer* _video_sizer; wxPanel* _audio_panel; - wxSizer* _audio_sizer; wxPanel* _subtitle_panel; - wxSizer* _subtitle_sizer; + wxPanel* _timing_panel; /** The film we are editing */ boost::shared_ptr<Film> _film; @@ -167,6 +167,8 @@ private: wxStaticText* _audio_description; wxChoice* _subtitle_stream; AudioMappingView* _audio_mapping; + Timecode* _start; + Timecode* _length; std::vector<Format const *> _formats; diff --git a/src/wx/timecode.cc b/src/wx/timecode.cc new file mode 100644 index 000000000..460f7423b --- /dev/null +++ b/src/wx/timecode.cc @@ -0,0 +1,90 @@ +/* + 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 <boost/lexical_cast.hpp> +#include "timecode.h" +#include "wx_util.h" + +using std::string; +using boost::lexical_cast; + +Timecode::Timecode (wxWindow* parent) + : wxPanel (parent) +{ + wxClientDC dc (parent); + wxSize size = dc.GetTextExtent (wxT ("9999")); + size.SetHeight (-1); + + wxTextValidator validator (wxFILTER_INCLUDE_CHAR_LIST); + wxArrayString list; + + string n = "0123456789"; + for (size_t i = 0; i < n.length(); ++i) { + list.Add (n[i]); + } + + validator.SetIncludes (list); + + wxBoxSizer* sizer = new wxBoxSizer (wxHORIZONTAL); + _hours = new wxTextCtrl (this, wxID_ANY, wxT(""), wxDefaultPosition, size, 0, validator); + _hours->SetMaxLength (2); + sizer->Add (_hours); + add_label_to_sizer (sizer, this, ":"); + _minutes = new wxTextCtrl (this, wxID_ANY, wxT(""), wxDefaultPosition, size); + _minutes->SetMaxLength (2); + sizer->Add (_minutes); + add_label_to_sizer (sizer, this, ":"); + _seconds = new wxTextCtrl (this, wxID_ANY, wxT(""), wxDefaultPosition, size); + _seconds->SetMaxLength (2); + sizer->Add (_seconds); + add_label_to_sizer (sizer, this, "."); + _frames = new wxTextCtrl (this, wxID_ANY, wxT(""), wxDefaultPosition, size); + _frames->SetMaxLength (2); + sizer->Add (_frames); + + SetSizerAndFit (sizer); +} + +void +Timecode::set (Time t, int fps) +{ + int const h = t / (3600 * TIME_HZ); + t -= h * 3600 * TIME_HZ; + int const m = t / (60 * TIME_HZ); + t -= m * 60 * TIME_HZ; + int const s = t / TIME_HZ; + t -= s * TIME_HZ; + int const f = t * fps / TIME_HZ; + + _hours->SetValue (wxString::Format ("%02d", h)); + _minutes->SetValue (wxString::Format ("%02d", m)); + _seconds->SetValue (wxString::Format ("%02d", s)); + _frames->SetValue (wxString::Format ("%02d", f)); +} + +Time +Timecode::get (int fps) const +{ + Time t = 0; + t += lexical_cast<int> (wx_to_std (_hours->GetValue())) * 3600 * TIME_HZ; + t += lexical_cast<int> (wx_to_std (_minutes->GetValue())) * 60 * TIME_HZ; + t += lexical_cast<int> (wx_to_std (_seconds->GetValue())) * TIME_HZ; + t += lexical_cast<int> (wx_to_std (_frames->GetValue())) * TIME_HZ / fps; + return t; +} diff --git a/src/wx/timecode.h b/src/wx/timecode.h new file mode 100644 index 000000000..f243ee0b8 --- /dev/null +++ b/src/wx/timecode.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 <wx/wx.h> +#include "lib/types.h" + +class Timecode : public wxPanel +{ +public: + Timecode (wxWindow *); + + void set (Time, int); + Time get (int) const; + +private: + wxTextCtrl* _hours; + wxTextCtrl* _minutes; + wxTextCtrl* _seconds; + wxTextCtrl* _frames; +}; diff --git a/src/wx/timeline.cc b/src/wx/timeline.cc index 96bd2ccd4..8c90c3d8c 100644 --- a/src/wx/timeline.cc +++ b/src/wx/timeline.cc @@ -1,5 +1,3 @@ -/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */ - /* Copyright (C) 2013 Carl Hetherington <cth@carlh.net> @@ -81,7 +79,7 @@ public: , _track (t) , _selected (false) { - c->Changed.connect (bind (&ContentView::content_changed, this, _2)); + _content_connection = c->Changed.connect (bind (&ContentView::content_changed, this, _2)); } Rect bbox () const @@ -150,11 +148,11 @@ private: #endif wxGraphicsPath path = gc->CreatePath (); - path.MoveToPoint (time_x (start), y_pos (_track)); - path.AddLineToPoint (time_x (start + len), y_pos (_track)); - path.AddLineToPoint (time_x (start + len), y_pos (_track + 1)); - path.AddLineToPoint (time_x (start), y_pos (_track + 1)); - path.AddLineToPoint (time_x (start), y_pos (_track)); + 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); gc->StrokePath (path); gc->FillPath (path); @@ -185,6 +183,8 @@ private: boost::weak_ptr<Content> _content; int _track; bool _selected; + + boost::signals2::scoped_connection _content_connection; }; class AudioContentView : public ContentView @@ -326,7 +326,7 @@ Timeline::Timeline (wxWindow* parent, shared_ptr<const Film> film) playlist_changed (); - film->playlist()->Changed.connect (bind (&Timeline::playlist_changed, this)); + _playlist_connection = film->playlist()->Changed.connect (bind (&Timeline::playlist_changed, this)); } void @@ -452,7 +452,7 @@ Timeline::mouse_moved (wxMouseEvent& ev) if (_down_view) { shared_ptr<Content> c = _down_view->content().lock(); if (c) { - c->set_start (_down_view_start + time_diff); + c->set_start (max (static_cast<Time> (0), _down_view_start + time_diff)); } } } diff --git a/src/wx/timeline.h b/src/wx/timeline.h index 79ceceaa0..52b29de86 100644 --- a/src/wx/timeline.h +++ b/src/wx/timeline.h @@ -1,5 +1,3 @@ -/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */ - /* Copyright (C) 2013 Carl Hetherington <cth@carlh.net> @@ -21,6 +19,7 @@ #include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> +#include <boost/signals2.hpp> #include <wx/wx.h> #include "util.h" @@ -76,4 +75,6 @@ private: boost::shared_ptr<ContentView> _down_view; Time _down_view_start; bool _first_move; + + boost::signals2::scoped_connection _playlist_connection; }; diff --git a/src/wx/wscript b/src/wx/wscript index 884eabc3a..d915f5899 100644 --- a/src/wx/wscript +++ b/src/wx/wscript @@ -21,6 +21,7 @@ sources = """ new_film_dialog.cc properties_dialog.cc server_dialog.cc + timecode.cc timeline.cc timeline_dialog.cc wx_util.cc |
