diff options
Diffstat (limited to 'src/wx')
| -rw-r--r-- | src/wx/about_dialog.cc | 10 | ||||
| -rw-r--r-- | src/wx/about_dialog.h | 11 | ||||
| -rw-r--r-- | src/wx/audio_mapping_view.cc | 26 | ||||
| -rw-r--r-- | src/wx/audio_mapping_view.h | 9 | ||||
| -rw-r--r-- | src/wx/audio_panel.cc | 3 | ||||
| -rw-r--r-- | src/wx/config_dialog.cc | 6 | ||||
| -rw-r--r-- | src/wx/content_widget.h | 9 | ||||
| -rw-r--r-- | src/wx/film_editor.cc | 2 | ||||
| -rw-r--r-- | src/wx/film_viewer.cc | 140 | ||||
| -rw-r--r-- | src/wx/film_viewer.h | 27 | ||||
| -rw-r--r-- | src/wx/properties_dialog.cc | 10 | ||||
| -rw-r--r-- | src/wx/screen_dialog.cc | 12 | ||||
| -rw-r--r-- | src/wx/screen_dialog.h | 8 | ||||
| -rw-r--r-- | src/wx/subtitle_panel.cc | 31 | ||||
| -rw-r--r-- | src/wx/subtitle_panel.h | 6 | ||||
| -rw-r--r-- | src/wx/subtitle_view.cc | 80 | ||||
| -rw-r--r-- | src/wx/subtitle_view.h | 33 | ||||
| -rw-r--r-- | src/wx/timecode.cc | 16 | ||||
| -rw-r--r-- | src/wx/timecode.h | 4 | ||||
| -rw-r--r-- | src/wx/timeline.cc | 106 | ||||
| -rw-r--r-- | src/wx/timeline.h | 10 | ||||
| -rw-r--r-- | src/wx/timing_panel.cc | 17 | ||||
| -rw-r--r-- | src/wx/video_panel.cc | 8 | ||||
| -rw-r--r-- | src/wx/video_panel.h | 9 | ||||
| -rw-r--r-- | src/wx/wscript | 1 | ||||
| -rw-r--r-- | src/wx/wx_ui_signaller.cc | 2 | ||||
| -rw-r--r-- | src/wx/wx_ui_signaller.h | 6 | ||||
| -rw-r--r-- | src/wx/wx_util.cc | 4 |
28 files changed, 383 insertions, 223 deletions
diff --git a/src/wx/about_dialog.cc b/src/wx/about_dialog.cc index 751b453ed..bd4a39811 100644 --- a/src/wx/about_dialog.cc +++ b/src/wx/about_dialog.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Carl Hetherington <cth@carlh.net> + Copyright (C) 2013-2014 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 @@ -17,6 +17,10 @@ */ +/** @file src/wx/about_dialog.cc + * @brief The "about DCP-o-matic" dialogue box. + */ + #include <wx/notebook.h> #include <wx/hyperlink.h> #include "lib/version.h" @@ -206,6 +210,10 @@ AboutDialog::AboutDialog (wxWindow* parent) SetSizerAndFit (overall_sizer); } +/** Add a section of credits. + * @param name Name of section. + * @param credits List of names. + */ void AboutDialog::add_section (wxString name, wxArrayString credits) { diff --git a/src/wx/about_dialog.h b/src/wx/about_dialog.h index a78abb93e..4901cf990 100644 --- a/src/wx/about_dialog.h +++ b/src/wx/about_dialog.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Carl Hetherington <cth@carlh.net> + Copyright (C) 2013-2014 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 @@ -17,10 +17,17 @@ */ +/** @file src/wx/about_dialog.h + * @brief The "about DCP-o-matic" dialogue box. + */ + #include <wx/wx.h> class wxNotebook; +/** @class AboutDialog + * @brief The "about DCP-o-matic" dialogue box. + */ class AboutDialog : public wxDialog { public: @@ -29,6 +36,6 @@ public: private: void add_section (wxString, wxArrayString); - wxNotebook* _notebook; + wxNotebook* _notebook; ///< notebook used to keep each list of names for the credits }; diff --git a/src/wx/audio_mapping_view.cc b/src/wx/audio_mapping_view.cc index d59c4ae07..c65eadd5a 100644 --- a/src/wx/audio_mapping_view.cc +++ b/src/wx/audio_mapping_view.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Carl Hetherington <cth@carlh.net> + Copyright (C) 2013-2014 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 @@ -17,15 +17,20 @@ */ +/** @file src/wx/audio_mapping_view.cc + * @brief AudioMappingView class and helpers. + */ + #include <wx/wx.h> #include <wx/renderer.h> #include <wx/grid.h> -#include <libdcp/types.h> +#include <dcp/types.h> #include "lib/audio_mapping.h" #include "lib/util.h" #include "audio_mapping_view.h" #include "wx_util.h" #include "audio_gain_dialog.h" +#include <boost/lexical_cast.hpp> using std::cout; using std::list; @@ -52,6 +57,9 @@ public: } }; +/** @class ValueRenderer + * @brief wxGridCellRenderer for a gain value. + */ class ValueRenderer : public wxGridCellRenderer { public: @@ -154,7 +162,7 @@ AudioMappingView::left_click (wxGridEvent& ev) return; } - libdcp::Channel d = static_cast<libdcp::Channel> (ev.GetCol() - 1); + dcp::Channel d = static_cast<dcp::Channel> (ev.GetCol() - 1); if (_map.get (ev.GetRow(), d) > 0) { _map.set (ev.GetRow(), d, 0); @@ -180,28 +188,28 @@ AudioMappingView::right_click (wxGridEvent& ev) void AudioMappingView::off () { - _map.set (_menu_row, static_cast<libdcp::Channel> (_menu_column - 1), 0); + _map.set (_menu_row, static_cast<dcp::Channel> (_menu_column - 1), 0); map_changed (); } void AudioMappingView::full () { - _map.set (_menu_row, static_cast<libdcp::Channel> (_menu_column - 1), 1); + _map.set (_menu_row, static_cast<dcp::Channel> (_menu_column - 1), 1); map_changed (); } void AudioMappingView::minus6dB () { - _map.set (_menu_row, static_cast<libdcp::Channel> (_menu_column - 1), pow (10, -6.0 / 20)); + _map.set (_menu_row, static_cast<dcp::Channel> (_menu_column - 1), pow (10, -6.0 / 20)); map_changed (); } void AudioMappingView::edit () { - libdcp::Channel d = static_cast<libdcp::Channel> (_menu_column - 1); + dcp::Channel d = static_cast<dcp::Channel> (_menu_column - 1); AudioGainDialog* dialog = new AudioGainDialog (this, _menu_row, _menu_column - 1, _map.get (_menu_row, d)); if (dialog->ShowModal () == wxID_OK) { @@ -238,7 +246,7 @@ AudioMappingView::update_cells () _grid->SetCellValue (i, 0, wxString::Format (wxT("%d"), i + 1)); for (int j = 1; j < _grid->GetNumberCols(); ++j) { - _grid->SetCellValue (i, j, std_to_wx (lexical_cast<string> (_map.get (i, static_cast<libdcp::Channel> (j - 1))))); + _grid->SetCellValue (i, j, std_to_wx (lexical_cast<string> (_map.get (i, static_cast<dcp::Channel> (j - 1))))); } } @@ -342,7 +350,7 @@ AudioMappingView::mouse_moved (wxMouseEvent& ev) if (row != _last_tooltip_row || column != _last_tooltip_column) { wxString s; - float const gain = _map.get (row, static_cast<libdcp::Channel> (column - 1)); + float const gain = _map.get (row, static_cast<dcp::Channel> (column - 1)); if (gain == 0) { s = wxString::Format (_("No audio will be passed from content channel %d to DCP channel %d."), row + 1, column); } else if (gain == 1) { diff --git a/src/wx/audio_mapping_view.h b/src/wx/audio_mapping_view.h index 98375eb9e..7ed699463 100644 --- a/src/wx/audio_mapping_view.h +++ b/src/wx/audio_mapping_view.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Carl Hetherington <cth@carlh.net> + Copyright (C) 2013-2014 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 @@ -17,6 +17,13 @@ */ +/** @file src/wx/audio_mapping_view.h + * @brief AudioMappingView class + * + * This class displays the mapping of one set of audio channels to another, + * with gain values on each node of the map. + */ + #include <boost/signals2.hpp> #include <wx/wx.h> #include <wx/grid.h> diff --git a/src/wx/audio_panel.cc b/src/wx/audio_panel.cc index 72cb9fe6a..26237db31 100644 --- a/src/wx/audio_panel.cc +++ b/src/wx/audio_panel.cc @@ -22,6 +22,7 @@ #include "lib/config.h" #include "lib/sound_processor.h" #include "lib/ffmpeg_content.h" +#include "lib/ffmpeg_audio_stream.h" #include "audio_dialog.h" #include "audio_panel.h" #include "audio_mapping_view.h" @@ -239,7 +240,7 @@ AudioPanel::setup_stream_description () } else { s << fcs->audio_channels() << wxT (" ") << _("channels"); } - s << wxT (", ") << fcs->content_audio_frame_rate() << _("Hz"); + s << wxT (", ") << fcs->audio_frame_rate() << _("Hz"); _description->SetLabel (s); } } diff --git a/src/wx/config_dialog.cc b/src/wx/config_dialog.cc index e65e931d0..68fbc3f1b 100644 --- a/src/wx/config_dialog.cc +++ b/src/wx/config_dialog.cc @@ -28,7 +28,7 @@ #include <wx/preferences.h> #include <wx/filepicker.h> #include <wx/spinctrl.h> -#include <libdcp/colour_matrix.h> +#include <dcp/colour_matrix.h> #include "lib/config.h" #include "lib/ratio.h" #include "lib/scaler.h" @@ -446,14 +446,14 @@ private: void issuer_changed () { - libdcp::XMLMetadata m = Config::instance()->dcp_metadata (); + dcp::XMLMetadata m = Config::instance()->dcp_metadata (); m.issuer = wx_to_std (_issuer->GetValue ()); Config::instance()->set_dcp_metadata (m); } void creator_changed () { - libdcp::XMLMetadata m = Config::instance()->dcp_metadata (); + dcp::XMLMetadata m = Config::instance()->dcp_metadata (); m.creator = wx_to_std (_creator->GetValue ()); Config::instance()->set_dcp_metadata (m); } diff --git a/src/wx/content_widget.h b/src/wx/content_widget.h index ca9485006..9e1338b7c 100644 --- a/src/wx/content_widget.h +++ b/src/wx/content_widget.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013 Carl Hetherington <cth@carlh.net> + Copyright (C) 2013-2014 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 @@ -17,6 +17,10 @@ */ +/** @file src/wx/content_widget.h + * @brief ContentWidget class. + */ + #ifndef DCPOMATIC_MULTIPLE_WIDGET_H #define DCPOMATIC_MULTIPLE_WIDGET_H @@ -26,7 +30,8 @@ #include <boost/function.hpp> #include "wx_util.h" -/** A widget which represents some Content state and which can be used +/** @class ContentWidget + * @brief A widget which represents some Content state and which can be used * when multiple pieces of content are selected. * * @param S Type containing the content being represented (e.g. VideoContent) diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc index 9c980b625..252a89719 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -867,7 +867,7 @@ FilmEditor::setup_content_sensitivity () _video_panel->Enable (video_selection.size() > 0 && _generally_sensitive); _audio_panel->Enable (audio_selection.size() > 0 && _generally_sensitive); - _subtitle_panel->Enable (selection.size() == 1 && dynamic_pointer_cast<FFmpegContent> (selection.front()) && _generally_sensitive); + _subtitle_panel->Enable (selection.size() == 1 && dynamic_pointer_cast<SubtitleContent> (selection.front()) && _generally_sensitive); _timing_panel->Enable (selection.size() == 1 && _generally_sensitive); } diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index ed1a2ce41..c848fe09b 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -37,6 +37,7 @@ #include "lib/player_video_frame.h" #include "lib/video_content.h" #include "lib/video_decoder.h" +#include "lib/timer.h" #include "film_viewer.h" #include "wx_util.h" @@ -51,7 +52,7 @@ using std::make_pair; using boost::shared_ptr; using boost::dynamic_pointer_cast; using boost::weak_ptr; -using libdcp::Size; +using dcp::Size; FilmViewer::FilmViewer (shared_ptr<Film> f, wxWindow* p) : wxPanel (p) @@ -62,7 +63,6 @@ FilmViewer::FilmViewer (shared_ptr<Film> f, wxWindow* p) , _frame_number (new wxStaticText (this, wxID_ANY, wxT(""))) , _timecode (new wxStaticText (this, wxID_ANY, wxT(""))) , _play_button (new wxToggleButton (this, wxID_ANY, _("Play"))) - , _got_frame (false) { #ifndef __WXOSX__ _panel->SetDoubleBuffered (true); @@ -122,7 +122,7 @@ FilmViewer::set_film (shared_ptr<Film> f) _frame.reset (); _slider->SetValue (0); - set_position_text (0); + set_position_text (); if (!_film) { return; @@ -136,30 +136,31 @@ FilmViewer::set_film (shared_ptr<Film> f) return; } - _player->disable_audio (); - _player->Video.connect (boost::bind (&FilmViewer::process_video, this, _1, _3)); + _player->set_approximate_size (); _player->Changed.connect (boost::bind (&FilmViewer::player_changed, this, _1)); calculate_sizes (); - fetch_next_frame (); + get (_position, true); } void -FilmViewer::fetch_current_frame_again () +FilmViewer::get (DCPTime p, bool accurate) { if (!_player) { return; } - /* We could do this with a seek and a fetch_next_frame, but this is - a shortcut to make it quicker. - */ - - _got_frame = false; - if (!_player->repeat_last_video ()) { - fetch_next_frame (); + list<shared_ptr<PlayerVideoFrame> > pvf = _player->get_video (p, accurate); + if (!pvf.empty ()) { + _frame = pvf.front()->image (); + _frame = _frame->scale (_frame->size(), Scaler::from_id ("fastbilinear"), PIX_FMT_RGB24, false); + } else { + _frame.reset (); } + + _position = p; + set_position_text (); _panel->Refresh (); _panel->Update (); } @@ -167,16 +168,12 @@ FilmViewer::fetch_current_frame_again () void FilmViewer::timer () { - if (!_player) { - return; - } - - fetch_next_frame (); + get (_position + DCPTime::from_frames (1, _film->video_frame_rate ()), true); - Time const len = _film->length (); + DCPTime const len = _film->length (); - if (len) { - int const new_slider_position = 4096 * _player->video_position() / len; + if (len.get ()) { + int const new_slider_position = 4096 * _position.get() / len.get(); if (new_slider_position != _slider->GetValue()) { _slider->SetValue (new_slider_position); } @@ -219,15 +216,16 @@ FilmViewer::paint_panel () void FilmViewer::slider_moved () { - if (_film && _player) { - Time t = _slider->GetValue() * _film->length() / 4096; - /* Ensure that we hit the end of the film at the end of the slider */ - if (t >= _film->length ()) { - t = _film->length() - _film->video_frames_to_time (1); - } - _player->seek (t, false); - fetch_next_frame (); + if (!_film) { + return; + } + + DCPTime t (_slider->GetValue() * _film->length().get() / 4096); + /* Ensure that we hit the end of the film at the end of the slider */ + if (t >= _film->length ()) { + t = _film->length() - DCPTime::from_frames (1, _film->video_frame_rate ()); } + get (t, false); } void @@ -236,7 +234,7 @@ FilmViewer::panel_sized (wxSizeEvent& ev) _panel_size.width = ev.GetSize().GetWidth(); _panel_size.height = ev.GetSize().GetHeight(); calculate_sizes (); - fetch_current_frame_again (); + get (_position, true); } void @@ -265,6 +263,13 @@ FilmViewer::calculate_sizes () _out_size.width = max (64, _out_size.width); _out_size.height = max (64, _out_size.height); + /* The player will round its image down to the nearest 4 pixels + to speed up its scale, so do similar here to avoid black borders + around things. This is a bit of a hack. + */ + _out_size.width &= ~3; + _out_size.height &= ~3; + _player->set_video_container_size (_out_size); } @@ -289,20 +294,7 @@ FilmViewer::check_play_state () } void -FilmViewer::process_video (shared_ptr<PlayerVideoFrame> pvf, Time t) -{ - if (pvf->eyes() == EYES_RIGHT) { - return; - } - - _frame = pvf->image (); - _got_frame = true; - - set_position_text (t); -} - -void -FilmViewer::set_position_text (Time t) +FilmViewer::set_position_text () { if (!_film) { _frame_number->SetLabel ("0"); @@ -312,9 +304,9 @@ FilmViewer::set_position_text (Time t) double const fps = _film->video_frame_rate (); /* Count frame number from 1 ... not sure if this is the best idea */ - _frame_number->SetLabel (wxString::Format (wxT("%d"), int (rint (t * fps / TIME_HZ)) + 1)); + _frame_number->SetLabel (wxString::Format (wxT("%d"), int (rint (_position.seconds() * fps)) + 1)); - double w = static_cast<double>(t) / TIME_HZ; + double w = _position.seconds (); int const h = (w / 3600); w -= h * 3600; int const m = (w / 60); @@ -325,35 +317,6 @@ FilmViewer::set_position_text (Time t) _timecode->SetLabel (wxString::Format (wxT("%02d:%02d:%02d.%02d"), h, m, s, f)); } -/** Ask the player to emit its next frame, then update our display */ -void -FilmViewer::fetch_next_frame () -{ - /* Clear our frame in case we don't get a new one */ - _frame.reset (); - - if (!_player) { - return; - } - - _got_frame = false; - - try { - while (!_got_frame && !_player->pass ()) {} - } catch (DecodeError& e) { - _play_button->SetValue (false); - check_play_state (); - error_dialog (this, wxString::Format (_("Could not decode video for view (%s)"), std_to_wx(e.what()).data())); - } catch (OpenFileError& e) { - /* There was a problem opening a content file; we'll let this slide as it - probably means a missing content file, which we're already taking care of. - */ - } - - _panel->Refresh (); - _panel->Update (); -} - void FilmViewer::active_jobs_changed (bool a) { @@ -377,31 +340,18 @@ FilmViewer::active_jobs_changed (bool a) void FilmViewer::back_clicked () { - if (!_player) { - return; + DCPTime p = _position - DCPTime::from_frames (1, _film->video_frame_rate ()); + if (p < DCPTime ()) { + p = DCPTime (); } - /* Player::video_position is the time after the last frame that we received. - We want to see the one before it, so we need to go back 2. - */ - - Time p = _player->video_position() - _film->video_frames_to_time (2); - if (p < 0) { - p = 0; - } - - _player->seek (p, true); - fetch_next_frame (); + get (p, true); } void FilmViewer::forward_clicked () { - if (!_player) { - return; - } - - fetch_next_frame (); + get (_position + DCPTime::from_frames (1, _film->video_frame_rate ()), true); } void @@ -412,5 +362,5 @@ FilmViewer::player_changed (bool frequent) } calculate_sizes (); - fetch_current_frame_again (); + get (_position, true); } diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h index 1e5b6d34d..950758f61 100644 --- a/src/wx/film_viewer.h +++ b/src/wx/film_viewer.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2014 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 @@ -32,19 +32,6 @@ class PlayerVideoFrame; /** @class FilmViewer * @brief A wx widget to view a preview of a Film. - * - * The film takes the following path through the viewer: - * - * 1. fetch_next_frame() asks our _player to decode some data. If it does, process_video() - * will be called. - * - * 2. process_video() takes the image from the player (_frame). - * - * 3. fetch_next_frame() calls _panel->Refresh() and _panel->Update() which results in - * paint_panel() being called; this creates frame_bitmap from _frame and blits it to the display. - * - * fetch_current_frame_again() asks the player to re-emit its current frame on the next pass(), and then - * starts from step #1. */ class FilmViewer : public wxPanel { @@ -59,16 +46,14 @@ private: void slider_moved (); void play_clicked (); void timer (); - void process_video (boost::shared_ptr<PlayerVideoFrame>, Time); void calculate_sizes (); void check_play_state (); - void fetch_current_frame_again (); - void fetch_next_frame (); void active_jobs_changed (bool); void back_clicked (); void forward_clicked (); void player_changed (bool); - void set_position_text (Time); + void set_position_text (); + void get (DCPTime, bool); boost::shared_ptr<Film> _film; boost::shared_ptr<Player> _player; @@ -84,10 +69,10 @@ private: wxTimer _timer; boost::shared_ptr<const Image> _frame; - bool _got_frame; + DCPTime _position; /** Size of our output (including padding if we have any) */ - libdcp::Size _out_size; + dcp::Size _out_size; /** Size of the panel that we have available */ - libdcp::Size _panel_size; + dcp::Size _panel_size; }; diff --git a/src/wx/properties_dialog.cc b/src/wx/properties_dialog.cc index 28247bc33..801996efa 100644 --- a/src/wx/properties_dialog.cc +++ b/src/wx/properties_dialog.cc @@ -45,8 +45,7 @@ PropertiesDialog::PropertiesDialog (wxWindow* parent, shared_ptr<Film> film) add (_("Frames already encoded"), true); _encoded = add (new ThreadedStaticText (this, _("counting..."), boost::bind (&PropertiesDialog::frames_already_encoded, this))); _encoded->Finished.connect (boost::bind (&PropertiesDialog::layout, this)); - - _frames->SetLabel (std_to_wx (lexical_cast<string> (_film->time_to_video_frames (_film->length())))); + _frames->SetLabel (std_to_wx (lexical_cast<string> (_film->length().frames (_film->video_frame_rate ())))); double const disk = double (_film->required_disk_space()) / 1073741824.0f; stringstream s; s << fixed << setprecision (1) << disk << wx_to_std (_("Gb")); @@ -64,10 +63,11 @@ PropertiesDialog::frames_already_encoded () const } catch (boost::thread_interrupted &) { return ""; } - - if (_film->length()) { + + uint64_t const frames = _film->length().frames (_film->video_frame_rate ()); + if (frames) { /* XXX: encoded_frames() should check which frames have been encoded */ - u << " (" << (_film->encoded_frames() * 100 / _film->time_to_video_frames (_film->length())) << "%)"; + u << " (" << (_film->encoded_frames() * 100 / frames) << "%)"; } return u.str (); } diff --git a/src/wx/screen_dialog.cc b/src/wx/screen_dialog.cc index b702ae0ad..0d46a46ec 100644 --- a/src/wx/screen_dialog.cc +++ b/src/wx/screen_dialog.cc @@ -19,7 +19,7 @@ #include <wx/filepicker.h> #include <wx/validate.h> -#include <libdcp/exceptions.h> +#include <dcp/exceptions.h> #include "lib/compose.hpp" #include "lib/util.h" #include "screen_dialog.h" @@ -31,7 +31,7 @@ using std::string; using std::cout; using boost::shared_ptr; -ScreenDialog::ScreenDialog (wxWindow* parent, string title, string name, shared_ptr<libdcp::Certificate> certificate) +ScreenDialog::ScreenDialog (wxWindow* parent, string title, string name, shared_ptr<dcp::Certificate> certificate) : TableDialog (parent, std_to_wx (title), 2, true) , _certificate (certificate) { @@ -79,7 +79,7 @@ ScreenDialog::name () const return wx_to_std (_name->GetValue()); } -shared_ptr<libdcp::Certificate> +shared_ptr<dcp::Certificate> ScreenDialog::certificate () const { return _certificate; @@ -89,9 +89,9 @@ void ScreenDialog::load_certificate (boost::filesystem::path file) { try { - _certificate.reset (new libdcp::Certificate (file)); + _certificate.reset (new dcp::Certificate (file)); _certificate_text->SetValue (_certificate->certificate ()); - } catch (libdcp::MiscError& e) { + } catch (dcp::MiscError& e) { error_dialog (this, String::compose ("Could not read certificate file (%1)", e.what())); } } @@ -128,7 +128,7 @@ void ScreenDialog::setup_sensitivity () { wxButton* ok = dynamic_cast<wxButton*> (FindWindowById (wxID_OK, this)); - ok->Enable (_certificate); + ok->Enable (_certificate.get ()); _download_certificate->Enable ( _manufacturer->GetStringSelection() == _("Doremi") || diff --git a/src/wx/screen_dialog.h b/src/wx/screen_dialog.h index 3601a8f6c..5c6d964b8 100644 --- a/src/wx/screen_dialog.h +++ b/src/wx/screen_dialog.h @@ -19,7 +19,7 @@ #include <wx/wx.h> #include <boost/shared_ptr.hpp> -#include <libdcp/certificates.h> +#include <dcp/certificates.h> #include "table_dialog.h" class Progress; @@ -27,10 +27,10 @@ class Progress; class ScreenDialog : public TableDialog { public: - ScreenDialog (wxWindow *, std::string, std::string name = "", boost::shared_ptr<libdcp::Certificate> c = boost::shared_ptr<libdcp::Certificate> ()); + ScreenDialog (wxWindow *, std::string, std::string name = "", boost::shared_ptr<dcp::Certificate> c = boost::shared_ptr<dcp::Certificate> ()); std::string name () const; - boost::shared_ptr<libdcp::Certificate> certificate () const; + boost::shared_ptr<dcp::Certificate> certificate () const; private: void select_certificate (); @@ -44,5 +44,5 @@ private: wxButton* _download_certificate; wxTextCtrl* _certificate_text; - boost::shared_ptr<libdcp::Certificate> _certificate; + boost::shared_ptr<dcp::Certificate> _certificate; }; diff --git a/src/wx/subtitle_panel.cc b/src/wx/subtitle_panel.cc index 63a18b0ce..aa3d3a735 100644 --- a/src/wx/subtitle_panel.cc +++ b/src/wx/subtitle_panel.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2014 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 @@ -20,9 +20,12 @@ #include <boost/lexical_cast.hpp> #include <wx/spinctrl.h> #include "lib/ffmpeg_content.h" +#include "lib/subrip_content.h" +#include "lib/ffmpeg_subtitle_stream.h" #include "subtitle_panel.h" #include "film_editor.h" #include "wx_util.h" +#include "subtitle_view.h" using std::vector; using std::string; @@ -32,6 +35,7 @@ using boost::dynamic_pointer_cast; SubtitlePanel::SubtitlePanel (FilmEditor* e) : FilmEditorPanel (e, _("Subtitles")) + , _view (0) { wxFlexGridSizer* grid = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP); _sizer->Add (grid, 0, wxALL, 8); @@ -70,6 +74,9 @@ SubtitlePanel::SubtitlePanel (FilmEditor* e) add_label_to_sizer (grid, this, _("Subtitle Stream"), true); _stream = new wxChoice (this, wxID_ANY); grid->Add (_stream, 1, wxEXPAND); + + _view_button = new wxButton (this, wxID_ANY, _("View...")); + grid->Add (_view_button); _x_offset->SetRange (-100, 100); _y_offset->SetRange (-100, 100); @@ -81,6 +88,7 @@ SubtitlePanel::SubtitlePanel (FilmEditor* e) _y_offset->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&SubtitlePanel::y_offset_changed, this)); _scale->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&SubtitlePanel::scale_changed, this)); _stream->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&SubtitlePanel::stream_changed, this)); + _view_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&SubtitlePanel::view_clicked, this)); } void @@ -164,6 +172,9 @@ SubtitlePanel::setup_sensitivity () _y_offset->Enable (j); _scale->Enable (j); _stream->Enable (j); + + SubtitleContentList c = _editor->selected_subtitle_content (); + _view_button->Enable (c.size() == 1); } void @@ -223,3 +234,21 @@ SubtitlePanel::content_selection_changed () film_content_changed (SubtitleContentProperty::SUBTITLE_Y_OFFSET); film_content_changed (SubtitleContentProperty::SUBTITLE_SCALE); } + +void +SubtitlePanel::view_clicked () +{ + if (_view) { + _view->Destroy (); + _view = 0; + } + + SubtitleContentList c = _editor->selected_subtitle_content (); + assert (c.size() == 1); + shared_ptr<SubRipContent> sr = dynamic_pointer_cast<SubRipContent> (c.front ()); + if (sr) { + _view = new SubtitleView (this, sr); + } + + _view->Show (); +} diff --git a/src/wx/subtitle_panel.h b/src/wx/subtitle_panel.h index 20d7c40c2..1ee775025 100644 --- a/src/wx/subtitle_panel.h +++ b/src/wx/subtitle_panel.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2014 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 @@ -21,6 +21,7 @@ class wxCheckBox; class wxSpinCtrl; +class SubtitleView; class SubtitlePanel : public FilmEditorPanel { @@ -37,6 +38,7 @@ private: void y_offset_changed (); void scale_changed (); void stream_changed (); + void view_clicked (); void setup_sensitivity (); @@ -45,4 +47,6 @@ private: wxSpinCtrl* _y_offset; wxSpinCtrl* _scale; wxChoice* _stream; + wxButton* _view_button; + SubtitleView* _view; }; diff --git a/src/wx/subtitle_view.cc b/src/wx/subtitle_view.cc new file mode 100644 index 000000000..d14f260c9 --- /dev/null +++ b/src/wx/subtitle_view.cc @@ -0,0 +1,80 @@ +/* + Copyright (C) 2014 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/subrip_decoder.h" +#include "lib/content_subtitle.h" +#include "subtitle_view.h" + +using std::list; +using boost::shared_ptr; +using boost::dynamic_pointer_cast; + +SubtitleView::SubtitleView (wxWindow* parent, shared_ptr<SubRipContent> content) + : wxDialog (parent, wxID_ANY, _("Subtitles")) +{ + _list = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_SINGLE_SEL); + + { + wxListItem ip; + ip.SetId (0); + ip.SetText (_("Start")); + ip.SetWidth (100); + _list->InsertColumn (0, ip); + } + + { + wxListItem ip; + ip.SetId (1); + ip.SetText (_("End")); + ip.SetWidth (100); + _list->InsertColumn (1, ip); + } + + { + wxListItem ip; + ip.SetId (2); + ip.SetText (_("Subtitle")); + ip.SetWidth (640); + _list->InsertColumn (2, ip); + } + + wxBoxSizer* sizer = new wxBoxSizer (wxVERTICAL); + sizer->Add (_list, 1, wxEXPAND); + + wxSizer* buttons = CreateSeparatedButtonSizer (wxOK | wxCANCEL); + if (buttons) { + sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder()); + } + + shared_ptr<SubRipDecoder> decoder (new SubRipDecoder (content)); + list<shared_ptr<ContentTextSubtitle> > subs = decoder->get_text_subtitles (ContentTimePeriod (ContentTime(), ContentTime::max ())); + int n = 0; + for (list<shared_ptr<ContentTextSubtitle> >::const_iterator i = subs.begin(); i != subs.end(); ++i) { + for (list<dcp::SubtitleString>::const_iterator j = (*i)->subs.begin(); j != (*i)->subs.end(); ++j) { + wxListItem list_item; + list_item.SetId (n); + _list->InsertItem (list_item); + _list->SetItem (n, 2, j->text ()); + ++n; + } + } + + SetSizerAndFit (sizer); +} + diff --git a/src/wx/subtitle_view.h b/src/wx/subtitle_view.h new file mode 100644 index 000000000..94a25b70c --- /dev/null +++ b/src/wx/subtitle_view.h @@ -0,0 +1,33 @@ +/* + Copyright (C) 2014 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/shared_ptr.hpp> +#include <wx/wx.h> +#include <wx/listctrl.h> + +class SubRipContent; + +class SubtitleView : public wxDialog +{ +public: + SubtitleView (wxWindow *, boost::shared_ptr<SubRipContent>); + +private: + wxListCtrl* _list; +}; diff --git a/src/wx/timecode.cc b/src/wx/timecode.cc index ee5b5604b..1ab4b590b 100644 --- a/src/wx/timecode.cc +++ b/src/wx/timecode.cc @@ -83,12 +83,12 @@ Timecode::Timecode (wxWindow* parent) } void -Timecode::set (Time t, int fps) +Timecode::set (DCPTime t, int fps) { /* Do this calculation with frames so that we can round to a frame boundary at the start rather than the end. */ - int64_t f = divide_with_round (t * fps, TIME_HZ); + int64_t f = rint (t.seconds() * fps); int const h = f / (3600 * fps); f -= h * 3600 * fps; @@ -105,18 +105,18 @@ Timecode::set (Time t, int fps) _fixed->SetLabel (wxString::Format ("%02d:%02d:%02d.%02" wxLongLongFmtSpec "d", h, m, s, f)); } -Time +DCPTime Timecode::get (int fps) const { - Time t = 0; + DCPTime t; string const h = wx_to_std (_hours->GetValue ()); - t += lexical_cast<int> (h.empty() ? "0" : h) * 3600 * TIME_HZ; + t += DCPTime::from_seconds (lexical_cast<int> (h.empty() ? "0" : h) * 3600); string const m = wx_to_std (_minutes->GetValue()); - t += lexical_cast<int> (m.empty() ? "0" : m) * 60 * TIME_HZ; + t += DCPTime::from_seconds (lexical_cast<int> (m.empty() ? "0" : m) * 60); string const s = wx_to_std (_seconds->GetValue()); - t += lexical_cast<int> (s.empty() ? "0" : s) * TIME_HZ; + t += DCPTime::from_seconds (lexical_cast<int> (s.empty() ? "0" : s)); string const f = wx_to_std (_frames->GetValue()); - t += lexical_cast<int> (f.empty() ? "0" : f) * TIME_HZ / fps; + t += DCPTime::from_seconds (lexical_cast<double> (f.empty() ? "0" : f) / fps); return t; } diff --git a/src/wx/timecode.h b/src/wx/timecode.h index 880b44a31..b13e8c3c0 100644 --- a/src/wx/timecode.h +++ b/src/wx/timecode.h @@ -26,8 +26,8 @@ class Timecode : public wxPanel public: Timecode (wxWindow *); - void set (Time, int); - Time get (int) const; + void set (DCPTime, int); + DCPTime get (int) const; void set_editable (bool); diff --git a/src/wx/timeline.cc b/src/wx/timeline.cc index d4df6d8b2..4b56168a1 100644 --- a/src/wx/timeline.cc +++ b/src/wx/timeline.cc @@ -35,7 +35,9 @@ using boost::dynamic_pointer_cast; using boost::bind; using boost::optional; -/** Parent class for components of the timeline (e.g. a piece of content or an axis) */ +/** @class View + * @brief Parent class for components of the timeline (e.g. a piece of content or an axis). + */ class View : public boost::noncopyable { public: @@ -64,9 +66,9 @@ public: protected: virtual void do_paint (wxGraphicsContext *) = 0; - int time_x (Time t) const + int time_x (DCPTime t) const { - return _timeline.tracks_position().x + t * _timeline.pixels_per_time_unit().get_value_or (0); + return _timeline.tracks_position().x + t.seconds() * _timeline.pixels_per_second().get_value_or (0); } Timeline& _timeline; @@ -76,7 +78,9 @@ private: }; -/** Parent class for views of pieces of content */ +/** @class ContentView + * @brief Parent class for views of pieces of content. + */ class ContentView : public View { public: @@ -101,7 +105,7 @@ public: return dcpomatic::Rect<int> ( time_x (content->position ()) - 8, y_pos (_track.get()) - 8, - content->length_after_trim () * _timeline.pixels_per_time_unit().get_value_or(0) + 16, + content->length_after_trim().seconds() * _timeline.pixels_per_second().get_value_or(0) + 16, _timeline.track_height() + 16 ); } @@ -142,8 +146,8 @@ private: return; } - Time const position = cont->position (); - Time const len = cont->length_after_trim (); + DCPTime const position = cont->position (); + DCPTime const len = cont->length_after_trim (); wxColour selected (colour().Red() / 2, colour().Green() / 2, colour().Blue() / 2); @@ -172,7 +176,7 @@ private: wxDouble name_leading; gc->GetTextExtent (name, &name_width, &name_height, &name_descent, &name_leading); - gc->Clip (wxRegion (time_x (position), y_pos (_track.get()), len * _timeline.pixels_per_time_unit().get_value_or(0), _timeline.track_height())); + gc->Clip (wxRegion (time_x (position), y_pos (_track.get()), len.seconds() * _timeline.pixels_per_second().get_value_or(0), _timeline.track_height())); gc->DrawText (name, time_x (position) + 12, y_pos (_track.get() + 1) - name_height - 4); gc->ResetClip (); } @@ -191,7 +195,7 @@ private: } if (!frequent) { - _timeline.setup_pixels_per_time_unit (); + _timeline.setup_pixels_per_second (); _timeline.Refresh (); } } @@ -246,6 +250,25 @@ private: } }; +class SubtitleContentView : public ContentView +{ +public: + SubtitleContentView (Timeline& tl, shared_ptr<Content> c) + : ContentView (tl, c) + {} + +private: + wxString type () const + { + return _("subtitles"); + } + + wxColour colour () const + { + return wxColour (163, 255, 154, 255); + } +}; + class TimeAxisView : public View { public: @@ -269,26 +292,26 @@ private: void do_paint (wxGraphicsContext* gc) { - if (!_timeline.pixels_per_time_unit()) { + if (!_timeline.pixels_per_second()) { return; } - double const pptu = _timeline.pixels_per_time_unit().get (); + double const pps = _timeline.pixels_per_second().get (); gc->SetPen (*wxThePenList->FindOrCreatePen (wxColour (0, 0, 0), 1, wxPENSTYLE_SOLID)); - int mark_interval = rint (128 / (TIME_HZ * pptu)); + double mark_interval = rint (128 / pps); if (mark_interval > 5) { - mark_interval -= mark_interval % 5; + mark_interval -= int (rint (mark_interval)) % 5; } if (mark_interval > 10) { - mark_interval -= mark_interval % 10; + mark_interval -= int (rint (mark_interval)) % 10; } if (mark_interval > 60) { - mark_interval -= mark_interval % 60; + mark_interval -= int (rint (mark_interval)) % 60; } if (mark_interval > 3600) { - mark_interval -= mark_interval % 3600; + mark_interval -= int (rint (mark_interval)) % 3600; } if (mark_interval < 1) { @@ -300,14 +323,15 @@ private: path.AddLineToPoint (_timeline.width(), _y); gc->StrokePath (path); - Time t = 0; - while ((t * pptu) < _timeline.width()) { + /* Time in seconds */ + DCPTime t; + while ((t.seconds() * pps) < _timeline.width()) { wxGraphicsPath path = gc->CreatePath (); path.MoveToPoint (time_x (t), _y - 4); path.AddLineToPoint (time_x (t), _y + 4); gc->StrokePath (path); - int tc = t / TIME_HZ; + double tc = t.seconds (); int const h = tc / 3600; tc -= h * 3600; int const m = tc / 60; @@ -321,12 +345,12 @@ private: wxDouble str_leading; gc->GetTextExtent (str, &str_width, &str_height, &str_descent, &str_leading); - int const tx = _timeline.x_offset() + t * pptu; + int const tx = _timeline.x_offset() + t.seconds() * pps; if ((tx + str_width) < _timeline.width()) { gc->DrawText (str, time_x (t), _y + 16); } - t += mark_interval * TIME_HZ; + t += DCPTime::from_seconds (mark_interval); } } @@ -406,10 +430,13 @@ Timeline::playlist_changed () if (dynamic_pointer_cast<AudioContent> (*i)) { _views.push_back (shared_ptr<View> (new AudioContentView (*this, *i))); } + if (dynamic_pointer_cast<SubtitleContent> (*i)) { + _views.push_back (shared_ptr<View> (new SubtitleContentView (*this, *i))); + } } assign_tracks (); - setup_pixels_per_time_unit (); + setup_pixels_per_second (); Refresh (); } @@ -421,11 +448,11 @@ Timeline::assign_tracks () if (!cv) { continue; } - + shared_ptr<Content> content = cv->content(); int t = 0; - while (1) { + while (true) { ViewList::iterator j = _views.begin(); while (j != _views.end()) { shared_ptr<ContentView> test = dynamic_pointer_cast<ContentView> (*j); @@ -471,14 +498,14 @@ Timeline::tracks () const } void -Timeline::setup_pixels_per_time_unit () +Timeline::setup_pixels_per_second () { shared_ptr<const Film> film = _film.lock (); - if (!film || film->length() == 0) { + if (!film || film->length() == DCPTime ()) { return; } - _pixels_per_time_unit = static_cast<double>(width() - x_offset() * 2) / film->length (); + _pixels_per_second = static_cast<double>(width() - x_offset() * 2) / film->length().seconds (); } shared_ptr<View> @@ -580,11 +607,11 @@ Timeline::right_down (wxMouseEvent& ev) void Timeline::set_position_from_event (wxMouseEvent& ev) { - if (!_pixels_per_time_unit) { + if (!_pixels_per_second) { return; } - double const pptu = _pixels_per_time_unit.get (); + double const pps = _pixels_per_second.get (); wxPoint const p = ev.GetPosition(); @@ -603,13 +630,13 @@ Timeline::set_position_from_event (wxMouseEvent& ev) return; } - Time new_position = _down_view_position + (p.x - _down_point.x) / pptu; + DCPTime new_position = _down_view_position + DCPTime::from_seconds ((p.x - _down_point.x) / pps); if (_snap) { bool first = true; - Time nearest_distance = TIME_MAX; - Time nearest_new_position = TIME_MAX; + DCPTime nearest_distance = DCPTime::max (); + DCPTime nearest_new_position = DCPTime::max (); /* Find the nearest content edge; this is inefficient */ for (ViewList::iterator i = _views.begin(); i != _views.end(); ++i) { @@ -620,7 +647,7 @@ Timeline::set_position_from_event (wxMouseEvent& ev) { /* Snap starts to ends */ - Time const d = abs (cv->content()->end() - new_position); + DCPTime const d = DCPTime (cv->content()->end() - new_position).abs (); if (first || d < nearest_distance) { nearest_distance = d; nearest_new_position = cv->content()->end(); @@ -629,7 +656,10 @@ Timeline::set_position_from_event (wxMouseEvent& ev) { /* Snap ends to starts */ - Time const d = abs (cv->content()->position() - (new_position + _down_view->content()->length_after_trim())); + DCPTime const d = DCPTime ( + cv->content()->position() - (new_position + _down_view->content()->length_after_trim()) + ).abs (); + if (d < nearest_distance) { nearest_distance = d; nearest_new_position = cv->content()->position() - _down_view->content()->length_after_trim (); @@ -641,14 +671,14 @@ Timeline::set_position_from_event (wxMouseEvent& ev) if (!first) { /* Snap if it's close; `close' means within a proportion of the time on the timeline */ - if (nearest_distance < (width() / pptu) / 32) { + if (nearest_distance < DCPTime::from_seconds ((width() / pps) / 32)) { new_position = nearest_new_position; } } } - if (new_position < 0) { - new_position = 0; + if (new_position < DCPTime ()) { + new_position = DCPTime (); } _down_view->content()->set_position (new_position); @@ -673,7 +703,7 @@ Timeline::film () const void Timeline::resized () { - setup_pixels_per_time_unit (); + setup_pixels_per_second (); } void diff --git a/src/wx/timeline.h b/src/wx/timeline.h index 7b4d75d09..4ba1cc425 100644 --- a/src/wx/timeline.h +++ b/src/wx/timeline.h @@ -52,8 +52,8 @@ public: return 48; } - boost::optional<double> pixels_per_time_unit () const { - return _pixels_per_time_unit; + boost::optional<double> pixels_per_second () const { + return _pixels_per_second; } Position<int> tracks_position () const { @@ -62,7 +62,7 @@ public: int tracks () const; - void setup_pixels_per_time_unit (); + void setup_pixels_per_second (); void set_snap (bool s) { _snap = s; @@ -96,11 +96,11 @@ private: ViewList _views; boost::shared_ptr<TimeAxisView> _time_axis_view; int _tracks; - boost::optional<double> _pixels_per_time_unit; + boost::optional<double> _pixels_per_second; bool _left_down; wxPoint _down_point; boost::shared_ptr<ContentView> _down_view; - Time _down_view_position; + DCPTime _down_view_position; bool _first_move; ContentMenu _menu; bool _snap; diff --git a/src/wx/timing_panel.cc b/src/wx/timing_panel.cc index 6d9bf4539..cc0639b4c 100644 --- a/src/wx/timing_panel.cc +++ b/src/wx/timing_panel.cc @@ -87,7 +87,7 @@ TimingPanel::film_content_changed (int property) if (content) { _position->set (content->position (), film_video_frame_rate); } else { - _position->set (0, 24); + _position->set (DCPTime () , 24); } } else if ( property == ContentProperty::LENGTH || @@ -98,24 +98,24 @@ TimingPanel::film_content_changed (int property) _full_length->set (content->full_length (), film_video_frame_rate); _play_length->set (content->length_after_trim (), film_video_frame_rate); } else { - _full_length->set (0, 24); - _play_length->set (0, 24); + _full_length->set (DCPTime (), 24); + _play_length->set (DCPTime (), 24); } } else if (property == ContentProperty::TRIM_START) { if (content) { _trim_start->set (content->trim_start (), film_video_frame_rate); _play_length->set (content->length_after_trim (), film_video_frame_rate); } else { - _trim_start->set (0, 24); - _play_length->set (0, 24); + _trim_start->set (DCPTime (), 24); + _play_length->set (DCPTime (), 24); } } else if (property == ContentProperty::TRIM_END) { if (content) { _trim_end->set (content->trim_end (), film_video_frame_rate); _play_length->set (content->length_after_trim (), film_video_frame_rate); } else { - _trim_end->set (0, 24); - _play_length->set (0, 24); + _trim_end->set (DCPTime (), 24); + _play_length->set (DCPTime (), 24); } } @@ -155,7 +155,8 @@ TimingPanel::full_length_changed () if (c.size() == 1) { shared_ptr<ImageContent> ic = dynamic_pointer_cast<ImageContent> (c.front ()); if (ic && ic->still ()) { - ic->set_video_length (rint (_full_length->get (_editor->film()->video_frame_rate()) * ic->video_frame_rate() / TIME_HZ)); + /* XXX: No effective FRC here... is this right? */ + ic->set_video_length (ContentTime (_full_length->get (_editor->film()->video_frame_rate()), FrameRateChange (1, 1))); } } } diff --git a/src/wx/video_panel.cc b/src/wx/video_panel.cc index 2d874b959..2a5577bc1 100644 --- a/src/wx/video_panel.cc +++ b/src/wx/video_panel.cc @@ -298,8 +298,8 @@ VideoPanel::setup_description () } 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 (); + if ((crop.left || crop.right || crop.top || crop.bottom) && vcs->video_size() != dcp::Size (0, 0)) { + dcp::Size cropped = vcs->video_size_after_crop (); d << wxString::Format ( _("Cropped to %dx%d (%.2f:1)\n"), cropped.width, cropped.height, @@ -308,8 +308,8 @@ VideoPanel::setup_description () ++lines; } - libdcp::Size const container_size = _editor->film()->frame_size (); - libdcp::Size const scaled = vcs->scale().size (vcs, container_size, container_size); + dcp::Size const container_size = _editor->film()->frame_size (); + dcp::Size const scaled = vcs->scale().size (vcs, container_size, container_size); if (scaled != vcs->video_size_after_crop ()) { d << wxString::Format ( diff --git a/src/wx/video_panel.h b/src/wx/video_panel.h index 99633491d..4331a9712 100644 --- a/src/wx/video_panel.h +++ b/src/wx/video_panel.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2014 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 @@ -17,6 +17,10 @@ */ +/** @file src/lib/video_panel.h + * @brief VideoPanel class. + */ + #include "lib/film.h" #include "film_editor_panel.h" #include "content_widget.h" @@ -26,6 +30,9 @@ class wxStaticText; class wxSpinCtrl; class wxButton; +/** @class VideoPanel + * @brief The video tab of the film editor. + */ class VideoPanel : public FilmEditorPanel { public: diff --git a/src/wx/wscript b/src/wx/wscript index 8c142698b..0c87c09be 100644 --- a/src/wx/wscript +++ b/src/wx/wscript @@ -38,6 +38,7 @@ sources = """ server_dialog.cc servers_list_dialog.cc subtitle_panel.cc + subtitle_view.cc table_dialog.cc timecode.cc timeline.cc diff --git a/src/wx/wx_ui_signaller.cc b/src/wx/wx_ui_signaller.cc index f30631960..8fc6670d6 100644 --- a/src/wx/wx_ui_signaller.cc +++ b/src/wx/wx_ui_signaller.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2014 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 diff --git a/src/wx/wx_ui_signaller.h b/src/wx/wx_ui_signaller.h index f7df6fca4..63f2049cd 100644 --- a/src/wx/wx_ui_signaller.h +++ b/src/wx/wx_ui_signaller.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2014 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 @@ -21,6 +21,10 @@ class wxEvtHandler; +/** @class wxUISignaller + * @brief UISignaller for the wxWidgets event loop + */ + class wxUISignaller : public UISignaller { public: diff --git a/src/wx/wx_util.cc b/src/wx/wx_util.cc index b73cd490d..aac35e97a 100644 --- a/src/wx/wx_util.cc +++ b/src/wx/wx_util.cc @@ -123,7 +123,7 @@ int const ThreadedStaticText::_update_event_id = 10000; * @param initial Initial text for the wxStaticText while the computation is being run. * @param fn Function which works out what the wxStaticText content should be and returns it. */ -ThreadedStaticText::ThreadedStaticText (wxWindow* parent, wxString initial, function<string ()> fn) +ThreadedStaticText::ThreadedStaticText (wxWindow* parent, wxString initial, boost::function<string ()> fn) : wxStaticText (parent, wxID_ANY, initial) { Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&ThreadedStaticText::thread_finished, this, _1), _update_event_id); @@ -139,7 +139,7 @@ ThreadedStaticText::~ThreadedStaticText () /** Run our thread and post the result to the GUI thread via AddPendingEvent */ void -ThreadedStaticText::run (function<string ()> fn) +ThreadedStaticText::run (boost::function<string ()> fn) try { wxCommandEvent ev (wxEVT_COMMAND_TEXT_UPDATED, _update_event_id); |
