summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-04-06 14:42:08 +0100
committerCarl Hetherington <cth@carlh.net>2013-04-06 14:42:08 +0100
commit8750efb9e072cf3b42e6c3c29521c7031c0b5dfd (patch)
tree0f0dd00b0413763b678ed2388b849cfe45a88468 /src
parent1bff0990433ab0ce588acaef7c589fa623bd998b (diff)
Basics of content dialogs.
Diffstat (limited to 'src')
-rw-r--r--src/lib/audio_content.cc4
-rw-r--r--src/lib/audio_content.h8
-rw-r--r--src/lib/audio_mapping.cc103
-rw-r--r--src/lib/audio_mapping.h53
-rw-r--r--src/lib/encoder.cc3
-rw-r--r--src/lib/sndfile_content.cc84
-rw-r--r--src/lib/sndfile_content.h32
-rw-r--r--src/lib/sndfile_decoder.cc65
-rw-r--r--src/lib/sndfile_decoder.h8
-rw-r--r--src/lib/util.cc52
-rw-r--r--src/lib/util.h13
-rw-r--r--src/lib/writer.cc3
-rw-r--r--src/lib/wscript1
-rw-r--r--src/wx/audio_dialog.cc7
-rw-r--r--src/wx/film_editor.cc79
-rw-r--r--src/wx/film_editor.h5
-rw-r--r--src/wx/imagemagick_content_dialog.cc62
-rw-r--r--src/wx/imagemagick_content_dialog.h34
-rw-r--r--src/wx/sndfile_content_dialog.cc67
-rw-r--r--src/wx/sndfile_content_dialog.h36
-rw-r--r--src/wx/wscript2
21 files changed, 536 insertions, 185 deletions
diff --git a/src/lib/audio_content.cc b/src/lib/audio_content.cc
index 8ca1e83c9..9968f4725 100644
--- a/src/lib/audio_content.cc
+++ b/src/lib/audio_content.cc
@@ -22,6 +22,10 @@
using boost::shared_ptr;
+int const AudioContentProperty::AUDIO_CHANNELS = 200;
+int const AudioContentProperty::AUDIO_LENGTH = 201;
+int const AudioContentProperty::AUDIO_FRAME_RATE = 202;
+
AudioContent::AudioContent (boost::filesystem::path f)
: Content (f)
{
diff --git a/src/lib/audio_content.h b/src/lib/audio_content.h
index 2bfc20656..d5dbf266b 100644
--- a/src/lib/audio_content.h
+++ b/src/lib/audio_content.h
@@ -27,6 +27,14 @@ namespace cxml {
class Node;
}
+class AudioContentProperty
+{
+public:
+ static int const AUDIO_CHANNELS;
+ static int const AUDIO_LENGTH;
+ static int const AUDIO_FRAME_RATE;
+};
+
class AudioContent : public virtual Content
{
public:
diff --git a/src/lib/audio_mapping.cc b/src/lib/audio_mapping.cc
new file mode 100644
index 000000000..3fc423e10
--- /dev/null
+++ b/src/lib/audio_mapping.cc
@@ -0,0 +1,103 @@
+/*
+ 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 "audio_mapping.h"
+
+using std::map;
+using boost::optional;
+
+AutomaticAudioMapping::AutomaticAudioMapping (int c)
+ : _source_channels (c)
+{
+
+}
+
+optional<libdcp::Channel>
+AutomaticAudioMapping::source_to_dcp (int c) const
+{
+ if (c >= _source_channels) {
+ return optional<libdcp::Channel> ();
+ }
+
+ if (_source_channels == 1) {
+ /* mono sources to centre */
+ return libdcp::CENTRE;
+ }
+
+ return static_cast<libdcp::Channel> (c);
+}
+
+optional<int>
+AutomaticAudioMapping::dcp_to_source (libdcp::Channel c) const
+{
+ if (_source_channels == 1) {
+ if (c == libdcp::CENTRE) {
+ return 0;
+ } else {
+ return optional<int> ();
+ }
+ }
+
+ if (static_cast<int> (c) >= _source_channels) {
+ return optional<int> ();
+ }
+
+ return static_cast<int> (c);
+}
+
+int
+AutomaticAudioMapping::dcp_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;
+ }
+
+ return _source_channels;
+}
+
+optional<int>
+ConfiguredAudioMapping::dcp_to_source (libdcp::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;
+ }
+
+ return i->first;
+}
+
+optional<libdcp::Channel>
+ConfiguredAudioMapping::source_to_dcp (int c) const
+{
+ map<int, libdcp::Channel>::const_iterator i = _source_to_dcp.find (c);
+ if (i == _source_to_dcp.end ()) {
+ return boost::none;
+ }
+
+ return i->second;
+}
+
+
diff --git a/src/lib/audio_mapping.h b/src/lib/audio_mapping.h
new file mode 100644
index 000000000..8804bde06
--- /dev/null
+++ b/src/lib/audio_mapping.h
@@ -0,0 +1,53 @@
+/*
+ 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 <map>
+#include <boost/optional.hpp>
+#include <libdcp/types.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);
+
+ 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;
+};
+
+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;
+
+private:
+ std::map<int, libdcp::Channel> _source_to_dcp;
+};
diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc
index 568307462..a0b88e33e 100644
--- a/src/lib/encoder.cc
+++ b/src/lib/encoder.cc
@@ -38,6 +38,7 @@
#include "cross.h"
#include "writer.h"
#include "player.h"
+#include "audio_mapping.h"
#include "i18n.h"
@@ -426,7 +427,7 @@ Encoder::encoder_thread (ServerDescription* server)
void
Encoder::write_audio (shared_ptr<const AudioBuffers> data)
{
- AudioMapping m (_film->audio_channels ());
+ AutomaticAudioMapping m (_film->audio_channels ());
if (m.dcp_channels() != _film->audio_channels()) {
/* Remap (currently just for mono -> 5.1) */
diff --git a/src/lib/sndfile_content.cc b/src/lib/sndfile_content.cc
index 684405efb..ee4f21eef 100644
--- a/src/lib/sndfile_content.cc
+++ b/src/lib/sndfile_content.cc
@@ -17,13 +17,18 @@
*/
+#include <libcxml/cxml.h>
#include "sndfile_content.h"
+#include "sndfile_decoder.h"
#include "compose.hpp"
+#include "job.h"
#include "i18n.h"
using std::string;
+using std::stringstream;
using boost::shared_ptr;
+using boost::lexical_cast;
SndfileContent::SndfileContent (boost::filesystem::path f)
: Content (f)
@@ -35,9 +40,10 @@ SndfileContent::SndfileContent (boost::filesystem::path f)
SndfileContent::SndfileContent (shared_ptr<const cxml::Node> node)
: Content (node)
, AudioContent (node)
-
{
-
+ _audio_channels = node->number_child<int> ("AudioChannels");
+ _audio_length = node->number_child<ContentAudioFrame> ("AudioLength");
+ _audio_frame_rate = node->number_child<int> ("AudioFrameRate");
}
string
@@ -49,37 +55,21 @@ SndfileContent::summary () const
string
SndfileContent::information () const
{
- return "";
-}
-
-int
-SndfileContent::audio_channels () const
-{
- /* XXX */
- return 0;
-}
-
-ContentAudioFrame
-SndfileContent::audio_length () const
-{
- /* XXX */
- return 0;
-}
-
-int
-SndfileContent::audio_frame_rate () const
-{
- /* XXX */
- return 0;
-}
-
-int64_t
-SndfileContent::audio_channel_layout () const
-{
- /* XXX */
- return 0;
-}
+ if (_audio_frame_rate == 0) {
+ return "";
+ }
+
+ stringstream s;
+
+ s << String::compose (
+ _("%1 channels, %2kHz, %3 samples"),
+ audio_channels(),
+ audio_frame_rate() / 1000.0,
+ audio_length()
+ );
+ return s.str ();
+}
bool
SndfileContent::valid_file (boost::filesystem::path f)
@@ -95,3 +85,33 @@ SndfileContent::clone () const
{
return shared_ptr<Content> (new SndfileContent (*this));
}
+
+void
+SndfileContent::examine (shared_ptr<Film> film, shared_ptr<Job> job, bool quick)
+{
+ job->set_progress_unknown ();
+ Content::examine (film, job, quick);
+
+ SndfileDecoder dec (film, shared_from_this());
+
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+ _audio_channels = dec.audio_channels ();
+ _audio_length = dec.audio_length ();
+ _audio_frame_rate = dec.audio_frame_rate ();
+ }
+
+ signal_changed (AudioContentProperty::AUDIO_CHANNELS);
+ signal_changed (AudioContentProperty::AUDIO_LENGTH);
+ signal_changed (AudioContentProperty::AUDIO_FRAME_RATE);
+}
+
+void
+SndfileContent::as_xml (xmlpp::Node* node) const
+{
+ node->add_child("Type")->add_child_text ("Sndfile");
+ Content::as_xml (node);
+ node->add_child("AudioChannels")->add_child_text (lexical_cast<string> (_audio_channels));
+ 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));
+}
diff --git a/src/lib/sndfile_content.h b/src/lib/sndfile_content.h
index b696b57a5..27c5f3615 100644
--- a/src/lib/sndfile_content.h
+++ b/src/lib/sndfile_content.h
@@ -17,6 +17,9 @@
*/
+extern "C" {
+#include <libavutil/audioconvert.h>
+}
#include "audio_content.h"
namespace cxml {
@@ -33,15 +36,36 @@ public:
return boost::dynamic_pointer_cast<SndfileContent> (Content::shared_from_this ());
}
+ void examine (boost::shared_ptr<Film>, boost::shared_ptr<Job>, bool);
std::string summary () const;
std::string information () const;
+ void as_xml (xmlpp::Node *) const;
boost::shared_ptr<Content> clone () const;
/* AudioContent */
- int audio_channels () const;
- ContentAudioFrame audio_length () const;
- int audio_frame_rate () const;
- int64_t audio_channel_layout () const;
+ int audio_channels () const {
+ boost::mutex::scoped_lock lm (_mutex);
+ return _audio_channels;
+ }
+
+ ContentAudioFrame audio_length () const {
+ boost::mutex::scoped_lock lm (_mutex);
+ return _audio_length;
+ }
+
+ int audio_frame_rate () const {
+ boost::mutex::scoped_lock lm (_mutex);
+ return _audio_frame_rate;
+ }
+
+ int64_t audio_channel_layout () const {
+ return av_get_default_channel_layout (audio_channels ());
+ }
static bool valid_file (boost::filesystem::path);
+
+private:
+ int _audio_channels;
+ ContentAudioFrame _audio_length;
+ int _audio_frame_rate;
};
diff --git a/src/lib/sndfile_decoder.cc b/src/lib/sndfile_decoder.cc
index 1f97e5c41..c7311112a 100644
--- a/src/lib/sndfile_decoder.cc
+++ b/src/lib/sndfile_decoder.cc
@@ -28,59 +28,62 @@
using std::vector;
using std::string;
-using std::stringstream;
using std::min;
using std::cout;
using boost::shared_ptr;
-using boost::optional;
-
-/* XXX */
SndfileDecoder::SndfileDecoder (shared_ptr<const Film> f, shared_ptr<const SndfileContent> c)
: Decoder (f)
, AudioDecoder (f)
+ , _sndfile_content (c)
{
- sf_count_t frames;
- SNDFILE* sf = open_file (frames);
- sf_close (sf);
+ _sndfile = sf_open (_sndfile_content->file().string().c_str(), SFM_READ, &_info);
+ if (!_sndfile) {
+ throw DecodeError (_("could not open audio file for reading"));
+ }
+
+ _remaining = _info.frames;
}
-SNDFILE*
-SndfileDecoder::open_file (sf_count_t & frames)
+SndfileDecoder::~SndfileDecoder ()
{
- frames = 0;
-
- SF_INFO info;
- SNDFILE* s = sf_open (_sndfile_content->file().string().c_str(), SFM_READ, &info);
- if (!s) {
- throw DecodeError (_("could not open external audio file for reading"));
+ if (_sndfile) {
+ sf_close (_sndfile);
}
-
- frames = info.frames;
- return s;
}
bool
SndfileDecoder::pass ()
{
- sf_count_t frames;
- SNDFILE* sndfile = open_file (frames);
-
/* Do things in half second blocks as I think there may be limits
to what FFmpeg (and in particular the resampler) can cope with.
*/
sf_count_t const block = _sndfile_content->audio_frame_rate() / 2;
+ sf_count_t const this_time = min (block, _remaining);
+
+ shared_ptr<AudioBuffers> audio (new AudioBuffers (_sndfile_content->audio_channels(), this_time));
+ sf_read_float (_sndfile, audio->data(0), this_time);
+ audio->set_frames (this_time);
+ Audio (audio);
+ _remaining -= this_time;
- shared_ptr<AudioBuffers> audio (new AudioBuffers (_sndfile_content->audio_channels(), block));
- while (frames > 0) {
- sf_count_t const this_time = min (block, frames);
- sf_read_float (sndfile, audio->data(0), this_time);
- audio->set_frames (this_time);
- Audio (audio);
- frames -= this_time;
- }
+ return (_remaining == 0);
+}
- sf_close (sndfile);
+int
+SndfileDecoder::audio_channels () const
+{
+ return _info.channels;
+}
- return true;
+ContentAudioFrame
+SndfileDecoder::audio_length () const
+{
+ return _info.frames;
+}
+
+int
+SndfileDecoder::audio_frame_rate () const
+{
+ return _info.samplerate;
}
diff --git a/src/lib/sndfile_decoder.h b/src/lib/sndfile_decoder.h
index 56fc3a9f0..2900afea0 100644
--- a/src/lib/sndfile_decoder.h
+++ b/src/lib/sndfile_decoder.h
@@ -27,12 +27,20 @@ class SndfileDecoder : public AudioDecoder
{
public:
SndfileDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<const SndfileContent>);
+ ~SndfileDecoder ();
bool pass ();
+ int audio_channels () const;
+ ContentAudioFrame audio_length () const;
+ int audio_frame_rate () const;
+
private:
SNDFILE* open_file (sf_count_t &);
void close_file (SNDFILE*);
boost::shared_ptr<const SndfileContent> _sndfile_content;
+ SNDFILE* _sndfile;
+ SF_INFO _info;
+ ContentAudioFrame _remaining;
};
diff --git a/src/lib/util.cc b/src/lib/util.cc
index e0de82c64..1e60b43fc 100644
--- a/src/lib/util.cc
+++ b/src/lib/util.cc
@@ -914,58 +914,6 @@ audio_channel_name (int c)
return channels[c];
}
-AudioMapping::AudioMapping (int c)
- : _source_channels (c)
-{
-
-}
-
-optional<libdcp::Channel>
-AudioMapping::source_to_dcp (int c) const
-{
- if (c >= _source_channels) {
- return optional<libdcp::Channel> ();
- }
-
- if (_source_channels == 1) {
- /* mono sources to centre */
- return libdcp::CENTRE;
- }
-
- return static_cast<libdcp::Channel> (c);
-}
-
-optional<int>
-AudioMapping::dcp_to_source (libdcp::Channel c) const
-{
- if (_source_channels == 1) {
- if (c == libdcp::CENTRE) {
- return 0;
- } else {
- return optional<int> ();
- }
- }
-
- if (static_cast<int> (c) >= _source_channels) {
- return optional<int> ();
- }
-
- return static_cast<int> (c);
-}
-
-int
-AudioMapping::dcp_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;
- }
-
- return _source_channels;
-}
-
FrameRateConversion::FrameRateConversion (float source, int dcp)
: skip (false)
, repeat (false)
diff --git a/src/lib/util.h b/src/lib/util.h
index 23ebd52bc..1fe6212e4 100644
--- a/src/lib/util.h
+++ b/src/lib/util.h
@@ -194,19 +194,6 @@ private:
float** _data;
};
-class AudioMapping
-{
-public:
- AudioMapping (int);
-
- 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;
-};
-
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 ();
diff --git a/src/lib/writer.cc b/src/lib/writer.cc
index 5d38860e7..6df1a1f21 100644
--- a/src/lib/writer.cc
+++ b/src/lib/writer.cc
@@ -31,6 +31,7 @@
#include "dcp_video_frame.h"
#include "dcp_content_type.h"
#include "player.h"
+#include "audio_mapping.h"
#include "i18n.h"
@@ -77,7 +78,7 @@ Writer::Writer (shared_ptr<Film> f)
_picture_asset_writer = _picture_asset->start_write (_first_nonexistant_frame > 0);
- AudioMapping m (_film->audio_channels ());
+ AutomaticAudioMapping m (_film->audio_channels ());
if (m.dcp_channels() > 0) {
_sound_asset.reset (
diff --git a/src/lib/wscript b/src/lib/wscript
index 32a2cde23..896598a0e 100644
--- a/src/lib/wscript
+++ b/src/lib/wscript
@@ -8,6 +8,7 @@ sources = """
audio_analysis.cc
audio_content.cc
audio_decoder.cc
+ audio_mapping.cc
audio_source.cc
config.cc
combiner.cc
diff --git a/src/wx/audio_dialog.cc b/src/wx/audio_dialog.cc
index 1241c2e76..f53ea7c19 100644
--- a/src/wx/audio_dialog.cc
+++ b/src/wx/audio_dialog.cc
@@ -20,6 +20,7 @@
#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"
@@ -108,7 +109,7 @@ AudioDialog::setup_channels ()
return;
}
- AudioMapping m (_film->audio_channels ());
+ AutomaticAudioMapping m (_film->audio_channels ());
for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
if (m.dcp_to_source(static_cast<libdcp::Channel>(i))) {
@@ -134,7 +135,7 @@ AudioDialog::try_to_load_analysis ()
_plot->set_analysis (a);
- AudioMapping m (_film->audio_channels ());
+ AutomaticAudioMapping m (_film->audio_channels ());
optional<libdcp::Channel> c = m.source_to_dcp (0);
if (c) {
_channel_checkbox[c.get()]->SetValue (true);
@@ -157,7 +158,7 @@ AudioDialog::channel_clicked (wxCommandEvent& ev)
assert (c < MAX_AUDIO_CHANNELS);
- AudioMapping m (_film->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 ());
diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc
index 58fc077a3..6c42359fb 100644
--- a/src/wx/film_editor.cc
+++ b/src/wx/film_editor.cc
@@ -49,6 +49,8 @@
#include "dci_metadata_dialog.h"
#include "scaler.h"
#include "audio_dialog.h"
+#include "imagemagick_content_dialog.h"
+#include "sndfile_content_dialog.h"
using std::string;
using std::cout;
@@ -198,9 +200,9 @@ FilmEditor::connect_to_widgets ()
_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_remove_clicked), 0, this);
+ _content_edit->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_edit_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);
- _imagemagick_video_length->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::imagemagick_video_length_changed), 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);
@@ -343,6 +345,8 @@ FilmEditor::make_content_panel ()
b->Add (_content_add);
_content_remove = new wxButton (_content_panel, wxID_ANY, _("Remove"));
b->Add (_content_remove);
+ _content_edit = new wxButton (_content_panel, wxID_ANY, _("Edit..."));
+ b->Add (_content_edit);
_content_earlier = new wxButton (_content_panel, wxID_ANY, _("Earlier"));
b->Add (_content_earlier);
_content_later = new wxButton (_content_panel, wxID_ANY, _("Later"));
@@ -355,21 +359,6 @@ FilmEditor::make_content_panel ()
_content_information = new wxTextCtrl (_content_panel, wxID_ANY, wxT ("\n\n\n\n"), wxDefaultPosition, wxDefaultSize, wxTE_READONLY | wxTE_MULTILINE);
_content_sizer->Add (_content_information, 1, wxEXPAND | wxALL, 6);
-
- wxFlexGridSizer* grid = new wxFlexGridSizer (2, 4, 4);
- _content_sizer->Add (grid, 0, wxEXPAND | wxALL, 6);
-
- {
- add_label_to_sizer (grid, _content_panel, (_("Duration")));
- wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
- _imagemagick_video_length = new wxSpinCtrl (_content_panel);
- s->Add (_imagemagick_video_length);
- /// TRANSLATORS: this is an abbreviation for seconds, the unit of time
- add_label_to_sizer (s, _content_panel, _("s"));
- grid->Add (s);
- }
-
- _imagemagick_video_length->SetRange (1, 3600);
}
void
@@ -723,14 +712,9 @@ FilmEditor::film_content_changed (weak_ptr<Content> content, int property)
setup_show_audio_sensitivity ();
} else if (property == VideoContentProperty::VIDEO_LENGTH) {
setup_length ();
-
boost::shared_ptr<Content> c = content.lock ();
if (c && c == selected_content()) {
setup_content_information ();
- shared_ptr<ImageMagickContent> im = dynamic_pointer_cast<ImageMagickContent> (c);
- if (im) {
- checked_set (_imagemagick_video_length, im->video_length() / 24);
- }
}
} else if (property == FFmpegContentProperty::AUDIO_STREAM) {
if (_film->ffmpeg_audio_stream()) {
@@ -1259,6 +1243,33 @@ FilmEditor::content_remove_clicked (wxCommandEvent &)
}
void
+FilmEditor::content_edit_clicked (wxCommandEvent &)
+{
+ shared_ptr<Content> c = selected_content ();
+ if (!c) {
+ return;
+ }
+
+ 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 ();
+ }
+}
+
+void
FilmEditor::content_earlier_clicked (wxCommandEvent &)
{
shared_ptr<Content> c = selected_content ();
@@ -1281,15 +1292,6 @@ FilmEditor::content_item_selected (wxListEvent &)
{
setup_content_button_sensitivity ();
setup_content_information ();
-
- shared_ptr<Content> c = selected_content ();
- if (c) {
- shared_ptr<ImageMagickContent> im = dynamic_pointer_cast<ImageMagickContent> (c);
- _imagemagick_video_length->Enable (im);
- if (im) {
- checked_set (_imagemagick_video_length, im->video_length() / 24);
- }
- }
}
void
@@ -1310,27 +1312,12 @@ FilmEditor::setup_content_button_sensitivity ()
_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);
}
-void
-FilmEditor::imagemagick_video_length_changed (wxCommandEvent &)
-{
- shared_ptr<Content> c = selected_content ();
- if (!c) {
- return;
- }
-
- shared_ptr<ImageMagickContent> im = dynamic_pointer_cast<ImageMagickContent> (c);
- if (!im) {
- return;
- }
-
- im->set_video_length (_imagemagick_video_length->GetValue() * 24);
-}
-
shared_ptr<Content>
FilmEditor::selected_content ()
{
diff --git a/src/wx/film_editor.h b/src/wx/film_editor.h
index 2870714f9..b6f6a24ee 100644
--- a/src/wx/film_editor.h
+++ b/src/wx/film_editor.h
@@ -16,7 +16,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
+
/** @file src/film_editor.h
* @brief A wx widget to edit a film's metadata, and perform various functions.
*/
@@ -66,6 +66,7 @@ private:
void content_item_selected (wxListEvent &);
void content_add_clicked (wxCommandEvent &);
void content_remove_clicked (wxCommandEvent &);
+ void content_edit_clicked (wxCommandEvent &);
void content_earlier_clicked (wxCommandEvent &);
void content_later_clicked (wxCommandEvent &);
void imagemagick_video_length_changed (wxCommandEvent &);
@@ -131,10 +132,10 @@ private:
wxListCtrl* _content;
wxButton* _content_add;
wxButton* _content_remove;
+ wxButton* _content_edit;
wxButton* _content_earlier;
wxButton* _content_later;
wxTextCtrl* _content_information;
- wxSpinCtrl* _imagemagick_video_length;
wxButton* _edit_dci_button;
wxChoice* _format;
wxStaticText* _format_description;
diff --git a/src/wx/imagemagick_content_dialog.cc b/src/wx/imagemagick_content_dialog.cc
new file mode 100644
index 000000000..726e4b8e2
--- /dev/null
+++ b/src/wx/imagemagick_content_dialog.cc
@@ -0,0 +1,62 @@
+/*
+ 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/spinctrl.h>
+#include "lib/imagemagick_content.h"
+#include "imagemagick_content_dialog.h"
+#include "wx_util.h"
+
+using boost::shared_ptr;
+
+ImageMagickContentDialog::ImageMagickContentDialog (wxWindow* parent, shared_ptr<ImageMagickContent> content)
+ : wxDialog (parent, wxID_ANY, _("Image"))
+{
+ wxFlexGridSizer* grid = new wxFlexGridSizer (3, 6, 6);
+ grid->AddGrowableCol (1, 1);
+
+ {
+ add_label_to_sizer (grid, this, (_("Duration")));
+ wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
+ _video_length = new wxSpinCtrl (this);
+ s->Add (_video_length);
+ /// TRANSLATORS: this is an abbreviation for seconds, the unit of time
+ add_label_to_sizer (s, this, _("s"));
+ grid->Add (s);
+ }
+
+ 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);
+
+ checked_set (_video_length, content->video_length () / 24);
+}
+
+int
+ImageMagickContentDialog::video_length () const
+{
+ return _video_length->GetValue ();
+}
diff --git a/src/wx/imagemagick_content_dialog.h b/src/wx/imagemagick_content_dialog.h
new file mode 100644
index 000000000..2fa955929
--- /dev/null
+++ b/src/wx/imagemagick_content_dialog.h
@@ -0,0 +1,34 @@
+/*
+ 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>
+
+class wxSpinCtrl;
+class ImageMagickContent;
+
+class ImageMagickContentDialog : public wxDialog
+{
+public:
+ ImageMagickContentDialog (wxWindow *, boost::shared_ptr<ImageMagickContent>);
+
+ int video_length () const;
+
+private:
+ wxSpinCtrl* _video_length;
+};
diff --git a/src/wx/sndfile_content_dialog.cc b/src/wx/sndfile_content_dialog.cc
new file mode 100644
index 000000000..f305b158c
--- /dev/null
+++ b/src/wx/sndfile_content_dialog.cc
@@ -0,0 +1,67 @@
+/*
+ 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);
+}
diff --git a/src/wx/sndfile_content_dialog.h b/src/wx/sndfile_content_dialog.h
new file mode 100644
index 000000000..5a328892a
--- /dev/null
+++ b/src/wx/sndfile_content_dialog.h
@@ -0,0 +1,36 @@
+/*
+ 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;
+};
diff --git a/src/wx/wscript b/src/wx/wscript
index 42bb8ca88..bd21af6ce 100644
--- a/src/wx/wscript
+++ b/src/wx/wscript
@@ -14,11 +14,13 @@ sources = """
filter_dialog.cc
filter_view.cc
gain_calculator_dialog.cc
+ imagemagick_content_dialog.cc
job_manager_view.cc
job_wrapper.cc
new_film_dialog.cc
properties_dialog.cc
server_dialog.cc
+ sndfile_content_dialog.cc
wx_util.cc
wx_ui_signaller.cc
"""