_samples_per_point = max (int64_t (1), _film->audio_length() / _num_points);
- _current.resize (_film->audio_channels ());
- _analysis.reset (new AudioAnalysis (_film->audio_channels()));
+ _current.resize (MAX_AUDIO_CHANNELS);
+ _analysis.reset (new AudioAnalysis (MAX_AUDIO_CHANNELS));
while (!player->pass()) {
set_progress (float (_done) / _film->audio_length ());
#include "audio_mapping.h"
-using std::map;
-using boost::optional;
-
-AutomaticAudioMapping::AutomaticAudioMapping (int c)
- : _source_channels (c)
+using std::list;
+using std::cout;
+using std::make_pair;
+using std::pair;
+using boost::shared_ptr;
+
+void
+AudioMapping::add (Channel c, libdcp::Channel d)
{
-
+ _content_to_dcp.push_back (make_pair (c, d));
}
-optional<libdcp::Channel>
-AutomaticAudioMapping::source_to_dcp (int c) const
+/* XXX: this is grotty */
+int
+AudioMapping::dcp_channels () const
{
- if (c >= _source_channels) {
- return optional<libdcp::Channel> ();
+ for (list<pair<Channel, libdcp::Channel> >::const_iterator i = _content_to_dcp.begin(); i != _content_to_dcp.end(); ++i) {
+ if (((int) i->second) > 2) {
+ return 6;
+ }
}
- if (_source_channels == 1) {
- /* mono sources to centre */
- return libdcp::CENTRE;
- }
-
- return static_cast<libdcp::Channel> (c);
+ return 2;
}
-optional<int>
-AutomaticAudioMapping::dcp_to_source (libdcp::Channel c) const
+list<AudioMapping::Channel>
+AudioMapping::dcp_to_content (libdcp::Channel d) const
{
- if (_source_channels == 1) {
- if (c == libdcp::CENTRE) {
- return 0;
- } else {
- return optional<int> ();
+ list<AudioMapping::Channel> c;
+ for (list<pair<Channel, libdcp::Channel> >::const_iterator i = _content_to_dcp.begin(); i != _content_to_dcp.end(); ++i) {
+ if (i->second == d) {
+ c.push_back (i->first);
}
}
- if (static_cast<int> (c) >= _source_channels) {
- return optional<int> ();
- }
-
- return static_cast<int> (c);
+ return c;
}
-int
-AutomaticAudioMapping::dcp_channels () const
+list<AudioMapping::Channel>
+AudioMapping::content_channels () const
{
- if (_source_channels == 1) {
- /* The source is mono, so to put the mono channel into
- the centre we need to generate a 5.1 soundtrack.
- */
- return 6;
+ list<AudioMapping::Channel> c;
+ for (list<pair<Channel, 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 _source_channels;
+ return c;
}
-optional<int>
-ConfiguredAudioMapping::dcp_to_source (libdcp::Channel c) const
+list<libdcp::Channel>
+AudioMapping::content_to_dcp (Channel c) const
{
- map<int, libdcp::Channel>::const_iterator i = _source_to_dcp.begin ();
- while (i != _source_to_dcp.end() && i->second != c) {
- ++i;
- }
-
- if (i == _source_to_dcp.end ()) {
- return boost::none;
+ list<libdcp::Channel> d;
+ for (list<pair<Channel, libdcp::Channel> >::const_iterator i = _content_to_dcp.begin(); i != _content_to_dcp.end(); ++i) {
+ if (i->first == c) {
+ d.push_back (i->second);
+ }
}
- return i->first;
+ return d;
}
-optional<libdcp::Channel>
-ConfiguredAudioMapping::source_to_dcp (int c) const
+bool
+operator== (AudioMapping::Channel const & a, AudioMapping::Channel const & b)
{
- map<int, libdcp::Channel>::const_iterator i = _source_to_dcp.find (c);
- if (i == _source_to_dcp.end ()) {
- return boost::none;
- }
-
- return i->second;
+ shared_ptr<const AudioContent> sa = a.content.lock ();
+ shared_ptr<const AudioContent> sb = b.content.lock ();
+ return sa == sb && a.index == b.index;
}
+
*/
-#include <vector>
-#include <map>
-#include <boost/optional.hpp>
+#ifndef DVDOMATIC_AUDIO_MAPPING_H
+#define DVDOMATIC_AUDIO_MAPPING_H
+
+#include <list>
+#include <string>
#include <libdcp/types.h>
+#include <boost/shared_ptr.hpp>
+#include "audio_content.h"
class AudioMapping
{
public:
- virtual boost::optional<libdcp::Channel> source_to_dcp (int c) const = 0;
- virtual boost::optional<int> dcp_to_source (libdcp::Channel c) const = 0;
-};
-
-class AutomaticAudioMapping : public AudioMapping
-{
-public:
- AutomaticAudioMapping (int);
+ struct Channel {
+ Channel (boost::weak_ptr<const AudioContent> c, int i)
+ : content (c)
+ , index (i)
+ {}
+
+ boost::weak_ptr<const AudioContent> content;
+ int index;
+ };
+
+ void add (Channel, libdcp::Channel);
- boost::optional<libdcp::Channel> source_to_dcp (int c) const;
- boost::optional<int> dcp_to_source (libdcp::Channel c) const;
int dcp_channels () const;
-
-private:
- int _source_channels;
-};
+ std::list<Channel> dcp_to_content (libdcp::Channel) const;
+ std::list<std::pair<Channel, libdcp::Channel> > content_to_dcp () const {
+ return _content_to_dcp;
+ }
-class ConfiguredAudioMapping : public AudioMapping
-{
-public:
- boost::optional<libdcp::Channel> source_to_dcp (int c) const;
- boost::optional<int> dcp_to_source (libdcp::Channel c) const;
+ std::list<Channel> content_channels () const;
+ std::list<libdcp::Channel> content_to_dcp (Channel) const;
private:
- std::map<int, libdcp::Channel> _source_to_dcp;
+ std::list<std::pair<Channel, libdcp::Channel> > _content_to_dcp;
};
+
+extern bool operator== (AudioMapping::Channel const &, AudioMapping::Channel const &);
+
+#endif
void
Encoder::write_audio (shared_ptr<const AudioBuffers> data)
{
+#if 0
+ XXX
AutomaticAudioMapping m (_film->audio_channels ());
if (m.dcp_channels() != _film->audio_channels()) {
data = b;
}
+#endif
_writer->write (data);
}
signal_changed (FFmpegContentProperty::SUBTITLE_STREAM);
signal_changed (FFmpegContentProperty::AUDIO_STREAMS);
signal_changed (FFmpegContentProperty::AUDIO_STREAM);
+ signal_changed (AudioContentProperty::AUDIO_CHANNELS);
}
string
FFmpegContent::summary () const
{
- return String::compose (_("Movie: %1"), file().filename ());
+ return String::compose (_("Movie: %1"), file().filename().string());
}
string
case Film::CONTENT:
_playlist->setup (content ());
set_dcp_frame_rate (best_dcp_frame_rate (video_frame_rate ()));
+ set_audio_mapping (_playlist->default_audio_mapping ());
break;
default:
break;
}
}
+void
+Film::set_audio_mapping (AudioMapping m)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _audio_mapping = m;
+ }
+
+ signal_changed (AUDIO_MAPPING);
+}
+
void
Film::content_changed (boost::weak_ptr<Content> c, int p)
{
if (p == VideoContentProperty::VIDEO_FRAME_RATE) {
set_dcp_frame_rate (best_dcp_frame_rate (video_frame_rate ()));
- }
+ } else if (p == AudioContentProperty::AUDIO_CHANNELS) {
+ set_audio_mapping (_playlist->default_audio_mapping ());
+ }
if (ui_signaller) {
ui_signaller->emit (boost::bind (boost::ref (ContentChanged), c, p));
#include "dci_metadata.h"
#include "types.h"
#include "ffmpeg_content.h"
+#include "audio_mapping.h"
class DCPContentType;
class Format;
COLOUR_LUT,
J2K_BANDWIDTH,
DCI_METADATA,
- DCP_FRAME_RATE
+ DCP_FRAME_RATE,
+ AUDIO_MAPPING
};
return _dcp_frame_rate;
}
+ AudioMapping audio_mapping () const {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ return _audio_mapping;
+ }
+
/* SET */
void set_directory (std::string);
void set_dci_metadata (DCIMetadata);
void set_dcp_frame_rate (int);
void set_dci_date_today ();
+ void set_audio_mapping (AudioMapping);
/** Emitted when some property has of the Film has changed */
mutable boost::signals2::signal<void (Property)> Changed;
void read_metadata ();
void content_changed (boost::weak_ptr<Content>, int);
boost::shared_ptr<FFmpegContent> ffmpeg () const;
+ void setup_default_audio_mapping ();
/** Log to write to */
boost::shared_ptr<Log> _log;
int _dcp_frame_rate;
/** The date that we should use in a DCI name */
boost::gregorian::date _dci_date;
+ AudioMapping _audio_mapping;
/** true if our state has changed since we last saved it */
mutable bool _dirty;
string
ImageMagickContent::summary () const
{
- return String::compose (_("Image: %1"), file().filename ());
+ return String::compose (_("Image: %1"), file().filename().string());
}
bool
using std::list;
using std::cout;
using std::vector;
+using std::min;
using boost::shared_ptr;
using boost::weak_ptr;
using boost::dynamic_pointer_cast;
{
ContentChanged (c, p);
}
+
+AudioMapping
+Playlist::default_audio_mapping () const
+{
+ AudioMapping m;
+
+ switch (_audio_from) {
+ case AUDIO_NONE:
+ break;
+ case AUDIO_FFMPEG:
+ if (_ffmpeg->audio_channels() == 1) {
+ /* Map mono sources to centre */
+ m.add (AudioMapping::Channel (_ffmpeg, 0), libdcp::CENTRE);
+ } else {
+ int const N = min (_ffmpeg->audio_channels (), MAX_AUDIO_CHANNELS);
+ /* Otherwise just start with a 1:1 mapping */
+ for (int i = 0; i < N; ++i) {
+ m.add (AudioMapping::Channel (_ffmpeg, i), (libdcp::Channel) i);
+ }
+ }
+ break;
+
+ case AUDIO_SNDFILE:
+ {
+ int n = 0;
+ for (list<shared_ptr<const SndfileContent> >::const_iterator i = _sndfile.begin(); i != _sndfile.end(); ++i) {
+ cout << "sndfile " << (*i)->audio_channels() << "\n";
+ for (int j = 0; j < (*i)->audio_channels(); ++j) {
+ m.add (AudioMapping::Channel (*i, j), (libdcp::Channel) n);
+ ++n;
+ if (n >= MAX_AUDIO_CHANNELS) {
+ break;
+ }
+ }
+ if (n >= MAX_AUDIO_CHANNELS) {
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ return m;
+}
#include "video_sink.h"
#include "audio_sink.h"
#include "ffmpeg_content.h"
+#include "audio_mapping.h"
class Content;
class FFmpegContent;
libdcp::Size video_size () const;
ContentVideoFrame video_length () const;
+ AudioMapping default_audio_mapping () const;
+
enum VideoFrom {
VIDEO_NONE,
VIDEO_FFMPEG,
using std::string;
using std::stringstream;
+using std::cout;
using boost::shared_ptr;
using boost::lexical_cast;
SndfileContent::SndfileContent (boost::filesystem::path f)
: Content (f)
, AudioContent (f)
+ , _audio_channels (0)
+ , _audio_length (0)
+ , _audio_frame_rate (0)
{
}
string
SndfileContent::summary () const
{
- return String::compose (_("Sound file: %1"), file().filename ());
+ return String::compose (_("Sound file: %1"), file().filename().string());
}
string
node->add_child("AudioLength")->add_child_text (lexical_cast<string> (_audio_length));
node->add_child("AudioFrameRate")->add_child_text (lexical_cast<string> (_audio_frame_rate));
}
+
_picture_asset_writer = _picture_asset->start_write (_first_nonexistant_frame > 0);
- AutomaticAudioMapping m (_film->audio_channels ());
-
- if (m.dcp_channels() > 0) {
+ if (_film->audio_channels() > 0) {
_sound_asset.reset (
new libdcp::SoundAsset (
_film->dir (_film->dcp_name()),
N_("audio.mxf"),
_film->dcp_frame_rate (),
- m.dcp_channels (),
+ _film->audio_mapping().dcp_channels (),
dcp_audio_sample_rate (_film->audio_frame_rate())
)
);
#include <boost/filesystem.hpp>
#include "lib/audio_analysis.h"
#include "lib/film.h"
-#include "lib/audio_mapping.h"
#include "audio_dialog.h"
#include "audio_plot.h"
#include "wx_util.h"
_film = f;
try_to_load_analysis ();
- setup_channels ();
_plot->set_gain (_film->audio_gain ());
_film_changed_connection = _film->Changed.connect (bind (&AudioDialog::film_changed, this, _1));
SetTitle (wxString::Format (_("DVD-o-matic audio - %s"), std_to_wx(_film->name()).data()));
}
-void
-AudioDialog::setup_channels ()
-{
- if (!_film->has_audio()) {
- return;
- }
-
- AutomaticAudioMapping m (_film->audio_channels ());
-
- for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
- if (m.dcp_to_source(static_cast<libdcp::Channel>(i))) {
- _channel_checkbox[i]->Show ();
- } else {
- _channel_checkbox[i]->Hide ();
- }
- }
-}
void
AudioDialog::try_to_load_analysis ()
_plot->set_analysis (a);
- AutomaticAudioMapping m (_film->audio_channels ());
- optional<libdcp::Channel> c = m.source_to_dcp (0);
- if (c) {
- _channel_checkbox[c.get()]->SetValue (true);
- _plot->set_channel_visible (0, true);
- }
+ _channel_checkbox[0]->SetValue (true);
+ _plot->set_channel_visible (0, true);
for (int i = 0; i < AudioPoint::COUNT; ++i) {
_type_checkbox[i]->SetValue (true);
assert (c < MAX_AUDIO_CHANNELS);
- AutomaticAudioMapping m (_film->audio_channels ());
- optional<int> s = m.dcp_to_source (static_cast<libdcp::Channel> (c));
- if (s) {
- _plot->set_channel_visible (s.get(), _channel_checkbox[c]->GetValue ());
- }
+ _plot->set_channel_visible (c, _channel_checkbox[c]->GetValue ());
}
void
case Film::AUDIO_GAIN:
_plot->set_gain (_film->audio_gain ());
break;
- case Film::CONTENT:
- setup_channels ();
- break;
default:
break;
}
void type_clicked (wxCommandEvent &);
void smoothing_changed (wxScrollEvent &);
void try_to_load_analysis ();
- void setup_channels ();
boost::shared_ptr<Film> _film;
AudioPlot* _plot;
--- /dev/null
+/*
+ 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 <wx/wx.h>
+#include <wx/renderer.h>
+#include <wx/grid.h>
+#include <libdcp/types.h>
+#include "lib/audio_mapping.h"
+#include "audio_mapping_view.h"
+#include "wx_util.h"
+
+using std::cout;
+using std::list;
+using boost::shared_ptr;
+
+/* This could go away with wxWidgets 2.9, which has an API call
+ to find these values.
+*/
+
+#ifdef __WXMSW__
+#define CHECKBOX_WIDTH 16
+#define CHECKBOX_HEIGHT 16
+#endif
+
+#ifdef __WXGTK__
+#define CHECKBOX_WIDTH 20
+#define CHECKBOX_HEIGHT 20
+#endif
+
+
+class NoSelectionStringRenderer : public wxGridCellStringRenderer
+{
+public:
+ void Draw (wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, const wxRect& rect, int row, int col, bool)
+ {
+ wxGridCellStringRenderer::Draw (grid, attr, dc, rect, row, col, false);
+ }
+};
+
+class CheckBoxRenderer : public wxGridCellRenderer
+{
+public:
+
+ void Draw (wxGrid& grid, wxGridCellAttr &, wxDC& dc, const wxRect& rect, int row, int col, bool)
+ {
+ wxRendererNative::Get().DrawCheckBox (
+ &grid,
+ dc, rect,
+ grid.GetCellValue (row, col) == "1" ? static_cast<int>(wxCONTROL_CHECKED) : 0
+ );
+ }
+
+ wxSize GetBestSize (wxGrid &, wxGridCellAttr &, wxDC &, int, int)
+ {
+ return wxSize (CHECKBOX_WIDTH + 4, CHECKBOX_HEIGHT + 4);
+ }
+
+ wxGridCellRenderer* Clone () const
+ {
+ return new CheckBoxRenderer;
+ }
+};
+
+
+AudioMappingView::AudioMappingView (wxWindow* parent)
+ : wxPanel (parent, wxID_ANY)
+{
+ _grid = new wxGrid (this, wxID_ANY);
+
+ _grid->CreateGrid (0, 7);
+ _grid->HideRowLabels ();
+ _grid->DisableDragRowSize ();
+ _grid->DisableDragColSize ();
+ _grid->EnableEditing (false);
+ _grid->SetCellHighlightPenWidth (0);
+ _grid->SetDefaultRenderer (new NoSelectionStringRenderer);
+
+ _grid->SetColLabelValue (0, _("Content channel"));
+ _grid->SetColLabelValue (1, _("L"));
+ _grid->SetColLabelValue (2, _("R"));
+ _grid->SetColLabelValue (3, _("C"));
+ _grid->SetColLabelValue (4, _("Lfe"));
+ _grid->SetColLabelValue (5, _("Ls"));
+ _grid->SetColLabelValue (6, _("Rs"));
+
+ _grid->AutoSize ();
+
+ wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
+ s->Add (_grid, 1, wxEXPAND);
+ SetSizerAndFit (s);
+
+ Connect (wxID_ANY, wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler (AudioMappingView::left_click), 0, this);
+}
+
+void
+AudioMappingView::left_click (wxGridEvent& ev)
+{
+ if (ev.GetCol() == 0) {
+ return;
+ }
+
+ if (_grid->GetCellValue (ev.GetRow(), ev.GetCol()) == "1") {
+ _grid->SetCellValue (ev.GetRow(), ev.GetCol(), "0");
+ } else {
+ _grid->SetCellValue (ev.GetRow(), ev.GetCol(), "1");
+ }
+}
+
+void
+AudioMappingView::set_mapping (AudioMapping map)
+{
+ if (_grid->GetNumberRows ()) {
+ _grid->DeleteRows (0, _grid->GetNumberRows ());
+ }
+
+ list<AudioMapping::Channel> content_channels = map.content_channels ();
+ _grid->InsertRows (0, content_channels.size ());
+
+ for (size_t r = 0; r < content_channels.size(); ++r) {
+ for (int c = 1; c < 7; ++c) {
+ _grid->SetCellRenderer (r, c, new CheckBoxRenderer);
+ }
+ }
+
+ int n = 0;
+ for (list<AudioMapping::Channel>::iterator i = content_channels.begin(); i != content_channels.end(); ++i) {
+ shared_ptr<const AudioContent> ac = i->content.lock ();
+ assert (ac);
+ _grid->SetCellValue (n, 0, wxString::Format ("%s %d", std_to_wx (ac->file().filename().string()), i->index + 1));
+
+ list<libdcp::Channel> const d = map.content_to_dcp (*i);
+ for (list<libdcp::Channel>::const_iterator j = d.begin(); j != d.end(); ++j) {
+ _grid->SetCellValue (n, static_cast<int> (*j) + 1, "1");
+ }
+ ++n;
+ }
+
+ _grid->AutoSize ();
+}
+
--- /dev/null
+/*
+ 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/signals2.hpp>
+#include <wx/wx.h>
+#include <wx/grid.h>
+
+class AudioMappingView : public wxPanel
+{
+public:
+ AudioMappingView (wxWindow *);
+
+ void set_mapping (AudioMapping);
+
+private:
+ void left_click (wxGridEvent &);
+
+ wxGrid* _grid;
+};
#include "scaler.h"
#include "audio_dialog.h"
#include "imagemagick_content_dialog.h"
-#include "sndfile_content_dialog.h"
+#include "audio_mapping_view.h"
using std::string;
using std::cout;
_edit_dci_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::edit_dci_button_clicked), 0, this);
_format->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::format_changed), 0, this);
_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->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler (FilmEditor::content_selection_changed), 0, this);
+ _content->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler (FilmEditor::content_selection_changed), 0, this);
+ _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);
grid->Add (s, 1, wxEXPAND);
}
+ _audio_mapping = new AudioMappingView (_audio_panel);
+ _audio_sizer->Add (_audio_mapping, 1, wxEXPAND | wxALL, 6);
+
_audio_gain->SetRange (-60, 60);
_audio_delay->SetRange (-1000, 1000);
}
_frame_rate_description->SetLabel (wxT (""));
_best_dcp_frame_rate->Disable ();
}
+ break;
+ case Film::AUDIO_MAPPING:
+ _audio_mapping->set_mapping (_film->audio_mapping ());
+ break;
}
}
film_changed (Film::J2K_BANDWIDTH);
film_changed (Film::DCI_METADATA);
film_changed (Film::DCP_FRAME_RATE);
+ film_changed (Film::AUDIO_MAPPING);
film_content_changed (boost::shared_ptr<Content> (), FFmpegContentProperty::SUBTITLE_STREAMS);
film_content_changed (boost::shared_ptr<Content> (), FFmpegContentProperty::SUBTITLE_STREAM);
}
}
+void
+FilmEditor::content_activated (wxListEvent& ev)
+{
+ ContentList c = _film->content ();
+ assert (ev.GetIndex() >= 0 && size_t (ev.GetIndex()) < c.size ());
+
+ edit_content (c[ev.GetIndex()]);
+}
+
void
FilmEditor::content_edit_clicked (wxCommandEvent &)
{
return;
}
+ edit_content (c);
+}
+
+void
+FilmEditor::edit_content (shared_ptr<Content> c)
+{
shared_ptr<ImageMagickContent> im = dynamic_pointer_cast<ImageMagickContent> (c);
if (im) {
ImageMagickContentDialog* d = new ImageMagickContentDialog (this, im);
- int const r = d->ShowModal ();
- d->Destroy ();
-
- if (r == wxID_OK) {
- im->set_video_length (d->video_length() * 24);
- }
- }
-
- shared_ptr<SndfileContent> sf = dynamic_pointer_cast<SndfileContent> (c);
- if (sf) {
- SndfileContentDialog* d = new SndfileContentDialog (this, sf);
d->ShowModal ();
d->Destroy ();
+
+ im->set_video_length (d->video_length() * 24);
}
}
}
void
-FilmEditor::content_item_selected (wxListEvent &)
+FilmEditor::content_selection_changed (wxListEvent &)
{
setup_content_button_sensitivity ();
setup_content_information ();
{
_content_add->Enable (_generally_sensitive);
- bool const have_selection = _content->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1;
- _content_edit->Enable (have_selection && _generally_sensitive);
- _content_remove->Enable (have_selection && _generally_sensitive);
- _content_earlier->Enable (have_selection && _generally_sensitive);
- _content_later->Enable (have_selection && _generally_sensitive);
+ shared_ptr<Content> selection = selected_content ();
+
+ _content_edit->Enable (selection && _generally_sensitive && dynamic_pointer_cast<ImageMagickContent> (selection));
+ _content_remove->Enable (selection && _generally_sensitive);
+ _content_earlier->Enable (selection && _generally_sensitive);
+ _content_later->Enable (selection && _generally_sensitive);
}
shared_ptr<Content>
class wxListEvent;
class Film;
class AudioDialog;
+class AudioMappingView;
/** @class FilmEditor
* @brief A wx widget to edit a film's metadata, and perform various functions.
void top_crop_changed (wxCommandEvent &);
void bottom_crop_changed (wxCommandEvent &);
void trust_content_headers_changed (wxCommandEvent &);
- void content_item_selected (wxListEvent &);
+ void content_selection_changed (wxListEvent &);
+ void content_activated (wxListEvent &);
void content_add_clicked (wxCommandEvent &);
void content_remove_clicked (wxCommandEvent &);
void content_edit_clicked (wxCommandEvent &);
void active_jobs_changed (bool);
boost::shared_ptr<Content> selected_content ();
+ void edit_content (boost::shared_ptr<Content>);
wxNotebook* _notebook;
wxPanel* _film_panel;
wxButton* _show_audio;
wxSpinCtrl* _audio_delay;
wxChoice* _ffmpeg_audio_stream;
+ AudioMappingView* _audio_mapping;
wxCheckBox* _with_subtitles;
wxChoice* _ffmpeg_subtitle_stream;
wxSpinCtrl* _subtitle_offset;
+++ /dev/null
-/*
- 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 "lib/util.h"
-#include "lib/sndfile_content.h"
-#include "sndfile_content_dialog.h"
-#include "wx_util.h"
-
-using boost::shared_ptr;
-
-SndfileContentDialog::SndfileContentDialog (wxWindow* parent, shared_ptr<SndfileContent> content)
- : wxDialog (parent, wxID_ANY, _("Sound file"))
-{
- wxFlexGridSizer* grid = new wxFlexGridSizer (7, 6, 0);
-
- add_label_to_sizer (grid, this, wxT (""));
- add_label_to_sizer (grid, this, _("L"));
- add_label_to_sizer (grid, this, _("R"));
- add_label_to_sizer (grid, this, _("C"));
- add_label_to_sizer (grid, this, _("Lfe"));
- add_label_to_sizer (grid, this, _("Ls"));
- add_label_to_sizer (grid, this, _("Rs"));
-
- _buttons.resize (content->audio_channels ());
- for (int i = 0; i < content->audio_channels(); ++i) {
-
- if (content->audio_channels() == 1) {
- add_label_to_sizer (grid, this, _("Source"));
- } else {
- add_label_to_sizer (grid, this, wxString::Format (_("Source %d"), i + 1));
- }
-
- for (int j = 0; j < MAX_AUDIO_CHANNELS; ++j) {
- wxRadioButton* b = new wxRadioButton (this, wxID_ANY, wxT (""), wxDefaultPosition, wxDefaultSize, j ? 0 : wxRB_GROUP);
- _buttons[i].push_back (b);
- grid->Add (b, wxSHRINK);
- }
- }
-
- wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL);
- overall_sizer->Add (grid, 1, wxEXPAND | wxALL, 6);
-
- wxSizer* buttons = CreateSeparatedButtonSizer (wxOK);
- if (buttons) {
- overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
- }
-
- SetSizer (overall_sizer);
- overall_sizer->Layout ();
- overall_sizer->SetSizeHints (this);
-}
+++ /dev/null
-/*
- 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 <vector>
-#include <boost/shared_ptr.hpp>
-#include <wx/wx.h>
-#include "lib/audio_mapping.h"
-
-class SndfileContent;
-
-class SndfileContentDialog : public wxDialog
-{
-public:
- SndfileContentDialog (wxWindow *, boost::shared_ptr<SndfileContent>);
-
- ConfiguredAudioMapping audio_mapping () const;
-
-private:
- std::vector<std::vector<wxRadioButton *> > _buttons;
-};
sources = """
audio_dialog.cc
+ audio_mapping_view.cc
audio_plot.cc
config_dialog.cc
dci_metadata_dialog.cc
new_film_dialog.cc
properties_dialog.cc
server_dialog.cc
- sndfile_content_dialog.cc
wx_util.cc
wx_ui_signaller.cc
"""