Fix up AudioMapping confusions with respect to number of content channels.
authorCarl Hetherington <cth@carlh.net>
Tue, 16 Jul 2013 22:09:34 +0000 (23:09 +0100)
committerCarl Hetherington <cth@carlh.net>
Tue, 16 Jul 2013 22:09:34 +0000 (23:09 +0100)
src/lib/audio_mapping.cc
src/lib/audio_mapping.h
src/lib/ffmpeg_content.cc
src/lib/ffmpeg_content.h
src/lib/sndfile_content.cc
src/wx/audio_mapping_view.cc

index 4630f17c16eeb9058c93384389a061531a9e2e9e..7a5da7d2a4571445fd8d253393d7043d2f89a790 100644 (file)
@@ -32,6 +32,7 @@ using boost::lexical_cast;
 using boost::dynamic_pointer_cast;
 
 AudioMapping::AudioMapping ()
+       : _content_channels (0)
 {
 
 }
@@ -40,13 +41,20 @@ AudioMapping::AudioMapping ()
  *  @param c Number of channels.
  */
 AudioMapping::AudioMapping (int c)
+       : _content_channels (c)
 {
-       if (c == 1) {
+
+}
+
+void
+AudioMapping::make_default ()
+{
+       if (_content_channels == 1) {
                /* Mono -> Centre */
                add (0, libdcp::CENTRE);
        } else {
                /* 1:1 mapping */
-               for (int i = 0; i < c; ++i) {
+               for (int i = 0; i < _content_channels; ++i) {
                        add (i, static_cast<libdcp::Channel> (i));
                }
        }
@@ -54,6 +62,8 @@ AudioMapping::AudioMapping (int c)
 
 AudioMapping::AudioMapping (shared_ptr<const cxml::Node> node)
 {
+       _content_channels = node->number_child<int> ("ContentChannels");
+       
        list<shared_ptr<cxml::Node> > const c = node->node_children ("Map");
        for (list<shared_ptr<cxml::Node> >::const_iterator i = c.begin(); i != c.end(); ++i) {
                add ((*i)->number_child<int> ("ContentIndex"), static_cast<libdcp::Channel> ((*i)->number_child<int> ("DCP")));
@@ -79,22 +89,11 @@ AudioMapping::dcp_to_content (libdcp::Channel d) const
        return c;
 }
 
-list<int>
-AudioMapping::content_channels () const
-{
-       list<int> c;
-       for (list<pair<int, libdcp::Channel> >::const_iterator i = _content_to_dcp.begin(); i != _content_to_dcp.end(); ++i) {
-               if (find (c.begin(), c.end(), i->first) == c.end ()) {
-                       c.push_back (i->first);
-               }
-       }
-
-       return c;
-}
-
 list<libdcp::Channel>
 AudioMapping::content_to_dcp (int c) const
 {
+       assert (c < _content_channels);
+       
        list<libdcp::Channel> d;
        for (list<pair<int, libdcp::Channel> >::const_iterator i = _content_to_dcp.begin(); i != _content_to_dcp.end(); ++i) {
                if (i->first == c) {
@@ -108,6 +107,8 @@ AudioMapping::content_to_dcp (int c) const
 void
 AudioMapping::as_xml (xmlpp::Node* node) const
 {
+       node->add_child ("ContentChannels")->add_child_text (lexical_cast<string> (_content_channels));
+       
        for (list<pair<int, libdcp::Channel> >::const_iterator i = _content_to_dcp.begin(); i != _content_to_dcp.end(); ++i) {
                xmlpp::Node* t = node->add_child ("Map");
                t->add_child ("ContentIndex")->add_child_text (lexical_cast<string> (i->first));
index ed2c3f28d28517eb9aaeb4a13c1380c84a85cf64..9a507b550e958a8d0928adf2f1a9733eb79db708 100644 (file)
@@ -32,6 +32,11 @@ namespace cxml {
        class Node;
 }
 
+/** A many-to-many mapping from some content channels to DCP channels.
+ *  The number of content channels is set on construction and fixed,
+ *  and then each of those content channels can be mapped to zero or
+ *  more DCP channels.
+ */
 class AudioMapping
 {
 public:
@@ -44,16 +49,21 @@ public:
        void as_xml (xmlpp::Node *) const;
 
        void add (int, libdcp::Channel);
+       void make_default ();
 
        std::list<int> dcp_to_content (libdcp::Channel) const;
        std::list<std::pair<int, libdcp::Channel> > content_to_dcp () const {
                return _content_to_dcp;
        }
 
-       std::list<int> content_channels () const;
+       int content_channels () const {
+               return _content_channels;
+       }
+       
        std::list<libdcp::Channel> content_to_dcp (int) const;
 
 private:
+       int _content_channels;
        std::list<std::pair<int, libdcp::Channel> > _content_to_dcp;
 };
 
index 4c9b1d1662d8eee0bf96abf2aac5adf0adb56fa3..ebad8c8bdccb48d33d23d5556474c685e3d155fa 100644 (file)
@@ -281,12 +281,12 @@ operator== (FFmpegAudioStream const & a, FFmpegAudioStream const & b)
 }
 
 FFmpegAudioStream::FFmpegAudioStream (shared_ptr<const cxml::Node> node)
+       : mapping (node->node_child ("Mapping"))
 {
        name = node->string_child ("Name");
        id = node->number_child<int> ("Id");
        frame_rate = node->number_child<int> ("FrameRate");
        channels = node->number_child<int64_t> ("Channels");
-       mapping = AudioMapping (node->node_child ("Mapping"));
        first_audio = node->optional_number_child<double> ("FirstAudio");
 }
 
index bf550942a952e983878931090f84ad22acb0c0f7..1af586a715b4e9194926d36d39fdcd865eefabe2 100644 (file)
@@ -24,6 +24,7 @@
 #include "video_content.h"
 #include "audio_content.h"
 #include "subtitle_content.h"
+#include "audio_mapping.h"
 
 class Filter;
 class ffmpeg_pts_offset_test;
@@ -37,7 +38,9 @@ public:
                , frame_rate (f)
                , channels (c)
                , mapping (c)
-       {}
+       {
+               mapping.make_default ();
+       }
 
        FFmpegAudioStream (boost::shared_ptr<const cxml::Node>);
 
@@ -52,8 +55,11 @@ public:
 
 private:
        friend class ffmpeg_pts_offset_test;
+
        /* Constructor for tests */
-       FFmpegAudioStream () {}
+       FFmpegAudioStream ()
+               : mapping (1)
+       {}
 };
 
 extern bool operator== (FFmpegAudioStream const & a, FFmpegAudioStream const & b);
index 2dd7d8f67648b5b97a067cb9ea17484aa64d3614..7e6d56a9e4c5eda1c91d94d6eea341f725bcdc31 100644 (file)
@@ -44,11 +44,11 @@ SndfileContent::SndfileContent (shared_ptr<const Film> f, boost::filesystem::pat
 SndfileContent::SndfileContent (shared_ptr<const Film> f, shared_ptr<const cxml::Node> node)
        : Content (f, node)
        , AudioContent (f, node)
+       , _audio_mapping (node->node_child ("AudioMapping"))
 {
        _audio_channels = node->number_child<int> ("AudioChannels");
        _audio_length = node->number_child<AudioContent::Frame> ("AudioLength");
        _audio_frame_rate = node->number_child<int> ("AudioFrameRate");
-       _audio_mapping = AudioMapping (node->node_child ("AudioMapping"));
 }
 
 string
@@ -109,6 +109,7 @@ SndfileContent::examine (shared_ptr<Job> job)
 
        /* XXX: do this in signal_changed...? */
        _audio_mapping = AudioMapping (_audio_channels);
+       _audio_mapping.make_default ();
        signal_changed (AudioContentProperty::AUDIO_MAPPING);
 }
 
index 5f0f74d23e17cdbf71d211a03490046c301124ce..45d11cf80bf635c49ef72467b41eff2e467c17ce 100644 (file)
@@ -22,6 +22,7 @@
 #include <wx/grid.h>
 #include <libdcp/types.h>
 #include "lib/audio_mapping.h"
+#include "lib/util.h"
 #include "audio_mapping_view.h"
 #include "wx_util.h"
 
@@ -108,12 +109,16 @@ AudioMappingView::left_click (wxGridEvent& ev)
        }
        
        if (_grid->GetCellValue (ev.GetRow(), ev.GetCol()) == wxT("1")) {
+               cout << "set " << ev.GetRow() << " " << ev.GetCol() << " to 0.\n";
                _grid->SetCellValue (ev.GetRow(), ev.GetCol(), wxT("0"));
        } else {
+               cout << "set " << ev.GetRow() << " " << ev.GetCol() << " to 1.\n";
                _grid->SetCellValue (ev.GetRow(), ev.GetCol(), wxT("1"));
        }
 
-       _map = AudioMapping ();
+       _map = AudioMapping (_map.content_channels ());
+       cout << "was: " << _map.dcp_to_content(libdcp::CENTRE).size() << "\n";
+       
        for (int i = 0; i < _grid->GetNumberRows(); ++i) {
                for (int j = 1; j < _grid->GetNumberCols(); ++j) {
                        if (_grid->GetCellValue (i, j) == wxT ("1")) {
@@ -122,6 +127,7 @@ AudioMappingView::left_click (wxGridEvent& ev)
                }
        }
 
+       cout << "changed: " << _map.dcp_to_content(libdcp::CENTRE).size() << "\n";
        Changed (_map);
 }
 
@@ -134,27 +140,24 @@ AudioMappingView::set (AudioMapping map)
                _grid->DeleteRows (0, _grid->GetNumberRows ());
        }
 
-       list<int> content_channels = _map.content_channels ();
-       _grid->InsertRows (0, content_channels.size ());
+       _grid->InsertRows (0, _map.content_channels ());
 
-       for (size_t r = 0; r < content_channels.size(); ++r) {
+       for (int r = 0; r < _map.content_channels(); ++r) {
                for (int c = 1; c < 7; ++c) {
                        _grid->SetCellRenderer (r, c, new CheckBoxRenderer);
                }
        }
        
-       int n = 0;
-       for (list<int>::iterator i = content_channels.begin(); i != content_channels.end(); ++i) {
-               _grid->SetCellValue (n, 0, wxString::Format (wxT("%d"), *i + 1));
+       for (int i = 0; i < _map.content_channels(); ++i) {
+               _grid->SetCellValue (i, 0, wxString::Format (wxT("%d"), i + 1));
 
-               list<libdcp::Channel> const d = _map.content_to_dcp (*i);
+               list<libdcp::Channel> const d = _map.content_to_dcp (i);
                for (list<libdcp::Channel>::const_iterator j = d.begin(); j != d.end(); ++j) {
                        int const c = static_cast<int>(*j) + 1;
                        if (c < _grid->GetNumberCols ()) {
-                               _grid->SetCellValue (n, c, wxT("1"));
+                               _grid->SetCellValue (i, c, wxT("1"));
                        }
                }
-               ++n;
        }
 }