X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Fwx%2Ffilm_editor.cc;h=ca43ffb8a2a8b1c57ab6685be2b976812a71b052;hb=f08d36982bf940dbd59caf6f24a90c1429fca5f8;hp=feb49ed78a394b392f93e118ae604fe3e2948ce9;hpb=d62877ae6c4e316e43f4052e4b9ba673610012cf;p=dcpomatic.git diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc index feb49ed78..ca43ffb8a 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -50,7 +50,9 @@ #include "scaler.h" #include "audio_dialog.h" #include "imagemagick_content_dialog.h" +#include "ffmpeg_content_dialog.h" #include "audio_mapping_view.h" +#include "timeline_dialog.h" using std::string; using std::cout; @@ -60,6 +62,7 @@ using std::fixed; using std::setprecision; using std::list; using std::vector; +using std::max; using boost::shared_ptr; using boost::weak_ptr; using boost::dynamic_pointer_cast; @@ -70,6 +73,7 @@ FilmEditor::FilmEditor (shared_ptr f, wxWindow* parent) : wxPanel (parent) , _generally_sensitive (true) , _audio_dialog (0) + , _timeline_dialog (0) { wxBoxSizer* s = new wxBoxSizer (wxVERTICAL); _notebook = new wxNotebook (this, wxID_ANY); @@ -86,6 +90,8 @@ FilmEditor::FilmEditor (shared_ptr f, wxWindow* parent) make_subtitle_panel (); _notebook->AddPage (_subtitle_panel, _("Subtitles"), false); + setup_formats (); + set_film (f); connect_to_widgets (); @@ -93,8 +99,6 @@ FilmEditor::FilmEditor (shared_ptr f, wxWindow* parent) bind (&FilmEditor::active_jobs_changed, this, _1) ); - setup_formats (); - SetSizerAndFit (s); } @@ -146,7 +150,7 @@ FilmEditor::make_film_panel () } ++r; - _frame_rate_description = new wxStaticText (_film_panel, wxID_ANY, wxT (" \n \n "), wxDefaultPosition, wxDefaultSize); + _frame_rate_description = new wxStaticText (_film_panel, wxID_ANY, wxT ("\n \n "), wxDefaultPosition, wxDefaultSize); grid->Add (_frame_rate_description, wxGBPosition (r, 0), wxGBSpan (1, 2), wxEXPAND | wxALIGN_CENTER_VERTICAL | wxALL, 6); wxFont font = _frame_rate_description->GetFont(); font.SetStyle(wxFONTSTYLE_ITALIC); @@ -174,6 +178,11 @@ FilmEditor::make_film_panel () } ++r; + add_label_to_grid_bag_sizer (grid, _film_panel, _("Trim method"), wxGBPosition (r, 0)); + _trim_type = new wxChoice (_film_panel, wxID_ANY); + grid->Add (_trim_type, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL); + ++r; + _ab = new wxCheckBox (_film_panel, wxID_ANY, _("A/B")); grid->Add (_ab, wxGBPosition (r, 0)); ++r; @@ -187,49 +196,54 @@ FilmEditor::make_film_panel () for (list::const_iterator i = dfr.begin(); i != dfr.end(); ++i) { _dcp_frame_rate->Append (std_to_wx (boost::lexical_cast (*i))); } + + _trim_type->Append (_("encode all frames and play the subset")); + _trim_type->Append (_("encode only the subset")); } void FilmEditor::connect_to_widgets () { - _name->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (FilmEditor::name_changed), 0, this); - _use_dci_name->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::use_dci_name_toggled), 0, this); - _edit_dci_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::edit_dci_button_clicked), 0, this); - _format->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::format_changed), 0, this); - _trust_content_headers->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::trust_content_headers_changed), 0, this); - _content->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler (FilmEditor::content_selection_changed), 0, this); - _content->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler (FilmEditor::content_selection_changed), 0, this); - _content->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler (FilmEditor::content_activated), 0, this); - _content_add->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_add_clicked), 0, this); - _content_remove->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_remove_clicked), 0, this); - _content_edit->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_edit_clicked), 0, this); - _content_earlier->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_earlier_clicked), 0, this); - _content_later->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_later_clicked), 0, this); - _left_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::left_crop_changed), 0, this); - _right_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::right_crop_changed), 0, this); - _top_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::top_crop_changed), 0, this); - _bottom_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::bottom_crop_changed), 0, this); - _filters_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::edit_filters_clicked), 0, this); - _scaler->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::scaler_changed), 0, this); - _dcp_content_type->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_content_type_changed), 0, this); - _dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_frame_rate_changed), 0, this); - _best_dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::best_dcp_frame_rate_clicked), 0, this); - _ab->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::ab_toggled), 0, this); - _trim_start->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::trim_start_changed), 0, this); - _trim_end->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::trim_end_changed), 0, this); - _with_subtitles->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::with_subtitles_toggled), 0, this); - _subtitle_offset->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::subtitle_offset_changed), 0, this); - _subtitle_scale->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::subtitle_scale_changed), 0, this); - _colour_lut->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::colour_lut_changed), 0, this); - _j2k_bandwidth->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::j2k_bandwidth_changed), 0, this); - _ffmpeg_subtitle_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::ffmpeg_subtitle_stream_changed), 0, this); - _ffmpeg_audio_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::ffmpeg_audio_stream_changed), 0, this); - _audio_gain->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::audio_gain_changed), 0, this); + _name->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (FilmEditor::name_changed), 0, this); + _use_dci_name->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::use_dci_name_toggled), 0, this); + _edit_dci_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::edit_dci_button_clicked), 0, this); + _format->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::format_changed), 0, this); + _trust_content_headers->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::trust_content_headers_changed), 0, this); + _content->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler (FilmEditor::content_selection_changed), 0, this); + _content->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler (FilmEditor::content_selection_changed), 0, this); + _content->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler (FilmEditor::content_activated), 0, this); + _content_add->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_add_clicked), 0, this); + _content_remove->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_remove_clicked), 0, this); + _content_properties->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_properties_clicked), 0, this); + _content_earlier->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_earlier_clicked), 0, this); + _content_later->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_later_clicked), 0, this); + _content_timeline->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_timeline_clicked), 0, this); + _loop_content->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::loop_content_toggled), 0, this); + _loop_count->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::loop_count_changed), 0, this); + _left_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::left_crop_changed), 0, this); + _right_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::right_crop_changed), 0, this); + _top_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::top_crop_changed), 0, this); + _bottom_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::bottom_crop_changed), 0, this); + _filters_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::edit_filters_clicked), 0, this); + _scaler->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::scaler_changed), 0, this); + _dcp_content_type->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_content_type_changed), 0, this); + _dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_frame_rate_changed), 0, this); + _best_dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::best_dcp_frame_rate_clicked), 0, this); + _ab->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::ab_toggled), 0, this); + _trim_start->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::trim_start_changed), 0, this); + _trim_end->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::trim_end_changed), 0, this); + _trim_type->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::trim_type_changed), 0, this); + _with_subtitles->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::with_subtitles_toggled), 0, this); + _subtitle_offset->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::subtitle_offset_changed), 0, this); + _subtitle_scale->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::subtitle_scale_changed), 0, this); + _colour_lut->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::colour_lut_changed), 0, this); + _j2k_bandwidth->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::j2k_bandwidth_changed), 0, this); + _audio_gain->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::audio_gain_changed), 0, this); _audio_gain_calculate_button->Connect ( wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::audio_gain_calculate_button_clicked), 0, this ); - _show_audio->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::show_audio_clicked), 0, this); - _audio_delay->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::audio_delay_changed), 0, this); + _show_audio->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::show_audio_clicked), 0, this); + _audio_delay->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::audio_delay_changed), 0, this); } void @@ -347,20 +361,32 @@ FilmEditor::make_content_panel () b->Add (_content_add); _content_remove = new wxButton (_content_panel, wxID_ANY, _("Remove")); b->Add (_content_remove); - _content_edit = new wxButton (_content_panel, wxID_ANY, _("Edit...")); - b->Add (_content_edit); + _content_properties = new wxButton (_content_panel, wxID_ANY, _("Properties...")); + b->Add (_content_properties); _content_earlier = new wxButton (_content_panel, wxID_ANY, _("Earlier")); b->Add (_content_earlier); _content_later = new wxButton (_content_panel, wxID_ANY, _("Later")); b->Add (_content_later); + _content_timeline = new wxButton (_content_panel, wxID_ANY, _("Timeline...")); + b->Add (_content_timeline); s->Add (b, 0, wxALL, 4); - _content_sizer->Add (s, 1, wxEXPAND | wxALL, 6); + _content_sizer->Add (s, 0.75, wxEXPAND | wxALL, 6); } - _content_information = new wxTextCtrl (_content_panel, wxID_ANY, wxT ("\n\n\n\n"), wxDefaultPosition, wxDefaultSize, wxTE_READONLY | wxTE_MULTILINE); + _content_information = new wxTextCtrl (_content_panel, wxID_ANY, wxT ("\n \n "), wxDefaultPosition, wxDefaultSize, wxTE_READONLY | wxTE_MULTILINE); _content_sizer->Add (_content_information, 1, wxEXPAND | wxALL, 6); + + wxBoxSizer* h = new wxBoxSizer (wxHORIZONTAL); + _loop_content = new wxCheckBox (_content_panel, wxID_ANY, _("Loop everything")); + h->Add (_loop_content, 0, wxALL, 6); + _loop_count = new wxSpinCtrl (_content_panel, wxID_ANY); + h->Add (_loop_count, 0, wxALL, 6); + add_label_to_sizer (h, _content_panel, _("times")); + _content_sizer->Add (h, 0, wxALL, 6); + + _loop_count->SetRange (2, 1024); } void @@ -398,16 +424,6 @@ FilmEditor::make_audio_panel () grid->Add (s); } - { - add_label_to_sizer (grid, _audio_panel, _("Audio Stream")); - wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); - _ffmpeg_audio_stream = new wxChoice (_audio_panel, wxID_ANY); - s->Add (_ffmpeg_audio_stream, 1); - _audio = new wxStaticText (_audio_panel, wxID_ANY, wxT ("")); - s->Add (_audio, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, 8); - grid->Add (s, 1, wxEXPAND); - } - _audio_mapping = new AudioMappingView (_audio_panel); _audio_sizer->Add (_audio_mapping, 1, wxEXPAND | wxALL, 6); @@ -426,10 +442,8 @@ FilmEditor::make_subtitle_panel () _with_subtitles = new wxCheckBox (_subtitle_panel, wxID_ANY, _("With Subtitles")); grid->Add (_with_subtitles, 1); + grid->AddSpacer (0); - _ffmpeg_subtitle_stream = new wxChoice (_subtitle_panel, wxID_ANY); - grid->Add (_ffmpeg_subtitle_stream); - { add_label_to_sizer (grid, _subtitle_panel, _("Subtitle Offset")); wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); @@ -606,8 +620,13 @@ FilmEditor::film_changed (Film::Property p) setup_formats (); setup_format (); setup_subtitle_control_sensitivity (); - setup_streams (); setup_show_audio_sensitivity (); + setup_length (); + break; + case Film::LOOP: + checked_set (_loop_content, _film->loop() > 1); + checked_set (_loop_count, _film->loop()); + setup_loop_sensitivity (); break; case Film::TRUST_CONTENT_HEADERS: checked_set (_trust_content_headers, _film->trust_content_headers ()); @@ -654,6 +673,9 @@ FilmEditor::film_changed (Film::Property p) case Film::TRIM_END: checked_set (_trim_end, _film->trim_end()); break; + case Film::TRIM_TYPE: + checked_set (_trim_type, _film->trim_type() == Film::CPL ? 0 : 1); + break; case Film::AUDIO_GAIN: checked_set (_audio_gain, _film->audio_gain ()); break; @@ -685,15 +707,20 @@ FilmEditor::film_changed (Film::Property p) setup_dcp_name (); break; case Film::DCP_FRAME_RATE: + { + bool done = false; for (unsigned int i = 0; i < _dcp_frame_rate->GetCount(); ++i) { if (wx_to_std (_dcp_frame_rate->GetString(i)) == boost::lexical_cast (_film->dcp_frame_rate())) { - if (_dcp_frame_rate->GetSelection() != int(i)) { - _dcp_frame_rate->SetSelection (i); - break; - } + checked_set (_dcp_frame_rate, i); + done = true; + break; } } + if (!done) { + checked_set (_dcp_frame_rate, -1); + } + if (_film->video_frame_rate()) { _best_dcp_frame_rate->Enable (best_dcp_frame_rate (_film->video_frame_rate ()) != _film->dcp_frame_rate ()); } else { @@ -701,6 +728,7 @@ FilmEditor::film_changed (Film::Property p) } setup_frame_rate_description (); break; + } case Film::AUDIO_MAPPING: _audio_mapping->set_mapping (_film->audio_mapping ()); break; @@ -719,27 +747,17 @@ FilmEditor::film_content_changed (weak_ptr content, int property) if (property == FFmpegContentProperty::SUBTITLE_STREAMS) { setup_subtitle_control_sensitivity (); - setup_streams (); } else if (property == FFmpegContentProperty::AUDIO_STREAMS) { - setup_streams (); setup_show_audio_sensitivity (); - } else if (property == VideoContentProperty::VIDEO_LENGTH) { + } else if (property == VideoContentProperty::VIDEO_LENGTH || property == AudioContentProperty::AUDIO_LENGTH) { setup_length (); boost::shared_ptr c = content.lock (); if (c && c == selected_content()) { setup_content_information (); } } else if (property == FFmpegContentProperty::AUDIO_STREAM) { - if (_film->ffmpeg_audio_stream()) { - checked_set (_ffmpeg_audio_stream, boost::lexical_cast (_film->ffmpeg_audio_stream()->id)); - } setup_dcp_name (); - setup_audio_details (); setup_show_audio_sensitivity (); - } else if (property == FFmpegContentProperty::SUBTITLE_STREAM) { - if (_film->ffmpeg_subtitle_stream()) { - checked_set (_ffmpeg_subtitle_stream, boost::lexical_cast (_film->ffmpeg_subtitle_stream()->id)); - } } } @@ -767,17 +785,19 @@ void FilmEditor::setup_length () { stringstream s; - if (_film->video_frame_rate() > 0 && _film->video_length()) { - s << _film->video_length() << " " - << wx_to_std (_("frames")) << "; " << seconds_to_hms (_film->video_length() / _film->video_frame_rate()); - } else if (_film->video_length()) { - s << _film->video_length() << " " - << wx_to_std (_("frames")); - } + ContentVideoFrame const frames = _film->content_length (); + + if (frames && _film->video_frame_rate()) { + s << frames << " " << wx_to_std (_("frames")) << "; " << seconds_to_hms (frames / _film->video_frame_rate()); + } else if (frames) { + s << frames << " " << wx_to_std (_("frames")); + } + _length->SetLabel (std_to_wx (s.str ())); - if (_film->video_length()) { - _trim_start->SetRange (0, _film->video_length()); - _trim_end->SetRange (0, _film->video_length()); + + if (frames) { + _trim_start->SetRange (0, frames); + _trim_end->SetRange (0, frames); } } @@ -785,23 +805,27 @@ void FilmEditor::setup_frame_rate_description () { wxString d; + int lines = 0; + if (_film->video_frame_rate()) { d << std_to_wx (FrameRateConversion (_film->video_frame_rate(), _film->dcp_frame_rate()).description); + ++lines; #ifdef HAVE_SWRESAMPLE - if (_film->audio_frame_rate() != _film->target_audio_sample_rate ()) { + if (_film->audio_frame_rate() && _film->audio_frame_rate() != _film->target_audio_sample_rate ()) { d << wxString::Format ( _("Audio will be resampled from %dHz to %dHz\n"), _film->audio_frame_rate(), _film->target_audio_sample_rate() ); - } else { - d << "\n"; + ++lines; } -#else - d << "\n"; #endif } + for (int i = lines; i < 2; ++i) { + d << wxT ("\n "); + } + _frame_rate_description->SetLabel (d); } @@ -838,7 +862,7 @@ FilmEditor::dcp_content_type_changed (wxCommandEvent &) void FilmEditor::set_film (shared_ptr f) { - set_things_sensitive (_film != 0); + set_things_sensitive (f != 0); if (_film == f) { return; @@ -864,6 +888,7 @@ FilmEditor::set_film (shared_ptr f) film_changed (Film::NAME); film_changed (Film::USE_DCI_NAME); film_changed (Film::CONTENT); + film_changed (Film::LOOP); film_changed (Film::TRUST_CONTENT_HEADERS); film_changed (Film::DCP_CONTENT_TYPE); film_changed (Film::FORMAT); @@ -873,6 +898,7 @@ FilmEditor::set_film (shared_ptr f) film_changed (Film::TRIM_START); film_changed (Film::TRIM_END); film_changed (Film::AB); + film_changed (Film::TRIM_TYPE); film_changed (Film::AUDIO_GAIN); film_changed (Film::AUDIO_DELAY); film_changed (Film::WITH_SUBTITLES); @@ -888,6 +914,8 @@ FilmEditor::set_film (shared_ptr f) film_content_changed (boost::shared_ptr (), FFmpegContentProperty::SUBTITLE_STREAM); film_content_changed (boost::shared_ptr (), FFmpegContentProperty::AUDIO_STREAMS); film_content_changed (boost::shared_ptr (), FFmpegContentProperty::AUDIO_STREAM); + + setup_content_information (); } /** Updates the sensitivity of lots of widgets to a given value. @@ -911,12 +939,13 @@ FilmEditor::set_things_sensitive (bool s) _bottom_crop->Enable (s); _filters_button->Enable (s); _scaler->Enable (s); - _ffmpeg_audio_stream->Enable (s); _dcp_content_type->Enable (s); + _best_dcp_frame_rate->Enable (s); _dcp_frame_rate->Enable (s); _trim_start->Enable (s); _trim_end->Enable (s); _ab->Enable (s); + _trim_type->Enable (s); _colour_lut->Enable (s); _j2k_bandwidth->Enable (s); _audio_gain->Enable (s); @@ -1066,7 +1095,7 @@ FilmEditor::setup_subtitle_control_sensitivity () { bool h = false; if (_generally_sensitive && _film) { - h = !_film->ffmpeg_subtitle_streams().empty(); + h = _film->has_subtitles (); } _with_subtitles->Enable (h); @@ -1076,7 +1105,6 @@ FilmEditor::setup_subtitle_control_sensitivity () j = _film->with_subtitles (); } - _ffmpeg_subtitle_stream->Enable (j); _subtitle_offset->Enable (j); _subtitle_scale->Enable (j); } @@ -1104,93 +1132,6 @@ FilmEditor::edit_dci_button_clicked (wxCommandEvent &) d->Destroy (); } -void -FilmEditor::setup_streams () -{ - if (!_film) { - return; - } - - _ffmpeg_audio_stream->Clear (); - vector a = _film->ffmpeg_audio_streams (); - for (vector::iterator i = a.begin(); i != a.end(); ++i) { - _ffmpeg_audio_stream->Append (std_to_wx (i->name), new wxStringClientData (std_to_wx (boost::lexical_cast (i->id)))); - } - - if (_film->ffmpeg_audio_stream()) { - checked_set (_ffmpeg_audio_stream, boost::lexical_cast (_film->ffmpeg_audio_stream()->id)); - } - - _ffmpeg_subtitle_stream->Clear (); - vector s = _film->ffmpeg_subtitle_streams (); - for (vector::iterator i = s.begin(); i != s.end(); ++i) { - _ffmpeg_subtitle_stream->Append (std_to_wx (i->name), new wxStringClientData (std_to_wx (boost::lexical_cast (i->id)))); - } - - if (_film->ffmpeg_subtitle_stream()) { - checked_set (_ffmpeg_subtitle_stream, boost::lexical_cast (_film->ffmpeg_subtitle_stream()->id)); - } else { - _ffmpeg_subtitle_stream->SetSelection (wxNOT_FOUND); - } -} - -void -FilmEditor::ffmpeg_audio_stream_changed (wxCommandEvent &) -{ - if (!_film) { - return; - } - - vector a = _film->ffmpeg_audio_streams (); - vector::iterator i = a.begin (); - string const s = string_client_data (_ffmpeg_audio_stream->GetClientObject (_ffmpeg_audio_stream->GetSelection ())); - while (i != a.end() && lexical_cast (i->id) != s) { - ++i; - } - - if (i != a.end ()) { - _film->set_ffmpeg_audio_stream (*i); - } -} - -void -FilmEditor::ffmpeg_subtitle_stream_changed (wxCommandEvent &) -{ - if (!_film) { - return; - } - - vector a = _film->ffmpeg_subtitle_streams (); - vector::iterator i = a.begin (); - string const s = string_client_data (_ffmpeg_subtitle_stream->GetClientObject (_ffmpeg_subtitle_stream->GetSelection ())); - while (i != a.end() && lexical_cast (i->id) != s) { - ++i; - } - - if (i != a.end ()) { - _film->set_ffmpeg_subtitle_stream (*i); - } -} - -void -FilmEditor::setup_audio_details () -{ - if (!_film->ffmpeg_audio_stream()) { - _audio->SetLabel (wxT ("")); - } else { - wxString s; - if (_film->audio_channels() == 1) { - s << _("1 channel"); - } else { - s << _film->audio_channels() << " " << _("channels"); - } - s << ", " << _film->audio_frame_rate() << _("Hz"); - _audio->SetLabel (s); - } - - setup_notebook_size (); -} - void FilmEditor::active_jobs_changed (bool a) { @@ -1262,12 +1203,14 @@ FilmEditor::setup_content () /* Select the first item of content if non was selected before */ _content->SetItemState (0, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); } + + setup_content_information (); } void FilmEditor::content_add_clicked (wxCommandEvent &) { - wxFileDialog* d = new wxFileDialog (this); + wxFileDialog* d = new wxFileDialog (this, _("Choose a file or files"), wxT (""), wxT (""), wxT ("*.*"), wxFD_MULTIPLE); int const r = d->ShowModal (); d->Destroy (); @@ -1275,16 +1218,20 @@ FilmEditor::content_add_clicked (wxCommandEvent &) return; } - boost::filesystem::path p (wx_to_std (d->GetPath())); + wxArrayString paths; + d->GetPaths (paths); - if (ImageMagickContent::valid_file (p)) { - _film->add_content (shared_ptr (new ImageMagickContent (p))); - } else if (SndfileContent::valid_file (p)) { - _film->add_content (shared_ptr (new SndfileContent (p))); - } else { - _film->add_content (shared_ptr (new FFmpegContent (p))); + for (unsigned int i = 0; i < paths.GetCount(); ++i) { + boost::filesystem::path p (wx_to_std (paths[i])); + + if (ImageMagickContent::valid_file (p)) { + _film->add_content (shared_ptr (new ImageMagickContent (p))); + } else if (SndfileContent::valid_file (p)) { + _film->add_content (shared_ptr (new SndfileContent (p))); + } else { + _film->add_content (shared_ptr (new FFmpegContent (p))); + } } - } void @@ -1302,30 +1249,35 @@ FilmEditor::content_activated (wxListEvent& ev) ContentList c = _film->content (); assert (ev.GetIndex() >= 0 && size_t (ev.GetIndex()) < c.size ()); - edit_content (c[ev.GetIndex()]); + content_properties (c[ev.GetIndex()]); } void -FilmEditor::content_edit_clicked (wxCommandEvent &) +FilmEditor::content_properties_clicked (wxCommandEvent &) { shared_ptr c = selected_content (); if (!c) { return; } - edit_content (c); + content_properties (c); } void -FilmEditor::edit_content (shared_ptr c) +FilmEditor::content_properties (shared_ptr c) { shared_ptr im = dynamic_pointer_cast (c); if (im) { ImageMagickContentDialog* d = new ImageMagickContentDialog (this, im); d->ShowModal (); d->Destroy (); + } - im->set_video_length (d->video_length() * 24); + shared_ptr ff = dynamic_pointer_cast (c); + if (ff) { + FFmpegContentDialog* d = new FFmpegContentDialog (this, ff); + d->ShowModal (); + d->Destroy (); } } @@ -1373,10 +1325,15 @@ FilmEditor::setup_content_button_sensitivity () shared_ptr selection = selected_content (); - _content_edit->Enable (selection && _generally_sensitive && dynamic_pointer_cast (selection)); + _content_properties->Enable ( + selection && _generally_sensitive && + (dynamic_pointer_cast (selection) || dynamic_pointer_cast (selection)) + ); + _content_remove->Enable (selection && _generally_sensitive); _content_earlier->Enable (selection && _generally_sensitive); _content_later->Enable (selection && _generally_sensitive); + _content_timeline->Enable (_generally_sensitive); } shared_ptr @@ -1402,13 +1359,14 @@ FilmEditor::setup_scaling_description () int lines = 0; - d << wxString::Format ( - _("Original video is %dx%d (%.2f:1)\n"), - _film->video_size().width, _film->video_size().height, - float (_film->video_size().width) / _film->video_size().height - ); - - ++lines; + if (_film->video_size().width && _film->video_size().height) { + d << wxString::Format ( + _("Original video is %dx%d (%.2f:1)\n"), + _film->video_size().width, _film->video_size().height, + float (_film->video_size().width) / _film->video_size().height + ); + ++lines; + } Crop const crop = _film->crop (); if (crop.left || crop.right || crop.top || crop.bottom) { @@ -1444,8 +1402,50 @@ FilmEditor::setup_scaling_description () } for (int i = lines; i < 4; ++i) { - d << " \n"; + d << wxT ("\n "); } _scaling_description->SetLabel (d); } + +void +FilmEditor::trim_type_changed (wxCommandEvent &) +{ + _film->set_trim_type (_trim_type->GetSelection () == 0 ? Film::CPL : Film::ENCODE); +} + +void +FilmEditor::loop_content_toggled (wxCommandEvent &) +{ + if (_loop_content->GetValue ()) { + _film->set_loop (_loop_count->GetValue ()); + } else { + _film->set_loop (1); + } + + setup_loop_sensitivity (); +} + +void +FilmEditor::loop_count_changed (wxCommandEvent &) +{ + _film->set_loop (_loop_count->GetValue ()); +} + +void +FilmEditor::setup_loop_sensitivity () +{ + _loop_count->Enable (_loop_content->GetValue ()); +} + +void +FilmEditor::content_timeline_clicked (wxCommandEvent &) +{ + if (_timeline_dialog) { + _timeline_dialog->Destroy (); + _timeline_dialog = 0; + } + + _timeline_dialog = new TimelineDialog (this, _film->playlist ()); + _timeline_dialog->Show (); +}