#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;
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;
: wxPanel (parent)
, _generally_sensitive (true)
, _audio_dialog (0)
+ , _timeline_dialog (0)
{
wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
_notebook = new wxNotebook (this, wxID_ANY);
make_subtitle_panel ();
_notebook->AddPage (_subtitle_panel, _("Subtitles"), false);
+ setup_formats ();
+
set_film (f);
connect_to_widgets ();
bind (&FilmEditor::active_jobs_changed, this, _1)
);
- setup_formats ();
-
SetSizerAndFit (s);
}
_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_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);
_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);
_audio_gain_calculate_button->Connect (
wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::audio_gain_calculate_button_clicked), 0, this
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
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);
_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);
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 ());
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<string> (_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 {
}
setup_frame_rate_description ();
break;
+ }
case Film::AUDIO_MAPPING:
_audio_mapping->set_mapping (_film->audio_mapping ());
break;
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<Content> 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<string> (_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<string> (_film->ffmpeg_subtitle_stream()->id));
- }
}
}
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);
}
}
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);
film_content_changed (boost::shared_ptr<Content> (), FFmpegContentProperty::SUBTITLE_STREAM);
film_content_changed (boost::shared_ptr<Content> (), FFmpegContentProperty::AUDIO_STREAMS);
film_content_changed (boost::shared_ptr<Content> (), FFmpegContentProperty::AUDIO_STREAM);
+
+ setup_content_information ();
}
/** Updates the sensitivity of lots of widgets to a given value.
_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);
{
bool h = false;
if (_generally_sensitive && _film) {
- h = !_film->ffmpeg_subtitle_streams().empty();
+ h = _film->has_subtitles ();
}
_with_subtitles->Enable (h);
j = _film->with_subtitles ();
}
- _ffmpeg_subtitle_stream->Enable (j);
_subtitle_offset->Enable (j);
_subtitle_scale->Enable (j);
}
d->Destroy ();
}
-void
-FilmEditor::setup_streams ()
-{
- if (!_film) {
- return;
- }
-
- _ffmpeg_audio_stream->Clear ();
- vector<FFmpegAudioStream> a = _film->ffmpeg_audio_streams ();
- for (vector<FFmpegAudioStream>::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<string> (i->id))));
- }
-
- if (_film->ffmpeg_audio_stream()) {
- checked_set (_ffmpeg_audio_stream, boost::lexical_cast<string> (_film->ffmpeg_audio_stream()->id));
- }
-
- _ffmpeg_subtitle_stream->Clear ();
- vector<FFmpegSubtitleStream> s = _film->ffmpeg_subtitle_streams ();
- for (vector<FFmpegSubtitleStream>::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<string> (i->id))));
- }
-
- if (_film->ffmpeg_subtitle_stream()) {
- checked_set (_ffmpeg_subtitle_stream, boost::lexical_cast<string> (_film->ffmpeg_subtitle_stream()->id));
- } else {
- _ffmpeg_subtitle_stream->SetSelection (wxNOT_FOUND);
- }
-}
-
-void
-FilmEditor::ffmpeg_audio_stream_changed (wxCommandEvent &)
-{
- if (!_film) {
- return;
- }
-
- vector<FFmpegAudioStream> a = _film->ffmpeg_audio_streams ();
- vector<FFmpegAudioStream>::iterator i = a.begin ();
- string const s = string_client_data (_ffmpeg_audio_stream->GetClientObject (_ffmpeg_audio_stream->GetSelection ()));
- while (i != a.end() && lexical_cast<string> (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<FFmpegSubtitleStream> a = _film->ffmpeg_subtitle_streams ();
- vector<FFmpegSubtitleStream>::iterator i = a.begin ();
- string const s = string_client_data (_ffmpeg_subtitle_stream->GetClientObject (_ffmpeg_subtitle_stream->GetSelection ()));
- while (i != a.end() && lexical_cast<string> (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() << wxT (" ") << _("channels");
- }
- s << wxT (", ") << _film->audio_frame_rate() << _("Hz");
- _audio->SetLabel (s);
- }
-
- setup_notebook_size ();
-}
-
void
FilmEditor::active_jobs_changed (bool a)
{
/* 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 ();
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<ImageMagickContent> (new ImageMagickContent (p)));
- } else if (SndfileContent::valid_file (p)) {
- _film->add_content (shared_ptr<SndfileContent> (new SndfileContent (p)));
- } else {
- _film->add_content (shared_ptr<FFmpegContent> (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<ImageMagickContent> (new ImageMagickContent (p)));
+ } else if (SndfileContent::valid_file (p)) {
+ _film->add_content (shared_ptr<SndfileContent> (new SndfileContent (p)));
+ } else {
+ _film->add_content (shared_ptr<FFmpegContent> (new FFmpegContent (p)));
+ }
}
-
}
void
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<Content> c = selected_content ();
if (!c) {
return;
}
- edit_content (c);
+ content_properties (c);
}
void
-FilmEditor::edit_content (shared_ptr<Content> c)
+FilmEditor::content_properties (shared_ptr<Content> c)
{
shared_ptr<ImageMagickContent> im = dynamic_pointer_cast<ImageMagickContent> (c);
if (im) {
ImageMagickContentDialog* d = new ImageMagickContentDialog (this, im);
d->ShowModal ();
d->Destroy ();
+ }
- im->set_video_length (d->video_length() * 24);
+ shared_ptr<FFmpegContent> ff = dynamic_pointer_cast<FFmpegContent> (c);
+ if (ff) {
+ FFmpegContentDialog* d = new FFmpegContentDialog (this, ff);
+ d->ShowModal ();
+ d->Destroy ();
}
}
shared_ptr<Content> selection = selected_content ();
- _content_edit->Enable (selection && _generally_sensitive && dynamic_pointer_cast<ImageMagickContent> (selection));
+ _content_properties->Enable (
+ selection && _generally_sensitive &&
+ (dynamic_pointer_cast<ImageMagickContent> (selection) || dynamic_pointer_cast<FFmpegContent> (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<Content>
{
_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 ();
+}