Hand-apply a2f81da6d9afc5d3b5e647e1e05ca5d4507af42c from master;
authorCarl Hetherington <cth@carlh.net>
Tue, 24 Mar 2015 23:30:08 +0000 (23:30 +0000)
committerCarl Hetherington <cth@carlh.net>
Tue, 24 Mar 2015 23:30:08 +0000 (23:30 +0000)
allow "deletion" of the audio part of a FFmpeg file from the
timeline; delete unmaps the audio (#316).

ChangeLog
TO_PORT
src/lib/audio_mapping.cc
src/lib/audio_mapping.h
src/wx/content_menu.cc
src/wx/content_menu.h
src/wx/content_panel.cc
src/wx/timeline.cc
src/wx/timeline.h

index c15045f366a8827d3bcad195e949fed281b2583a..b063002d9f1c3c3e372aea4736636d0b7018b810 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2015-03-24  Carl Hetherington  <cth@carlh.net>
+
+       * Hand-apply 7ba9dcdbfe8f0d94ad9887843995c152c45dfe9e from master;
+       allow "deletion" of the audio part of a FFmpeg file from the
+       timeline; delete unmaps the audio (#316).
+
 2015-02-25  Carl Hetherington  <cth@carlh.net>
 
        * Version 2.0.41 released.
diff --git a/TO_PORT b/TO_PORT
index 3f4a200b425b93e2e146cbdbe3c1570ef9a67e56..8e85ad774300b070229a42dbba37da38bf942b28 100644 (file)
--- a/TO_PORT
+++ b/TO_PORT
@@ -1,4 +1,3 @@
-7ba9dcdbfe8f0d94ad9887843995c152c45dfe9e
 e30fd8d
 31eafa8a121b8d341d198e4fe426ee843cc70167
 3e3d3e46a74af7b3e6431033c7c80bd058c02cf6
index 5b3e36f25046e0b7e3a1a83cf6fe29e971eefb1c..35e4c036cf6f8b6e72cf88a4b46ff34054a9628c 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-2015 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
@@ -30,6 +30,7 @@ using std::make_pair;
 using std::pair;
 using std::string;
 using std::min;
+using std::vector;
 using boost::shared_ptr;
 using boost::dynamic_pointer_cast;
 using dcp::raw_convert;
@@ -144,3 +145,35 @@ AudioMapping::digest () const
 
        return digester.get ();
 }
+
+list<dcp::Channel>
+AudioMapping::mapped_dcp_channels () const
+{
+       static float const minus_96_db = 0.000015849;
+
+       list<dcp::Channel> mapped;
+       
+       for (vector<vector<float> >::const_iterator i = _gain.begin(); i != _gain.end(); ++i) {
+               for (size_t j = 0; j < i->size(); ++j) {
+                       if (abs ((*i)[j]) > minus_96_db) {
+                               mapped.push_back ((dcp::Channel) j);
+                       }
+               }
+       }
+
+       mapped.sort ();
+       mapped.unique ();
+       
+       return mapped;
+}
+
+void
+AudioMapping::unmap_all ()
+{
+       for (vector<vector<float> >::iterator i = _gain.begin(); i != _gain.end(); ++i) {
+               for (vector<float>::iterator j = i->begin(); j != i->end(); ++j) {
+                       *j = 0;
+               }
+       }
+}
+
index fdb23df8bc3d1f039b69a2830f2c0f5e3193d067..bac2b10b0a4b77cef32ccfe6c7bf9984d38d3462 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-2015 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
@@ -65,6 +65,9 @@ public:
        }
 
        std::string digest () const;
+
+       std::list<dcp::Channel> mapped_dcp_channels () const;
+       void unmap_all ();
        
 private:
        void setup (int);
index 749337b7518674c03b35ac2451272ebd84c26e12..23767bbe75e4a20a866b93f50243b348293195a4 100644 (file)
@@ -30,6 +30,8 @@
 #include "content_menu.h"
 #include "repeat_dialog.h"
 #include "wx_util.h"
+#include "timeline_video_content_view.h"
+#include "timeline_audio_content_view.h"
 
 using std::cout;
 using std::vector;
@@ -72,10 +74,11 @@ ContentMenu::~ContentMenu ()
 }
 
 void
-ContentMenu::popup (weak_ptr<Film> f, ContentList c, wxPoint p)
+ContentMenu::popup (weak_ptr<Film> f, ContentList c, TimelineContentViewList v, wxPoint p)
 {
        _film = f;
        _content = c;
+       _views = v;
        _repeat->Enable (!_content.empty ());
 
        int n = 0;
@@ -123,6 +126,7 @@ ContentMenu::repeat ()
        d->Destroy ();
 
        _content.clear ();
+       _views.clear ();
 }
 
 void
@@ -166,9 +170,46 @@ ContentMenu::remove ()
                return;
        }
 
-       film->playlist()->remove (_content);
+       /* We are removing from the timeline if _views is not empty */
+       bool handled = false;
+       if (!_views.empty ()) {
+               /* Special case: we only remove FFmpegContent if its video view is selected;
+                  if not, and its audio view is selected, we unmap the audio.
+               */
+               for (ContentList::iterator i = _content.begin(); i != _content.end(); ++i) {
+                       shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (*i);
+                       if (!fc) {
+                               continue;
+                       }
+                       
+                       shared_ptr<TimelineVideoContentView> video;
+                       shared_ptr<TimelineAudioContentView> audio;
+
+                       for (TimelineContentViewList::iterator i = _views.begin(); i != _views.end(); ++i) {
+                               shared_ptr<TimelineVideoContentView> v = dynamic_pointer_cast<TimelineVideoContentView> (*i);
+                               shared_ptr<TimelineAudioContentView> a = dynamic_pointer_cast<TimelineAudioContentView> (*i);
+                               if (v && v->content() == fc) {
+                                       video = v;
+                               } else if (a && a->content() == fc) {
+                                       audio = a;
+                               }
+                       }
+
+                       if (!video && audio) {
+                               AudioMapping m = fc->audio_mapping ();
+                               m.unmap_all ();
+                               fc->set_audio_mapping (m);
+                               handled = true;
+                       }
+               }
+       }
+
+       if (!handled) {
+               film->playlist()->remove (_content);
+       }
 
        _content.clear ();
+       _views.clear ();
 }
 
 void
index 996091f0cf59883a548ddb6c1f508d653e939aee..5f2a7f7b6dd35c0bbdbbd5b7ca29bb38fbe602ca 100644 (file)
@@ -23,6 +23,7 @@
 #include <wx/wx.h>
 #include <boost/shared_ptr.hpp>
 #include <boost/weak_ptr.hpp>
+#include "timeline_content_view.h"
 #include "lib/types.h"
 
 class Film;
@@ -33,7 +34,7 @@ public:
        ContentMenu (wxWindow* p);
        ~ContentMenu ();
        
-       void popup (boost::weak_ptr<Film>, ContentList, wxPoint);
+       void popup (boost::weak_ptr<Film>, ContentList, TimelineContentViewList, wxPoint);
 
 private:
        void repeat ();
@@ -49,6 +50,7 @@ private:
        boost::weak_ptr<Film> _film;
        wxWindow* _parent;
        ContentList _content;
+       TimelineContentViewList _views;
        wxMenuItem* _repeat;
        wxMenuItem* _join;
        wxMenuItem* _find_missing;
index 8bcf46f5c3151e2c0a2fe3f844e76483377833bc..30c03538b05ee4512ca69229b3d0c0655acb9898 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2015 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
@@ -335,7 +335,7 @@ ContentPanel::timeline_clicked ()
 void
 ContentPanel::right_click (wxListEvent& ev)
 {
-       _menu->popup (_film, selected (), ev.GetPoint ());
+       _menu->popup (_film, selected (), TimelineContentViewList (), ev.GetPoint ());
 }
 
 /** Set up broad sensitivity based on the type of content that is selected */
index 6ed91e098e17b05b5961fb47b5056191806e526a..2c032b8d33dee556f00f43a64e696adab3c5082b 100644 (file)
@@ -93,7 +93,12 @@ void
 Timeline::playlist_changed ()
 {
        ensure_ui_thread ();
-       
+       recreate_views ();
+}
+
+void
+Timeline::recreate_views ()
+{
        shared_ptr<const Film> fl = _film.lock ();
        if (!fl) {
                return;
@@ -108,7 +113,9 @@ Timeline::playlist_changed ()
                if (dynamic_pointer_cast<VideoContent> (*i)) {
                        _views.push_back (shared_ptr<TimelineView> (new TimelineVideoContentView (*this, *i)));
                }
-               if (dynamic_pointer_cast<AudioContent> (*i)) {
+
+               shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> (*i);
+               if (ac && !ac->audio_mapping().mapped_dcp_channels().empty ()) {
                        _views.push_back (shared_ptr<TimelineView> (new TimelineAudioContentView (*this, *i)));
                }
 
@@ -132,6 +139,8 @@ Timeline::playlist_content_changed (int property)
                assign_tracks ();
                setup_pixels_per_second ();
                Refresh ();
+       } else if (property == AudioContentProperty::AUDIO_MAPPING) {
+               recreate_views ();
        }
 }
 
@@ -303,7 +312,7 @@ Timeline::right_down (wxMouseEvent& ev)
                cv->set_selected (true);
        }
 
-       _menu.popup (_film, selected_content (), ev.GetPosition ());
+       _menu.popup (_film, selected_content (), selected_views (), ev.GetPosition ());
 }
 
 void
index 66f982c4ae279b3b6767f4ca33d81e2e0324bae9..cab0ea0e08525bc36221cbf401c360ee9b750757 100644 (file)
@@ -84,6 +84,7 @@ private:
        void assign_tracks ();
        void set_position_from_event (wxMouseEvent &);
        void clear_selection ();
+       void recreate_views ();
 
        boost::shared_ptr<TimelineView> event_to_view (wxMouseEvent &);
        TimelineContentViewList selected_views () const;