int const AnalyseAudioJob::_num_points = 1024;
-AnalyseAudioJob::AnalyseAudioJob (shared_ptr<const Film> f, shared_ptr<AudioContent> c)
+AnalyseAudioJob::AnalyseAudioJob (shared_ptr<const Film> f, shared_ptr<const Playlist> p)
: Job (f)
- , _content (c)
+ , _playlist (p)
, _done (0)
, _samples_per_point (1)
, _overall_peak (0)
void
AnalyseAudioJob::run ()
{
- shared_ptr<AudioContent> content = _content.lock ();
- if (!content) {
- return;
- }
-
- shared_ptr<Playlist> playlist (new Playlist);
- playlist->add (content);
- shared_ptr<Player> player (new Player (_film, playlist));
+ shared_ptr<Player> player (new Player (_film, _playlist));
player->set_ignore_video ();
int64_t const len = _film->length().frames (_film->audio_frame_rate());
}
_analysis->set_peak (_overall_peak, DCPTime::from_frames (_overall_peak_frame, _film->audio_frame_rate ()));
- _analysis->write (content->audio_analysis_path ());
+ _analysis->write (_film->audio_analysis_path (_playlist));
set_progress (1);
set_state (FINISHED_OK);
#include "types.h"
class AudioBuffers;
-class AudioContent;
+class Playlist;
/** @class AnalyseAudioJob
- * @brief A job to analyse the audio of a piece of AudioContent and make a note of its
+ * @brief A job to analyse the audio of a playlist and make a note of its
* broad peak and RMS levels.
*
- * After computing the peak and RMS levels over the length of the content, the job
- * will write a file to Content::audio_analysis_path.
+ * After computing the peak and RMS levels the job will write a file
+ * to Playlist::audio_analysis_path.
*/
class AnalyseAudioJob : public Job
{
public:
- AnalyseAudioJob (boost::shared_ptr<const Film>, boost::shared_ptr<AudioContent>);
+ AnalyseAudioJob (boost::shared_ptr<const Film>, boost::shared_ptr<const Playlist>);
std::string name () const;
std::string json_name () const;
private:
void analyse (boost::shared_ptr<const AudioBuffers>);
- boost::weak_ptr<AudioContent> _content;
+ boost::shared_ptr<const Playlist> _playlist;
int64_t _done;
int64_t _samples_per_point;
std::vector<AudioPoint> _current;
#include "config.h"
#include "frame_rate_change.h"
#include "raw_convert.h"
+#include "playlist.h"
#include <libcxml/cxml.h>
#include <boost/foreach.hpp>
signal_changed (AudioContentProperty::AUDIO_DELAY);
}
-boost::signals2::connection
-AudioContent::analyse_audio (boost::function<void()> finished)
-{
- shared_ptr<const Film> film = _film.lock ();
- DCPOMATIC_ASSERT (film);
-
- shared_ptr<AnalyseAudioJob> job (new AnalyseAudioJob (film, dynamic_pointer_cast<AudioContent> (shared_from_this())));
- boost::signals2::connection c = job->Finished.connect (finished);
- JobManager::instance()->add (job);
-
- return c;
-}
-
-boost::filesystem::path
-AudioContent::audio_analysis_path () const
-{
- shared_ptr<const Film> film = _film.lock ();
- if (!film) {
- return boost::filesystem::path ();
- }
-
- boost::filesystem::path p = film->audio_analysis_dir ();
- p /= digest() + "_" + audio_mapping().digest();
- return p;
-}
-
string
AudioContent::technical_summary () const
{
AudioMapping audio_mapping () const;
void set_audio_mapping (AudioMapping);
- boost::filesystem::path audio_analysis_path () const;
int resampled_audio_frame_rate () const;
bool has_rate_above_48k () const;
std::vector<std::string> audio_channel_names () const;
- boost::signals2::connection analyse_audio (boost::function<void()>);
-
void set_audio_gain (double);
void set_audio_delay (int);
#include "environment_info.h"
#include "raw_convert.h"
#include "audio_processor.h"
+#include "md5_digester.h"
#include <libcxml/cxml.h>
#include <dcp/cpl.h>
#include <dcp/signer.h>
}
boost::filesystem::path
-Film::audio_analysis_dir () const
+Film::audio_analysis_path (shared_ptr<const Playlist> playlist) const
{
- return dir ("analysis");
+ boost::filesystem::path p = dir ("analysis");
+
+ MD5Digester digester;
+ BOOST_FOREACH (shared_ptr<Content> i, playlist->content ()) {
+ shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> (i);
+ if (!ac) {
+ continue;
+ }
+
+ digester.add (ac->digest ());
+ digester.add (ac->audio_mapping().digest ());
+ digester.add (ac->audio_gain ());
+ }
+
+ if (audio_processor ()) {
+ digester.add (audio_processor()->id ());
+ }
+
+ p /= digester.get ();
+ return p;
}
/** Add suitable Jobs to the JobManager to create a DCP for this Film */
boost::filesystem::path j2c_path (int, Eyes, bool) const;
boost::filesystem::path internal_video_mxf_dir () const;
boost::filesystem::path internal_video_mxf_filename () const;
- boost::filesystem::path audio_analysis_dir () const;
+
+ boost::filesystem::path audio_analysis_path (boost::shared_ptr<const Playlist>) const;
void send_dcp_to_tms ();
void make_dcp ();
MD5_Update (&_context, data, size);
}
+void
+MD5Digester::add (string const & s)
+{
+ add (s.c_str (), s.length ());
+}
+
string
MD5Digester::get () const
{
void add (T data) {
add (&data, sizeof (T));
}
+
+ void add (std::string const & s);
std::string get () const;
*/
-#include <boost/filesystem.hpp>
-#include "lib/audio_analysis.h"
-#include "lib/film.h"
-#include "lib/audio_content.h"
#include "audio_dialog.h"
#include "audio_plot.h"
#include "wx_util.h"
+#include "lib/audio_analysis.h"
+#include "lib/film.h"
+#include "lib/analyse_audio_job.h"
+#include "lib/job_manager.h"
+#include "lib/playlist.h"
+#include <boost/filesystem.hpp>
using boost::shared_ptr;
using boost::bind;
}
void
-AudioDialog::set_content (shared_ptr<AudioContent> c)
+AudioDialog::set_playlist (shared_ptr<const Playlist> p)
{
- _content_changed_connection.disconnect ();
-
- _content = c;
-
+ _playlist_connection.disconnect ();
+ _playlist = p;
+ _playlist_connection = _playlist->ContentChanged.connect (boost::bind (&AudioDialog::try_to_load_analysis, this));
try_to_load_analysis ();
- _plot->set_gain (_content->audio_gain ());
-
- _content_changed_connection = _content->Changed.connect (bind (&AudioDialog::content_changed, this, _2));
-
- SetTitle (wxString::Format (_("DCP-o-matic audio - %s"), std_to_wx(_content->path_summary()).data()));
+ SetTitle (_("DCP-o-matic audio"));
}
void
return;
}
- if (!boost::filesystem::exists (_content->audio_analysis_path())) {
+ shared_ptr<const Film> film = _film.lock ();
+ DCPOMATIC_ASSERT (film);
+
+ boost::filesystem::path path = film->audio_analysis_path (_playlist);
+
+ if (!boost::filesystem::exists (path)) {
_plot->set_analysis (shared_ptr<AudioAnalysis> ());
_analysis.reset ();
- _analysis_finished_connection = _content->analyse_audio (bind (&AudioDialog::analysis_finished, this));
+ shared_ptr<AnalyseAudioJob> job (new AnalyseAudioJob (film, _playlist));
+ _analysis_finished_connection = job->Finished.connect (bind (&AudioDialog::analysis_finished, this));
+ JobManager::instance()->add (job);
return;
}
try {
- _analysis.reset (new AudioAnalysis (_content->audio_analysis_path ()));
+ _analysis.reset (new AudioAnalysis (path));
} catch (xmlpp::exception& e) {
/* Probably an old-style analysis file: recreate it */
- _analysis_finished_connection = _content->analyse_audio (bind (&AudioDialog::analysis_finished, this));
+ shared_ptr<AnalyseAudioJob> job (new AnalyseAudioJob (film, _playlist));
+ _analysis_finished_connection = job->Finished.connect (bind (&AudioDialog::analysis_finished, this));
+ JobManager::instance()->add (job);
return;
}
void
AudioDialog::analysis_finished ()
{
- if (!boost::filesystem::exists (_content->audio_analysis_path())) {
+ shared_ptr<const Film> film = _film.lock ();
+ DCPOMATIC_ASSERT (film);
+
+ if (!boost::filesystem::exists (film->audio_analysis_path (_playlist))) {
/* We analysed and still nothing showed up, so maybe it was cancelled or it failed.
Give up.
*/
void
AudioDialog::content_changed (int p)
{
- if (p == AudioContentProperty::AUDIO_GAIN) {
- _plot->set_gain (_content->audio_gain ());
- setup_peak_time ();
- } else if (p == AudioContentProperty::AUDIO_STREAMS) {
+ if (p == AudioContentProperty::AUDIO_GAIN || p == AudioContentProperty::AUDIO_STREAMS) {
try_to_load_analysis ();
}
}
return;
}
- float peak_dB = 20 * log10 (_analysis->peak().get()) + _content->audio_gain();
+ float peak_dB = 20 * log10 (_analysis->peak().get());
_peak_time->SetLabel (
wxString::Format (
public:
AudioDialog (wxWindow *, boost::shared_ptr<Film> film);
- void set_content (boost::shared_ptr<AudioContent>);
+ void set_playlist (boost::shared_ptr<const Playlist>);
private:
void content_changed (int);
void analysis_finished ();
void setup_peak_time ();
- boost::shared_ptr<AudioContent> _content;
+ boost::shared_ptr<const Playlist> _playlist;
boost::shared_ptr<AudioAnalysis> _analysis;
boost::weak_ptr<Film> _film;
AudioPlot* _plot;
wxCheckBox* _channel_checkbox[MAX_DCP_AUDIO_CHANNELS];
wxCheckBox* _type_checkbox[AudioPoint::COUNT];
wxSlider* _smoothing;
- boost::signals2::scoped_connection _content_changed_connection;
+ boost::signals2::scoped_connection _playlist_connection;
boost::signals2::scoped_connection _analysis_finished_connection;
};
#include "lib/config.h"
#include "lib/ffmpeg_content.h"
#include "lib/cinema_sound_processor.h"
-#include "audio_dialog.h"
#include "audio_panel.h"
#include "audio_mapping_view.h"
#include "wx_util.h"
AudioPanel::AudioPanel (ContentPanel* p)
: ContentSubPanel (p, _("Audio"))
- , _audio_dialog (0)
{
wxGridBagSizer* grid = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
_sizer->Add (grid, 0, wxALL, 8);
int r = 0;
- _show = new wxButton (this, wxID_ANY, _("Show Audio..."));
- grid->Add (_show, wxGBPosition (r, 0));
- ++r;
-
add_label_to_grid_bag_sizer (grid, this, _("Gain"), true, wxGBPosition (r, 0));
_gain = new ContentSpinCtrlDouble<AudioContent> (
this,
_gain->wrapped()->SetIncrement (0.5);
_delay->wrapped()->SetRange (-1000, 1000);
- _show->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&AudioPanel::show_clicked, this));
_gain_calculate_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&AudioPanel::gain_calculate_button_clicked, this));
_mapping_connection = _mapping->Changed.connect (boost::bind (&AudioPanel::mapping_changed, this, _1));
d->Destroy ();
}
-void
-AudioPanel::show_clicked ()
-{
- if (_audio_dialog) {
- _audio_dialog->Destroy ();
- _audio_dialog = 0;
- }
-
- AudioContentList ac = _parent->selected_audio ();
- if (ac.size() != 1) {
- return;
- }
-
- _audio_dialog = new AudioDialog (this, _parent->film ());
- _audio_dialog->Show ();
- _audio_dialog->set_content (ac.front ());
-}
-
void
AudioPanel::setup_description ()
{
{
AudioContentList sel = _parent->selected_audio ();
- if (_audio_dialog && sel.size() == 1) {
- _audio_dialog->set_content (sel.front ());
- }
-
_gain->set_content (sel);
_delay->set_content (sel);
_gain_calculate_button->Enable (sel.size() == 1);
- _show->Enable (sel.size() == 1);
_mapping->Enable (sel.size() == 1);
film_content_changed (AudioContentProperty::AUDIO_STREAMS);
class wxChoice;
class wxStaticText;
class AudioMappingView;
-class AudioDialog;
class AudioPanel : public ContentSubPanel
{
private:
void gain_calculate_button_clicked ();
- void show_clicked ();
void mapping_changed (AudioMapping);
void setup_description ();
ContentSpinCtrlDouble<AudioContent>* _gain;
wxButton* _gain_calculate_button;
- wxButton* _show;
ContentSpinCtrl<AudioContent>* _delay;
AudioMappingView* _mapping;
wxStaticText* _description;
- AudioDialog* _audio_dialog;
boost::signals2::scoped_connection _mapping_connection;
};
AudioPlot::AudioPlot (wxWindow* parent)
: wxPanel (parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE)
- , _gain (0)
, _smoothing (max_smoothing / 2)
{
#ifndef __WXOSX__
p = 1e-4;
}
- return metrics.height - (20 * log10(p) - _minimum + _gain) * metrics.y_scale - metrics.y_origin;
+ return metrics.height - (20 * log10(p) - _minimum) * metrics.y_scale - metrics.y_origin;
}
void
}
}
-void
-AudioPlot::set_gain (float g)
-{
- _gain = g;
- Refresh ();
-}
-
void
AudioPlot::set_smoothing (int s)
{
void set_analysis (boost::shared_ptr<AudioAnalysis>);
void set_channel_visible (int c, bool v);
void set_type_visible (int t, bool v);
- void set_gain (float);
void set_smoothing (int);
void set_message (wxString);
boost::shared_ptr<AudioAnalysis> _analysis;
bool _channel_visible[MAX_DCP_AUDIO_CHANNELS];
bool _type_visible[AudioPoint::COUNT];
- /** gain to apply in dB */
- float _gain;
int _smoothing;
std::vector<wxColour> _colours;
#include "wx_util.h"
#include "key_dialog.h"
#include "isdcf_metadata_dialog.h"
+#include "audio_dialog.h"
#include "lib/ratio.h"
#include "lib/config.h"
#include "lib/dcp_content_type.h"
using boost::shared_ptr;
DCPPanel::DCPPanel (wxNotebook* n, boost::shared_ptr<Film> f)
- : _film (f)
+ : _audio_dialog (0)
+ , _film (f)
, _generally_sensitive (true)
{
_panel = new wxPanel (n);
_audio_processor->Append (std_to_wx (ap->name ()), new wxStringClientData (std_to_wx (ap->id ())));
}
grid->Add (_audio_processor, wxGBPosition (r, 1));
-
+ ++r;
+
+ _show_audio = new wxButton (panel, wxID_ANY, _("Show audio..."));
+ grid->Add (_show_audio, wxGBPosition (r, 0), wxGBSpan (1, 2));
++r;
_audio_channels->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DCPPanel::audio_channels_changed, this));
_audio_processor->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DCPPanel::audio_processor_changed, this));
+ _show_audio->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&DCPPanel::show_audio_clicked, this));
return panel;
}
string const s = string_client_data (_audio_processor->GetClientObject (_audio_processor->GetSelection ()));
_film->set_audio_processor (AudioProcessor::from_id (s));
}
+
+void
+DCPPanel::show_audio_clicked ()
+{
+ if (!_film) {
+ return;
+ }
+
+ if (_audio_dialog) {
+ _audio_dialog->Destroy ();
+ _audio_dialog = 0;
+ }
+
+ AudioDialog* d = new AudioDialog (_panel, _film);
+ d->Show ();
+ d->set_playlist (_film->playlist ());
+}
class wxSpinCtrl;
class wxSizer;
+class AudioDialog;
+
class Film;
class DCPPanel : public boost::noncopyable
void encrypted_toggled ();
void edit_key_clicked ();
void audio_processor_changed ();
+ void show_audio_clicked ();
void setup_frame_rate_widget ();
void setup_container ();
wxSizer* _frame_rate_sizer;
wxChoice* _audio_channels;
wxChoice* _audio_processor;
+ wxButton* _show_audio;
wxButton* _best_frame_rate;
wxCheckBox* _three_d;
wxChoice* _resolution;
wxStaticText* _key;
wxButton* _edit_key;
+ AudioDialog* _audio_dialog;
+
boost::shared_ptr<Film> _film;
bool _generally_sensitive;
};
#include <boost/test/unit_test.hpp>
#include "lib/audio_analysis.h"
+#include "lib/analyse_audio_job.h"
#include "lib/film.h"
#include "lib/sndfile_content.h"
#include "lib/dcp_content_type.h"
#include "lib/ffmpeg_content.h"
#include "lib/ratio.h"
+#include "lib/job_manager.h"
#include "test.h"
using boost::shared_ptr;
film->examine_and_add_content (c);
wait_for_jobs ();
- c->analyse_audio (boost::bind (&finished));
+ shared_ptr<AnalyseAudioJob> job (new AnalyseAudioJob (film, film->playlist ()));
+ job->Finished.connect (boost::bind (&finished));
+ JobManager::instance()->add (job);
wait_for_jobs ();
}
film->examine_and_add_content (c);
wait_for_jobs ();
- c->analyse_audio (boost::bind (&finished));
+ shared_ptr<AnalyseAudioJob> job (new AnalyseAudioJob (film, film->playlist ()));
+ job->Finished.connect (boost::bind (&finished));
+ JobManager::instance()->add (job);
wait_for_jobs ();
}