Various bits.
authorCarl Hetherington <cth@carlh.net>
Mon, 1 Apr 2013 23:03:45 +0000 (00:03 +0100)
committerCarl Hetherington <cth@carlh.net>
Mon, 1 Apr 2013 23:03:45 +0000 (00:03 +0100)
21 files changed:
src/lib/content.h
src/lib/decoder.h
src/lib/encoder.h
src/lib/ffmpeg_content.cc
src/lib/ffmpeg_content.h
src/lib/ffmpeg_decoder.cc
src/lib/film.cc
src/lib/film.h
src/lib/imagemagick_content.cc
src/lib/imagemagick_content.h
src/lib/imagemagick_decoder.cc
src/lib/imagemagick_decoder.h
src/lib/playlist.cc
src/lib/playlist.h
src/lib/util.cc
src/lib/util.h
src/lib/video_content.cc
src/lib/wscript
src/wx/film_editor.cc
src/wx/film_viewer.cc
src/wx/film_viewer.h

index 3a94d229787d02b43e87f6edc0c1858158f2d5a4..87ef4658125282e8a900d391ccbc6e7708463a6f 100644 (file)
@@ -1,3 +1,22 @@
+/*
+    Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
 #ifndef DVDOMATIC_CONTENT_H
 #define DVDOMATIC_CONTENT_H
 
index 4ccdc046fcbb19f7da54e43ca0cba1fd4b5305cd..34accf6c740afdd60eb0e97a1a2e763d28a2c7e8 100644 (file)
@@ -58,8 +58,6 @@ public:
        virtual bool seek (double);
        virtual bool seek_to_last ();
 
-       boost::signals2::signal<void()> OutputChanged;
-
 protected:
        boost::shared_ptr<const Film> _film;
 
index 86880bc34942561ba12a1488feb00663c2c9d6d8..2cbd498e866f0b2db6e36ddc7cd5661ba7660c73 100644 (file)
@@ -106,7 +106,7 @@ private:
        static int const _history_size;
 
        /** Number of video frames received so far */
-       SourceFrame _video_frames_in;
+       ContentVideoFrame _video_frames_in;
        /** Number of video frames written for the DCP so far */
        int _video_frames_out;
 
index 42e04e8381e270b88bb91af7bf9fb7661103ce6c..50a69ae7b29c51e24561938b526fc3b528ddb3d2 100644 (file)
@@ -1,3 +1,22 @@
+/*
+    Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
 #include <libcxml/cxml.h>
 #include "ffmpeg_content.h"
 #include "ffmpeg_decoder.h"
index 95e24b7b3ef29e8e29e20ca63340c05ee4b4c167..c56dc0a61ecfdfb7cfe89cd854f97d1e637c2fc7 100644 (file)
@@ -1,3 +1,22 @@
+/*
+    Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
 #ifndef DVDOMATIC_FFMPEG_CONTENT_H
 #define DVDOMATIC_FFMPEG_CONTENT_H
 
index 25ca9bb8882f658385ac677f86a36c685ba5b404..ced9b95e9bcc7172f5536c6876c6bf995b8d547f 100644 (file)
@@ -592,7 +592,6 @@ FFmpegDecoder::film_changed (Film::Property p)
                boost::mutex::scoped_lock lm (_filter_graphs_mutex);
                _filter_graphs.clear ();
        }
-       OutputChanged ();
        break;
 
        default:
index fe16a65fa4faab40f3d6186fc6f35b06abf75f74..19e900784775277c1475fac5ac4232481e18cc88 100644 (file)
@@ -1043,6 +1043,62 @@ Film::add_content (shared_ptr<Content> c)
        examine_content (c);
 }
 
+void
+Film::remove_content (shared_ptr<Content> c)
+{
+       {
+               boost::mutex::scoped_lock lm (_state_mutex);
+               ContentList::iterator i = find (_content.begin(), _content.end(), c);
+               if (i != _content.end ()) {
+                       _content.erase (i);
+               }
+       }
+
+       signal_changed (CONTENT);
+}
+
+void
+Film::move_content_earlier (shared_ptr<Content> c)
+{
+       {
+               boost::mutex::scoped_lock lm (_state_mutex);
+               ContentList::iterator i = find (_content.begin(), _content.end(), c);
+               if (i == _content.begin () || i == _content.end()) {
+                       return;
+               }
+
+               ContentList::iterator j = i;
+               --j;
+
+               swap (*i, *j);
+       }
+
+       signal_changed (CONTENT);
+}
+
+void
+Film::move_content_later (shared_ptr<Content> c)
+{
+       {
+               boost::mutex::scoped_lock lm (_state_mutex);
+               ContentList::iterator i = find (_content.begin(), _content.end(), c);
+               if (i == _content.end()) {
+                       return;
+               }
+
+               ContentList::iterator j = i;
+               ++j;
+               if (j == _content.end ()) {
+                       return;
+               }
+
+               swap (*i, *j);
+       }
+
+       signal_changed (CONTENT);
+
+}
+
 ContentAudioFrame
 Film::audio_length () const
 {
index 6e097d44e86ee2402961c856d8547e48f97f1647..9682a37d767eb72086e351512569f4ed846a318a 100644 (file)
@@ -38,6 +38,7 @@ extern "C" {
 #include "dcp_content_type.h"
 #include "util.h"
 #include "dci_metadata.h"
+#include "types.h"
 
 class Format;
 class Job;
@@ -171,7 +172,7 @@ public:
                return _trust_content_headers;
        }
 
-       std::list<boost::shared_ptr<Content> > content () const {
+       ContentList content () const {
                boost::mutex::scoped_lock lm (_state_mutex);
                return _content;
        }
@@ -268,6 +269,9 @@ public:
        void set_use_dci_name (bool);
        void set_trust_content_headers (bool);
        void add_content (boost::shared_ptr<Content>);
+       void remove_content (boost::shared_ptr<Content>);
+       void move_content_earlier (boost::shared_ptr<Content>);
+       void move_content_later (boost::shared_ptr<Content>);
        void set_dcp_content_type (DCPContentType const *);
        void set_format (Format const *);
        void set_crop (Crop);
@@ -325,7 +329,6 @@ private:
        std::string _name;
        /** True if a auto-generated DCI-compliant name should be used for our DCP */
        bool _use_dci_name;
-       typedef std::list<boost::shared_ptr<Content> > ContentList;
        ContentList _content;
        bool _trust_content_headers;
        /** The type of content that this Film represents (feature, trailer etc.) */
index cb712b417fa3bb73f4b88649804ef6fe3c08a5e7..f9572b518fccf8a369b984423e855ed2e7e943a3 100644 (file)
@@ -1,5 +1,25 @@
+/*
+    Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
 #include <libcxml/cxml.h>
 #include "imagemagick_content.h"
+#include "imagemagick_decoder.h"
 #include "compose.hpp"
 
 #include "i18n.h"
@@ -11,8 +31,7 @@ ImageMagickContent::ImageMagickContent (boost::filesystem::path f)
        : Content (f)
        , VideoContent (f)
 {
-       /* XXX */
-       _video_length = 10 * 24;
+       
 }
 
 ImageMagickContent::ImageMagickContent (shared_ptr<const cxml::Node> node)
@@ -35,3 +54,26 @@ ImageMagickContent::valid_file (boost::filesystem::path f)
        transform (ext.begin(), ext.end(), ext.begin(), ::tolower);
        return (ext == ".tif" || ext == ".tiff" || ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".bmp");
 }
+
+void
+ImageMagickContent::as_xml (xmlpp::Node* node) const
+{
+       node->add_child("Type")->add_child_text ("ImageMagick");
+       Content::as_xml (node);
+       VideoContent::as_xml (node);
+}
+
+void
+ImageMagickContent::examine (shared_ptr<Film> film, shared_ptr<Job> job, bool quick)
+{
+       Content::examine (film, job, quick);
+       shared_ptr<ImageMagickDecoder> decoder (new ImageMagickDecoder (film, shared_from_this()));
+
+       {
+               boost::mutex::scoped_lock lm (_mutex);
+               /* XXX */
+               _video_length = 10 * 24;
+       }
+       
+       take_from_video_decoder (decoder);
+}
index 99b61451259d119efebaa23f3f5258097dd2b9c7..5820bd807ef5560c3b244e4fe7357a99a52790c5 100644 (file)
@@ -1,16 +1,38 @@
+/*
+    Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <boost/enable_shared_from_this.hpp>
 #include "video_content.h"
 
 namespace cxml {
        class Node;
 }
 
-class ImageMagickContent : public VideoContent
+class ImageMagickContent : public VideoContent, public boost::enable_shared_from_this<ImageMagickContent>
 {
 public:
        ImageMagickContent (boost::filesystem::path);
        ImageMagickContent (boost::shared_ptr<const cxml::Node>);
 
+       void examine (boost::shared_ptr<Film>, boost::shared_ptr<Job>, bool);
        std::string summary () const;
+       void as_xml (xmlpp::Node *) const;
 
        static bool valid_file (boost::filesystem::path);
 };
index 279c8bf3290ab36276fa7afb1627e3cfced1b3e3..508863e3e003d43350524ee46ec2b966cc1fe82a 100644 (file)
@@ -52,6 +52,12 @@ ImageMagickDecoder::native_size () const
        return s;
 }
 
+int
+ImageMagickDecoder::video_length () const
+{
+       return _imagemagick_content->video_length ();
+}
+
 bool
 ImageMagickDecoder::pass ()
 {
@@ -120,11 +126,3 @@ ImageMagickDecoder::seek (double t)
        _position = f;
        return false;
 }
-
-void
-ImageMagickDecoder::film_changed (Film::Property p)
-{
-       if (p == Film::CROP) {
-               OutputChanged ();
-       }
-}
index 7ad08df03a2e82f131ebbede586e890e00c34ba6..424cefe08ff7bacdbdf6b53fb2a945d96a64d100 100644 (file)
@@ -31,16 +31,11 @@ public:
        ImageMagickDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<const ImageMagickContent>);
 
        float frames_per_second () const {
-               /* We don't know */
-               return 0;
+               return 24;
        }
 
        libdcp::Size native_size () const;
-
-       ContentVideoFrame video_length () const {
-               /* We don't know */
-               return 0;
-       }
+       ContentVideoFrame video_length () const;
 
        int audio_channels () const {
                return 0;
@@ -80,8 +75,6 @@ protected:
        }
 
 private:
-       void film_changed (Film::Property);
-
        boost::shared_ptr<const ImageMagickContent> _imagemagick_content;
        ContentVideoFrame _position;
 };
index d9bf8ac363f0460116ede361fa7d956666cd33b6..609d4096cb739ca00c31bd7c5d745a55857a7e86 100644 (file)
@@ -27,6 +27,7 @@
 #include "imagemagick_decoder.h"
 
 using std::list;
+using std::cout;
 using boost::shared_ptr;
 using boost::dynamic_pointer_cast;
 
@@ -38,12 +39,12 @@ Playlist::Playlist ()
 }
 
 void
-Playlist::setup (list<shared_ptr<Content> > content)
+Playlist::setup (ContentList content)
 {
        _video_from = VIDEO_NONE;
        _audio_from = AUDIO_NONE;
        
-       for (list<shared_ptr<Content> >::const_iterator i = content.begin(); i != content.end(); ++i) {
+       for (ContentList::const_iterator i = content.begin(); i != content.end(); ++i) {
                shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (*i);
                if (fc) {
                        assert (!_ffmpeg);
@@ -287,11 +288,12 @@ Player::process_audio (shared_ptr<AudioBuffers> b)
        Audio (b);
 }
 
+/** @return true on error */
 bool
 Player::seek (double t)
 {
        bool r = false;
-       
+
        switch (_playlist->video_from()) {
        case Playlist::VIDEO_NONE:
                break;
@@ -301,7 +303,20 @@ Player::seek (double t)
                }
                break;
        case Playlist::VIDEO_IMAGEMAGICK:
-               if ((*_imagemagick_decoder)->seek (t)) {
+               /* Find the decoder that contains this position */
+               _imagemagick_decoder = _imagemagick_decoders.begin ();
+               while (_imagemagick_decoder != _imagemagick_decoders.end ()) {
+                       double const this_length = (*_imagemagick_decoder)->video_length() / _film->video_frame_rate ();
+                       if (this_length < t) {
+                               break;
+                       }
+                       t -= this_length;
+                       ++_imagemagick_decoder;
+               }
+
+               if (_imagemagick_decoder != _imagemagick_decoders.end()) {
+                       (*_imagemagick_decoder)->seek (t);
+               } else {
                        r = true;
                }
                break;
index 8278490490fb5f9b515bf8cd9d391a24e2e4107f..403fb58d42ead48e8af6b6df4e52a86707705393 100644 (file)
@@ -40,7 +40,7 @@ class Playlist
 public:
        Playlist ();
 
-       void setup (std::list<boost::shared_ptr<Content> >);
+       void setup (ContentList);
 
        ContentAudioFrame audio_length () const;
        int audio_channels () const;
index 1c020875abd95d5e3c7cd4f90f754d4a42375241..e0de82c64dc8a619d692e0a5817333a877ea2d4a 100644 (file)
@@ -476,16 +476,6 @@ dcp_audio_sample_rate (int fs)
        return 96000;
 }
 
-bool operator== (Crop const & a, Crop const & b)
-{
-       return (a.left == b.left && a.right == b.right && a.top == b.top && a.bottom == b.bottom);
-}
-
-bool operator!= (Crop const & a, Crop const & b)
-{
-       return !(a == b);
-}
-
 /** @param index Colour LUT index.
  *  @return Human-readable name.
  */
@@ -867,13 +857,13 @@ ensure_ui_thread ()
        assert (this_thread::get_id() == ui_thread);
 }
 
-/** @param v Source video frame.
+/** @param v Content video frame.
  *  @param audio_sample_rate Source audio sample rate.
  *  @param frames_per_second Number of video frames per second.
  *  @return Equivalent number of audio frames for `v'.
  */
 int64_t
-video_frames_to_audio_frames (SourceFrame v, float audio_sample_rate, float frames_per_second)
+video_frames_to_audio_frames (ContentVideoFrame v, float audio_sample_rate, float frames_per_second)
 {
        return ((int64_t) v * audio_sample_rate / frames_per_second);
 }
index b8c1e31161994eb6c23700efaace20c2281950bc..23ebd52bcf0ed85b8a16f7de262f6c70a9c16bf0 100644 (file)
@@ -37,6 +37,7 @@ extern "C" {
 #include <libavfilter/avfilter.h>
 }
 #include "compose.hpp"
+#include "types.h"
 
 #ifdef DVDOMATIC_DEBUG
 #define TIMING(...) _film->log()->microsecond_log (String::compose (__VA_ARGS__), Log::TIMING);
@@ -65,10 +66,6 @@ extern std::string audio_channel_name (int);
 extern boost::filesystem::path mo_path ();
 #endif
 
-typedef int SourceFrame;
-typedef int64_t ContentAudioFrame;
-typedef int ContentVideoFrame;
-
 struct FrameRateConversion
 {
        FrameRateConversion (float, int);
@@ -106,82 +103,6 @@ struct FrameRateConversion
 
 int best_dcp_frame_rate (float);
 
-/** @struct Crop
- *  @brief A description of the crop of an image or video.
- */
-struct Crop
-{
-       Crop () : left (0), right (0), top (0), bottom (0) {}
-
-       /** Number of pixels to remove from the left-hand side */
-       int left;
-       /** Number of pixels to remove from the right-hand side */
-       int right;
-       /** Number of pixels to remove from the top */
-       int top;
-       /** Number of pixels to remove from the bottom */
-       int bottom;
-};
-
-extern bool operator== (Crop const & a, Crop const & b);
-extern bool operator!= (Crop const & a, Crop const & b);
-
-/** @struct Position
- *  @brief A position.
- */
-struct Position
-{
-       Position ()
-               : x (0)
-               , y (0)
-       {}
-
-       Position (int x_, int y_)
-               : x (x_)
-               , y (y_)
-       {}
-
-       /** x coordinate */
-       int x;
-       /** y coordinate */
-       int y;
-};
-
-/** @struct Rect
- *  @brief A rectangle.
- */
-struct Rect
-{
-       Rect ()
-               : x (0)
-               , y (0)
-               , width (0)
-               , height (0)
-       {}
-
-       Rect (int x_, int y_, int w_, int h_)
-               : x (x_)
-               , y (y_)
-               , width (w_)
-               , height (h_)
-       {}
-
-       int x;
-       int y;
-       int width;
-       int height;
-
-       Position position () const {
-               return Position (x, y);
-       }
-
-       libdcp::Size size () const {
-               return libdcp::Size (width, height);
-       }
-
-       Rect intersection (Rect const & other) const;
-};
-
 extern std::string crop_string (Position, libdcp::Size);
 extern int dcp_audio_sample_rate (int);
 extern std::string colour_lut_index_to_name (int index);
@@ -286,7 +207,7 @@ private:
        int _source_channels;
 };
 
-extern int64_t video_frames_to_audio_frames (SourceFrame v, float audio_sample_rate, float frames_per_second);
+extern int64_t video_frames_to_audio_frames (ContentVideoFrame v, float audio_sample_rate, float frames_per_second);
 extern std::pair<std::string, int> cpu_info ();
 
 #endif
index 8a4414c18b1830ed558fdcb4fb1aad77b572db89..e697a281d8d30f2fc97744730a3314264f7d0b3e 100644 (file)
@@ -39,10 +39,14 @@ VideoContent::as_xml (xmlpp::Node* node) const
 void
 VideoContent::take_from_video_decoder (shared_ptr<VideoDecoder> d)
 {
+       /* These decoder calls could call other content methods which take a lock on the mutex */
+       libdcp::Size const vs = d->native_size ();
+       float const vfr = d->frames_per_second ();
+       
         {
                 boost::mutex::scoped_lock lm (_mutex);
-                _video_size = d->native_size ();
-                _video_frame_rate = d->frames_per_second ();
+                _video_size = vs;
+               _video_frame_rate = vfr;
         }
         
         Changed (VideoContentProperty::VIDEO_SIZE);
index 303a9951f104796511a8e931093c5d346ee1e8b6..f2bb678aa855f135b0ba2cb9c0d7af8c71b4dd3c 100644 (file)
@@ -49,6 +49,7 @@ sources = """
           timer.cc
           transcode_job.cc
           transcoder.cc
+          types.cc
           ui_signaller.cc
           util.cc
           version.cc
index 560c4ef27aaf1e7d37d1e76cb0d59e2071df2115..7930d86ce08800dae7baada0115d4b0c85719de7 100644 (file)
@@ -200,9 +200,9 @@ FilmEditor::connect_to_widgets ()
        _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_item_selected), 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_add_clicked), 0, this);
-       _content_earlier->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_add_clicked), 0, this);
-       _content_later->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_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);
@@ -1135,13 +1135,13 @@ FilmEditor::best_dcp_frame_rate_clicked (wxCommandEvent &)
                return;
        }
        
-//     _film->set_dcp_frame_rate (best_dcp_frame_rate (_film->source_frame_rate ()));
+       _film->set_dcp_frame_rate (best_dcp_frame_rate (_film->video_frame_rate ()));
 }
 
 void
 FilmEditor::setup_show_audio_sensitivity ()
 {
-//     _show_audio->Enable (_film && _film->has_audio ());
+       _show_audio->Enable (_film && _film->has_audio ());
 }
 
 void
@@ -1149,8 +1149,8 @@ FilmEditor::setup_content ()
 {
        _content->DeleteAllItems ();
 
-       list<shared_ptr<Content> > content = _film->content ();
-       for (list<shared_ptr<Content> >::iterator i = content.begin(); i != content.end(); ++i) {
+       ContentList content = _film->content ();
+       for (ContentList::iterator i = content.begin(); i != content.end(); ++i) {
                _content->InsertItem (_content->GetItemCount(), std_to_wx ((*i)->summary ()));
        }
 }
@@ -1181,19 +1181,40 @@ FilmEditor::content_add_clicked (wxCommandEvent &)
 void
 FilmEditor::content_remove_clicked (wxCommandEvent &)
 {
+       int const s = _content->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+       if (s == -1) {
+               return;
+       }
 
+       ContentList c = _film->content ();
+       assert (s >= 0 && size_t (s) < c.size ());
+       _film->remove_content (c[s]);
 }
 
 void
 FilmEditor::content_earlier_clicked (wxCommandEvent &)
 {
+       int const s = _content->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+       if (s == -1) {
+               return;
+       }
 
+       ContentList c = _film->content ();
+       assert (s >= 0 && size_t (s) < c.size ());
+       _film->move_content_earlier (c[s]);
 }
 
 void
 FilmEditor::content_later_clicked (wxCommandEvent &)
 {
+       int const s = _content->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+       if (s == -1) {
+               return;
+       }
 
+       ContentList c = _film->content ();
+       assert (s >= 0 && size_t (s) < c.size ());
+       _film->move_content_later (c[s]);
 }
 
 void
index 79b3d982f64b399d78a57c737a5a6d45d9d26b46..e45f79a87734f6775bab2f2427510296744f3622 100644 (file)
@@ -103,7 +103,6 @@ FilmViewer::film_changed (Film::Property p)
                _player->disable_video_sync ();
 
                _player->Video.connect (bind (&FilmViewer::process_video, this, _1, _2, _3));
-//             _player->OutputChanged.connect (boost::bind (&FilmViewer::decoder_changed, this));
                calculate_sizes ();
                get_frame ();
                _panel->Refresh ();
@@ -115,12 +114,8 @@ FilmViewer::film_changed (Film::Property p)
        case Film::SUBTITLE_SCALE:
        case Film::SCALER:
        case Film::FILTERS:
-               update_from_raw ();
-               break;
-       case Film::SUBTITLE_STREAM:
-//             if (_decoders.video) {
-//                     _decoders.video->set_subtitle_stream (_film->subtitle_stream ());
-//             }
+       case Film::CROP:
+               update_from_decoder ();
                break;
        default:
                break;
@@ -151,7 +146,7 @@ FilmViewer::set_film (shared_ptr<Film> f)
 }
 
 void
-FilmViewer::decoder_changed ()
+FilmViewer::update_from_decoder ()
 {
        if (!_player || _player->seek_to_last ()) {
                return;
@@ -223,7 +218,7 @@ FilmViewer::slider_moved (wxScrollEvent &)
        if (!_film || !_player) {
                return;
        }
-       
+
        if (_player->seek (_slider->GetValue() * _film->video_length() / (4096 * _film->video_frame_rate()))) {
                return;
        }
@@ -375,6 +370,9 @@ FilmViewer::process_video (shared_ptr<Image> image, bool, shared_ptr<Subtitle> s
        _got_frame = true;
 }
 
+/** Get a new _raw_frame from the decoder and then do
+ *  raw_to_display ().
+ */
 void
 FilmViewer::get_frame ()
 {
index 1e75045ac35c75fcb90962fafb36c5d1030d1ccf..f557d69b8f03f9f3e45e8e15274b7280bf7b316b 100644 (file)
@@ -51,7 +51,7 @@ private:
        void calculate_sizes ();
        void check_play_state ();
        void update_from_raw ();
-       void decoder_changed ();
+       void update_from_decoder ();
        void raw_to_display ();
        void get_frame ();
        void active_jobs_changed (bool);