/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2016 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
*/
-#include "lib/audio_content.h"
-#include "lib/subtitle_content.h"
-#include "lib/video_content.h"
-#include "lib/ffmpeg_content.h"
-#include "lib/content_factory.h"
-#include "lib/image_content.h"
-#include "lib/dcp_content.h"
-#include "lib/playlist.h"
#include "content_panel.h"
#include "wx_util.h"
#include "video_panel.h"
#include "timing_panel.h"
#include "timeline_dialog.h"
#include "image_sequence_dialog.h"
+#include "film_viewer.h"
+#include "lib/audio_content.h"
+#include "lib/subtitle_content.h"
+#include "lib/video_content.h"
+#include "lib/ffmpeg_content.h"
+#include "lib/content_factory.h"
+#include "lib/image_content.h"
+#include "lib/dcp_content.h"
+#include "lib/case_insensitive_sorter.h"
+#include "lib/playlist.h"
#include <wx/wx.h>
#include <wx/notebook.h>
#include <wx/listctrl.h>
#include <boost/filesystem.hpp>
-
-#include "lib/image_filename_sorter.cc"
+#include <boost/foreach.hpp>
+#include <iostream>
using std::list;
using std::string;
using boost::shared_ptr;
using boost::weak_ptr;
using boost::dynamic_pointer_cast;
+using boost::optional;
ContentPanel::ContentPanel (wxNotebook* n, boost::shared_ptr<Film> film, FilmViewer* viewer)
: _timeline_dialog (0)
, _parent (n)
, _film (film)
+ , _film_viewer (viewer)
, _generally_sensitive (true)
{
_panel = new wxPanel (n);
_panels.push_back (_audio_panel);
_subtitle_panel = new SubtitlePanel (this);
_panels.push_back (_subtitle_panel);
- _timing_panel = new TimingPanel (this, viewer);
+ _timing_panel = new TimingPanel (this, _film_viewer);
_panels.push_back (_timing_panel);
_content->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&ContentPanel::selection_changed, this));
VideoContentList
ContentPanel::selected_video ()
{
- ContentList c = selected ();
VideoContentList vc;
- for (ContentList::iterator i = c.begin(); i != c.end(); ++i) {
- shared_ptr<VideoContent> t = dynamic_pointer_cast<VideoContent> (*i);
+ BOOST_FOREACH (shared_ptr<Content> i, selected ()) {
+ shared_ptr<VideoContent> t = dynamic_pointer_cast<VideoContent> (i);
if (t) {
vc.push_back (t);
}
AudioContentList
ContentPanel::selected_audio ()
{
- ContentList c = selected ();
AudioContentList ac;
- for (ContentList::iterator i = c.begin(); i != c.end(); ++i) {
- shared_ptr<AudioContent> t = dynamic_pointer_cast<AudioContent> (*i);
+ BOOST_FOREACH (shared_ptr<Content> i, selected ()) {
+ shared_ptr<AudioContent> t = dynamic_pointer_cast<AudioContent> (i);
if (t) {
ac.push_back (t);
}
SubtitleContentList
ContentPanel::selected_subtitle ()
{
- ContentList c = selected ();
SubtitleContentList sc;
- for (ContentList::iterator i = c.begin(); i != c.end(); ++i) {
- shared_ptr<SubtitleContent> t = dynamic_pointer_cast<SubtitleContent> (*i);
+ BOOST_FOREACH (shared_ptr<Content> i, selected ()) {
+ shared_ptr<SubtitleContent> t = dynamic_pointer_cast<SubtitleContent> (i);
if (t) {
sc.push_back (t);
}
FFmpegContentList
ContentPanel::selected_ffmpeg ()
{
- ContentList c = selected ();
FFmpegContentList sc;
- for (ContentList::iterator i = c.begin(); i != c.end(); ++i) {
- shared_ptr<FFmpegContent> t = dynamic_pointer_cast<FFmpegContent> (*i);
+ BOOST_FOREACH (shared_ptr<Content> i, selected ()) {
+ shared_ptr<FFmpegContent> t = dynamic_pointer_cast<FFmpegContent> (i);
if (t) {
sc.push_back (t);
}
{
switch (p) {
case Film::CONTENT:
+ case Film::CONTENT_ORDER:
setup ();
break;
default:
break;
}
- for (list<ContentSubPanel*>::iterator i = _panels.begin(); i != _panels.end(); ++i) {
- (*i)->film_changed (p);
+ BOOST_FOREACH (ContentSubPanel* i, _panels) {
+ i->film_changed (p);
}
}
{
setup_sensitivity ();
- for (list<ContentSubPanel*>::iterator i = _panels.begin(); i != _panels.end(); ++i) {
- (*i)->content_selection_changed ();
+ BOOST_FOREACH (ContentSubPanel* i, _panels) {
+ i->content_selection_changed ();
+ }
+
+ optional<DCPTime> go_to;
+ BOOST_FOREACH (shared_ptr<Content> i, selected ()) {
+ if (!go_to || i->position() < go_to.get()) {
+ go_to = i->position ();
+ }
+ }
+
+ if (go_to) {
+ _film_viewer->set_position (go_to.get ());
+ }
+
+ if (_timeline_dialog) {
+ _timeline_dialog->set_selection (selected ());
}
}
/* The wxFD_CHANGE_DIR here prevents a `could not set working directory' error 123 on Windows when using
non-Latin filenames or paths.
*/
- wxFileDialog* d = new wxFileDialog (_panel, _("Choose a file or files"), wxT (""), wxT (""), wxT ("*.*"), wxFD_MULTIPLE | wxFD_CHANGE_DIR);
+ wxFileDialog* d = new wxFileDialog (
+ _panel,
+ _("Choose a file or files"),
+ wxT (""),
+ wxT (""),
+ wxT ("All files|*.*|Subtitle files|*.srt;*.xml|Audio files|*.wav;*.w64;*.flac;*.aif;*.aiff"),
+ wxFD_MULTIPLE | wxFD_CHANGE_DIR
+ );
+
int const r = d->ShowModal ();
if (r != wxID_OK) {
return;
}
- /* Guess if this is a DCP or a set of images: read the first ten filenames and if they
- are all valid image files we assume it is a set of images.
- */
-
- bool is_dcp = false;
- int read = 0;
- for (boost::filesystem::directory_iterator i(path); i != boost::filesystem::directory_iterator() && read < 10; ++i, ++read) {
- if (!boost::filesystem::is_regular_file (i->path()) || !valid_image_file (i->path())) {
- is_dcp = true;
- }
+ shared_ptr<Content> content = content_factory (_film, path);
+ if (!content) {
+ error_dialog (_parent, _("No content found in this folder."));
+ return;
}
- if (is_dcp) {
- try {
- shared_ptr<DCPContent> content (new DCPContent (_film, path));
- _film->examine_and_add_content (content);
- } catch (...) {
- error_dialog (_panel, _("Could not find a DCP nor a set of images in that folder."));
- }
- } else {
-
+ shared_ptr<ImageContent> ic = dynamic_pointer_cast<ImageContent> (content);
+ if (ic) {
ImageSequenceDialog* e = new ImageSequenceDialog (_panel);
r = e->ShowModal ();
float const frame_rate = e->frame_rate ();
return;
}
- shared_ptr<Content> content;
-
- try {
- shared_ptr<ImageContent> content (new ImageContent (_film, path));
- content->set_video_frame_rate (frame_rate);
- _film->examine_and_add_content (content);
- } catch (...) {
- error_dialog (_panel, _("Could not find any images in that folder"));
- return;
- }
+ ic->set_video_frame_rate (frame_rate);
}
+
+ _film->examine_and_add_content (content);
}
void
ContentPanel::remove_clicked ()
{
- ContentList c = selected ();
- if (c.size() == 1) {
- _film->remove_content (c.front ());
+ /* This method is also called when Delete is pressed, so check that our notebook page
+ is visible.
+ */
+ if (_parent->GetCurrentPage() != _panel) {
+ return;
+ }
+
+ BOOST_FOREACH (shared_ptr<Content> i, selected ()) {
+ _film->remove_content (i);
}
selection_changed ();
VideoContentList video_selection = selected_video ();
AudioContentList audio_selection = selected_audio ();
- _remove->Enable (selection.size() == 1 && _generally_sensitive);
+ _remove->Enable (!selection.empty() && _generally_sensitive);
_earlier->Enable (selection.size() == 1 && _generally_sensitive);
_later->Enable (selection.size() == 1 && _generally_sensitive);
_timeline->Enable (!_film->content().empty() && _generally_sensitive);
_timeline->Enable (s);
/* Set the panels in the content notebook */
- for (list<ContentSubPanel*>::iterator i = _panels.begin(); i != _panels.end(); ++i) {
- (*i)->Enable (s);
+ BOOST_FOREACH (ContentSubPanel* i, _panels) {
+ i->Enable (s);
}
}
void
ContentPanel::film_content_changed (int property)
{
- if (property == ContentProperty::PATH || property == ContentProperty::POSITION || property == DCPContentProperty::CAN_BE_PLAYED) {
+ if (property == ContentProperty::PATH || property == DCPContentProperty::CAN_BE_PLAYED) {
setup ();
}
- for (list<ContentSubPanel*>::iterator i = _panels.begin(); i != _panels.end(); ++i) {
- (*i)->film_content_changed (property);
+ BOOST_FOREACH (ContentSubPanel* i, _panels) {
+ i->film_content_changed (property);
}
}
ContentPanel::setup ()
{
ContentList content = _film->content ();
- sort (content.begin(), content.end(), ContentSorter ());
/* First, check to see if anything has changed and bail if not; this avoids
flickering on OS X.
}
vector<string> proposed;
- for (ContentList::iterator i = content.begin(); i != content.end(); ++i) {
- bool const valid = (*i)->paths_valid ();
+ BOOST_FOREACH (shared_ptr<Content> i, content) {
+ bool const valid = i->paths_valid ();
- string s = (*i)->summary ();
+ string s = i->summary ();
if (!valid) {
s = _("MISSING: ") + s;
}
_content->DeleteAllItems ();
- for (ContentList::iterator i = content.begin(); i != content.end(); ++i) {
+ BOOST_FOREACH (shared_ptr<Content> i, content) {
int const t = _content->GetItemCount ();
- bool const valid = (*i)->paths_valid ();
- shared_ptr<DCPContent> dcp = dynamic_pointer_cast<DCPContent> (*i);
+ bool const valid = i->paths_valid ();
+ shared_ptr<DCPContent> dcp = dynamic_pointer_cast<DCPContent> (i);
bool const needs_kdm = dcp && !dcp->can_be_played ();
- string s = (*i)->summary ();
+ string s = i->summary ();
if (!valid) {
s = _("MISSING: ") + s;
_content->InsertItem (t, std_to_wx (s));
- if ((*i)->summary() == selected_summary) {
+ if (i->summary() == selected_summary) {
_content->SetItemState (t, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
}
ContentPanel::add_files (list<boost::filesystem::path> paths)
{
/* It has been reported that the paths returned from e.g. wxFileDialog are not always sorted;
- I can't reproduce that, but sort them anyway.
+ I can't reproduce that, but sort them anyway. Don't use ImageFilenameSorter as a normal
+ alphabetical sort is expected here.
*/
- paths.sort (ImageFilenameSorter ());
+ paths.sort (CaseInsensitiveSorter ());
/* XXX: check for lots of files here and do something */
for (list<boost::filesystem::path>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
- shared_ptr<Content> c = content_factory (_film, *i);
- shared_ptr<ImageContent> ic = dynamic_pointer_cast<ImageContent> (c);
- if (ic) {
- ic->set_video_frame_rate (24);
- }
- _film->examine_and_add_content (c);
+ _film->examine_and_add_content (content_factory (_film, *i));
}
}