* Fix exporting multiple formats with different normalization settings or demo-noise settings * Add true-peak limiter (based on x42-limiter dpl.lv2) * Optionally use a limiter for loudness normalization * Fall back to short-term loudness when normalizing material too short for integrating loudness.
888 lines
25 KiB
C++
888 lines
25 KiB
C++
/*
|
|
* Copyright (C) 2008-2012 Sakari Bergen <sakari.bergen@beatwaves.net>
|
|
* Copyright (C) 2008-2016 Paul Davis <paul@linuxaudiosystems.com>
|
|
* Copyright (C) 2009-2012 David Robillard <d@drobilla.net>
|
|
* Copyright (C) 2013-2014 Colin Fletcher <colin.m.fletcher@googlemail.com>
|
|
* Copyright (C) 2016-2018 Robin Gareus <robin@gareus.org>
|
|
*
|
|
* 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.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#include "ardour/export_format_manager.h"
|
|
#include "ardour/filesystem_paths.h"
|
|
|
|
#include "ardour/export_format_specification.h"
|
|
#include "ardour/export_format_compatibility.h"
|
|
|
|
#include "pbd/i18n.h"
|
|
|
|
using std::string;
|
|
|
|
namespace ARDOUR
|
|
{
|
|
|
|
ExportFormatManager::ExportFormatManager (ExportFormatSpecPtr specification) :
|
|
pending_selection_change (false),
|
|
universal_set (new ExportFormatBase ())
|
|
{
|
|
current_selection = specification;
|
|
|
|
init_compatibilities ();
|
|
init_qualities ();
|
|
init_formats ();
|
|
init_sample_rates ();
|
|
|
|
prev_description = current_selection->description();
|
|
}
|
|
|
|
ExportFormatManager::~ExportFormatManager ()
|
|
{
|
|
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::init_compatibilities ()
|
|
{
|
|
ExportFormatCompatibilityPtr c_ptr;
|
|
|
|
c_ptr.reset (new ExportFormatCompatibility (_("CD")));
|
|
c_ptr->add_sample_rate (ExportFormatBase::SR_44_1);
|
|
c_ptr->add_format_id (ExportFormatBase::F_WAV);
|
|
c_ptr->add_format_id (ExportFormatBase::F_AIFF);
|
|
c_ptr->add_quality (ExportFormatBase::Q_LosslessLinear);
|
|
c_ptr->add_sample_format (ExportFormatBase::SF_16);
|
|
c_ptr->add_endianness (ExportFormatBase::E_FileDefault);
|
|
add_compatibility (c_ptr);
|
|
|
|
c_ptr.reset (new ExportFormatCompatibility (_("DVD-A")));
|
|
c_ptr->add_sample_rate (ExportFormatBase::SR_44_1);
|
|
c_ptr->add_sample_rate (ExportFormatBase::SR_48);
|
|
c_ptr->add_sample_rate (ExportFormatBase::SR_88_2);
|
|
c_ptr->add_sample_rate (ExportFormatBase::SR_96);
|
|
c_ptr->add_sample_rate (ExportFormatBase::SR_192);
|
|
c_ptr->add_format_id (ExportFormatBase::F_WAV);
|
|
c_ptr->add_format_id (ExportFormatBase::F_AIFF);
|
|
c_ptr->add_quality (ExportFormatBase::Q_LosslessLinear);
|
|
c_ptr->add_sample_format (ExportFormatBase::SF_16);
|
|
c_ptr->add_sample_format (ExportFormatBase::SF_24);
|
|
c_ptr->add_endianness (ExportFormatBase::E_FileDefault);
|
|
add_compatibility (c_ptr);
|
|
|
|
c_ptr.reset (new ExportFormatCompatibility (_("iPod")));
|
|
c_ptr->add_sample_rate (ExportFormatBase::SR_44_1);
|
|
c_ptr->add_sample_rate (ExportFormatBase::SR_48);
|
|
c_ptr->add_format_id (ExportFormatBase::F_WAV);
|
|
c_ptr->add_format_id (ExportFormatBase::F_AIFF);
|
|
c_ptr->add_quality (ExportFormatBase::Q_LosslessLinear);
|
|
c_ptr->add_sample_format (ExportFormatBase::SF_16);
|
|
c_ptr->add_sample_format (ExportFormatBase::SF_24);
|
|
c_ptr->add_endianness (ExportFormatBase::E_FileDefault);
|
|
add_compatibility (c_ptr);
|
|
|
|
c_ptr.reset (new ExportFormatCompatibility (_("Something else")));
|
|
c_ptr->add_sample_rate (ExportFormatBase::SR_44_1);
|
|
c_ptr->add_sample_rate (ExportFormatBase::SR_48);
|
|
c_ptr->add_format_id (ExportFormatBase::F_WAV);
|
|
c_ptr->add_format_id (ExportFormatBase::F_AIFF);
|
|
c_ptr->add_format_id (ExportFormatBase::F_AU);
|
|
c_ptr->add_format_id (ExportFormatBase::F_FLAC);
|
|
c_ptr->add_quality (ExportFormatBase::Q_LosslessLinear);
|
|
c_ptr->add_quality (ExportFormatBase::Q_LosslessCompression);
|
|
c_ptr->add_sample_format (ExportFormatBase::SF_16);
|
|
c_ptr->add_sample_format (ExportFormatBase::SF_24);
|
|
c_ptr->add_sample_format (ExportFormatBase::SF_32);
|
|
c_ptr->add_endianness (ExportFormatBase::E_FileDefault);
|
|
add_compatibility (c_ptr);
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::init_qualities ()
|
|
{
|
|
add_quality (QualityPtr (new QualityState (ExportFormatBase::Q_Any, _("Any"))));
|
|
add_quality (QualityPtr (new QualityState (ExportFormatBase::Q_LosslessLinear, _("Lossless (linear PCM)"))));
|
|
add_quality (QualityPtr (new QualityState (ExportFormatBase::Q_LossyCompression, _("Lossy compression"))));
|
|
add_quality (QualityPtr (new QualityState (ExportFormatBase::Q_LosslessCompression, _("Lossless compression"))));
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::init_formats ()
|
|
{
|
|
ExportFormatPtr f_ptr;
|
|
ExportFormatLinear * fl_ptr;
|
|
|
|
f_ptr.reset (fl_ptr = new ExportFormatTaggedLinear ("AIFF", ExportFormatBase::F_AIFF));
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_U8);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_8);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_16);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_24);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_32);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_Double);
|
|
fl_ptr->add_endianness (ExportFormatBase::E_Big);
|
|
fl_ptr->set_default_sample_format (ExportFormatBase::SF_16);
|
|
fl_ptr->set_extension ("aiff");
|
|
add_format (f_ptr);
|
|
|
|
f_ptr.reset (fl_ptr = new ExportFormatLinear ("AU", ExportFormatBase::F_AU));
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_8);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_16);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_24);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_32);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_Double);
|
|
fl_ptr->set_default_sample_format (ExportFormatBase::SF_16);
|
|
fl_ptr->set_extension ("au");
|
|
add_format (f_ptr);
|
|
|
|
f_ptr.reset (new ExportFormatBWF ());
|
|
add_format (f_ptr);
|
|
|
|
f_ptr.reset (fl_ptr = new ExportFormatLinear ("IRCAM", ExportFormatBase::F_IRCAM));
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_16);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_24);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_32);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
|
|
fl_ptr->set_default_sample_format (ExportFormatBase::SF_24);
|
|
fl_ptr->set_extension ("sf");
|
|
add_format (f_ptr);
|
|
|
|
f_ptr.reset (fl_ptr = new ExportFormatTaggedLinear ("WAV", ExportFormatBase::F_WAV));
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_U8);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_16);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_24);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_32);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_Double);
|
|
fl_ptr->add_endianness (ExportFormatBase::E_Little);
|
|
fl_ptr->set_default_sample_format (ExportFormatBase::SF_16);
|
|
fl_ptr->set_extension ("wav");
|
|
add_format (f_ptr);
|
|
|
|
f_ptr.reset (fl_ptr = new ExportFormatTaggedLinear ("W64", ExportFormatBase::F_W64));
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_U8);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_16);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_24);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_32);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_Double);
|
|
fl_ptr->set_default_sample_format (ExportFormatBase::SF_Double);
|
|
fl_ptr->set_extension ("w64");
|
|
add_format (f_ptr);
|
|
|
|
f_ptr.reset (fl_ptr = new ExportFormatLinear ("CAF", ExportFormatBase::F_CAF));
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_U8);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_16);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_24);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_32);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_Double);
|
|
fl_ptr->set_default_sample_format (ExportFormatBase::SF_Float);
|
|
fl_ptr->set_extension ("caf");
|
|
add_format (f_ptr);
|
|
|
|
f_ptr.reset (fl_ptr = new ExportFormatLinear ("RAW", ExportFormatBase::F_RAW));
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_U8);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_8);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_16);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_24);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_32);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
|
|
fl_ptr->add_sample_format (ExportFormatBase::SF_Double);
|
|
fl_ptr->set_default_sample_format (ExportFormatBase::SF_Float);
|
|
fl_ptr->set_extension ("raw");
|
|
add_format (f_ptr);
|
|
|
|
try {
|
|
f_ptr.reset (new ExportFormatOggVorbis ());
|
|
add_format (f_ptr);
|
|
} catch (ExportFormatIncompatible & e) {}
|
|
|
|
try {
|
|
f_ptr.reset (new ExportFormatFLAC ());
|
|
add_format (f_ptr);
|
|
} catch (ExportFormatIncompatible & e) {}
|
|
|
|
std::string unused;
|
|
if (ArdourVideoToolPaths::transcoder_exe (unused, unused)) {
|
|
f_ptr.reset (new ExportFormatFFMPEG ("MP3", "mp3"));
|
|
add_format (f_ptr);
|
|
}
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::init_sample_rates ()
|
|
{
|
|
add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_Session, _("Session rate"))));
|
|
add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_8, string_compose ("%1%2%3 kHz", std::fixed, std::setprecision(0), 8))));
|
|
add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_22_05, string_compose ("%1%2%3 kHz", std::fixed, std::setprecision(2), 22.05))));
|
|
add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_44_1, string_compose ("%1%2%3 kHz", std::fixed, std::setprecision(1), 44.1))));
|
|
add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_48, string_compose ("%1%2%3 kHz", std::fixed, std::setprecision(0), 48))));
|
|
add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_88_2, string_compose ("%1%2%3 kHz", std::fixed, std::setprecision(1), 88.2))));
|
|
add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_96, string_compose ("%1%2%3 kHz", std::fixed, std::setprecision(0), 96))));
|
|
add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_176_4, string_compose ("%1%2%3 kHz", std::fixed, std::setprecision(0), 176.4))));
|
|
add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_192, string_compose ("%1%2%3 kHz", std::fixed, std::setprecision(0), 192))));
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::add_compatibility (ExportFormatCompatibilityPtr ptr)
|
|
{
|
|
compatibilities.push_back (ptr);
|
|
ptr->SelectChanged.connect_same_thread (*this,
|
|
boost::bind (&ExportFormatManager::change_compatibility_selection,
|
|
this, _1, WeakExportFormatCompatibilityPtr (ptr)));
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::add_quality (QualityPtr ptr)
|
|
{
|
|
ptr->SelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_quality_selection, this, _1, WeakQualityPtr (ptr)));
|
|
qualities.push_back (ptr);
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::add_format (ExportFormatPtr ptr)
|
|
{
|
|
formats.push_back (ptr);
|
|
ptr->SelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_format_selection, this, _1, WeakExportFormatPtr (ptr)));
|
|
universal_set = universal_set->get_union (*ptr);
|
|
|
|
/* Encoding options */
|
|
|
|
boost::shared_ptr<HasSampleFormat> hsf;
|
|
|
|
if ((hsf = boost::dynamic_pointer_cast<HasSampleFormat> (ptr))) {
|
|
hsf->SampleFormatSelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_sample_format_selection, this, _1, _2));
|
|
hsf->DitherTypeSelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_dither_type_selection, this, _1, _2));
|
|
}
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::add_sample_rate (SampleRatePtr ptr)
|
|
{
|
|
ptr->SelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_sample_rate_selection, this, _1, WeakSampleRatePtr (ptr)));
|
|
sample_rates.push_back (ptr);
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::set_name (string name)
|
|
{
|
|
current_selection->set_name (name);
|
|
check_for_description_change ();
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_src_quality (ExportFormatBase::SRCQuality value)
|
|
{
|
|
current_selection->set_src_quality (value);
|
|
check_for_description_change ();
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_codec_quality (int value)
|
|
{
|
|
current_selection->set_codec_quality (value);
|
|
check_for_description_change ();
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_with_cue (bool value)
|
|
{
|
|
current_selection->set_with_cue (value);
|
|
check_for_description_change ();
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_with_toc (bool value)
|
|
{
|
|
current_selection->set_with_toc (value);
|
|
check_for_description_change ();
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_with_mp4chaps (bool value)
|
|
{
|
|
current_selection->set_with_mp4chaps (value);
|
|
check_for_description_change ();
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::set_command (std::string command)
|
|
{
|
|
current_selection->set_command (command);
|
|
check_for_description_change ();
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_trim_beginning (bool value)
|
|
{
|
|
current_selection->set_trim_beginning (value);
|
|
check_for_description_change ();
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_silence_beginning (AnyTime const & time)
|
|
{
|
|
current_selection->set_silence_beginning (time);
|
|
check_for_description_change ();
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_trim_end (bool value)
|
|
{
|
|
current_selection->set_trim_end (value);
|
|
check_for_description_change ();
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_silence_end (AnyTime const & time)
|
|
{
|
|
current_selection->set_silence_end (time);
|
|
check_for_description_change ();
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_normalize (bool value)
|
|
{
|
|
current_selection->set_normalize (value);
|
|
check_for_description_change ();
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_normalize_loudness (bool value)
|
|
{
|
|
current_selection->set_normalize_loudness (value);
|
|
check_for_description_change ();
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_tp_limiter (bool value)
|
|
{
|
|
current_selection->set_use_tp_limiter (value);
|
|
check_for_description_change ();
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_normalize_dbfs (float value)
|
|
{
|
|
current_selection->set_normalize_dbfs (value);
|
|
check_for_description_change ();
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_normalize_lufs (float value)
|
|
{
|
|
current_selection->set_normalize_lufs (value);
|
|
check_for_description_change ();
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_normalize_dbtp (float value)
|
|
{
|
|
current_selection->set_normalize_dbtp (value);
|
|
check_for_description_change ();
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_demo_noise_level (float value)
|
|
{
|
|
current_selection->set_demo_noise_level (value);
|
|
check_for_description_change ();
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_demo_noise_duration (int value)
|
|
{
|
|
current_selection->set_demo_noise_duration (value);
|
|
check_for_description_change ();
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_demo_noise_interval (int value)
|
|
{
|
|
current_selection->set_demo_noise_interval (value);
|
|
check_for_description_change ();
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_tagging (bool tag)
|
|
{
|
|
current_selection->set_tag (tag);
|
|
check_for_description_change ();
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::change_compatibility_selection (bool select, WeakExportFormatCompatibilityPtr const & compat)
|
|
{
|
|
bool do_selection_changed = !pending_selection_change;
|
|
if (!pending_selection_change) {
|
|
pending_selection_change = true;
|
|
}
|
|
|
|
ExportFormatCompatibilityPtr ptr = compat.lock();
|
|
|
|
if (ptr && select) {
|
|
select_compatibility (ptr);
|
|
}
|
|
|
|
if (do_selection_changed) {
|
|
selection_changed ();
|
|
}
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::change_quality_selection (bool select, WeakQualityPtr const & quality)
|
|
{
|
|
QualityPtr ptr = quality.lock ();
|
|
|
|
if (!ptr) {
|
|
return;
|
|
}
|
|
|
|
if (select) {
|
|
select_quality (ptr);
|
|
} else if (ptr->quality == current_selection->quality()) {
|
|
ptr.reset();
|
|
select_quality (ptr);
|
|
}
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::change_format_selection (bool select, WeakExportFormatPtr const & format)
|
|
{
|
|
ExportFormatPtr ptr = format.lock();
|
|
|
|
if (!ptr) {
|
|
return;
|
|
}
|
|
|
|
if (select) {
|
|
select_format (ptr);
|
|
} else if (ptr->get_format_id() == current_selection->format_id()) {
|
|
ptr.reset();
|
|
select_format (ptr);
|
|
}
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::change_sample_rate_selection (bool select, WeakSampleRatePtr const & rate)
|
|
{
|
|
SampleRatePtr ptr = rate.lock();
|
|
|
|
if (!ptr) {
|
|
return;
|
|
}
|
|
|
|
if (select) {
|
|
select_sample_rate (ptr);
|
|
} else if (ptr->rate == current_selection->sample_rate()) {
|
|
ptr.reset();
|
|
select_sample_rate (ptr);
|
|
}
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::change_sample_format_selection (bool select, WeakSampleFormatPtr const & format)
|
|
{
|
|
SampleFormatPtr ptr = format.lock();
|
|
|
|
if (!ptr) {
|
|
return;
|
|
}
|
|
|
|
if (select) {
|
|
select_sample_format (ptr);
|
|
} else if (ptr->format == current_selection->sample_format()) {
|
|
ptr.reset();
|
|
select_sample_format (ptr);
|
|
}
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::change_dither_type_selection (bool select, WeakDitherTypePtr const & type)
|
|
{
|
|
DitherTypePtr ptr = type.lock();
|
|
|
|
if (!ptr) {
|
|
return;
|
|
}
|
|
|
|
if (select) {
|
|
select_dither_type (ptr);
|
|
} else if (ptr->type == current_selection->dither_type()) {
|
|
ptr.reset();
|
|
select_dither_type (ptr);
|
|
}
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_compatibility (WeakExportFormatCompatibilityPtr const & /*compat*/)
|
|
{
|
|
/* Calculate compatibility intersection for the selection */
|
|
|
|
ExportFormatBasePtr compat_intersect = get_compatibility_intersection ();
|
|
|
|
/* Unselect incompatible items */
|
|
|
|
boost::shared_ptr<ExportFormatBase> select_intersect;
|
|
|
|
select_intersect = compat_intersect->get_intersection (*current_selection);
|
|
if (select_intersect->qualities_empty()) {
|
|
select_quality (QualityPtr());
|
|
}
|
|
|
|
select_intersect = compat_intersect->get_intersection (*current_selection);
|
|
if (select_intersect->formats_empty()) {
|
|
select_format (ExportFormatPtr());
|
|
}
|
|
|
|
select_intersect = compat_intersect->get_intersection (*current_selection);
|
|
if (select_intersect->sample_rates_empty()) {
|
|
select_sample_rate (SampleRatePtr());
|
|
}
|
|
|
|
select_intersect = compat_intersect->get_intersection (*current_selection);
|
|
if (select_intersect->sample_formats_empty()) {
|
|
select_sample_format (SampleFormatPtr());
|
|
}
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_quality (QualityPtr const & quality)
|
|
{
|
|
bool do_selection_changed = !pending_selection_change;
|
|
if (!pending_selection_change) {
|
|
pending_selection_change = true;
|
|
}
|
|
|
|
if (quality) {
|
|
current_selection->set_quality (quality->quality);
|
|
|
|
/* Deselect format if it is incompatible */
|
|
|
|
ExportFormatPtr format = get_selected_format();
|
|
if (format && !format->has_quality (quality->quality)) {
|
|
format->set_selected (false);
|
|
}
|
|
|
|
} else {
|
|
current_selection->set_quality (ExportFormatBase::Q_None);
|
|
|
|
QualityPtr current_quality = get_selected_quality();
|
|
if (current_quality) {
|
|
current_quality->set_selected (false);
|
|
}
|
|
|
|
/* Note:
|
|
* A quality is never explicitly deselected without also deselecting the format
|
|
* so we don't need to deselect the format here.
|
|
* doing so causes extra complications
|
|
*/
|
|
}
|
|
|
|
if (do_selection_changed) {
|
|
selection_changed ();
|
|
}
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_format (ExportFormatPtr const & format)
|
|
{
|
|
bool do_selection_changed = !pending_selection_change;
|
|
if (!pending_selection_change) {
|
|
pending_selection_change = true;
|
|
}
|
|
|
|
current_selection->set_format (format);
|
|
|
|
if (format) {
|
|
|
|
/* Slect right quality for format */
|
|
|
|
ExportFormatBase::Quality quality = format->get_quality();
|
|
for (QualityList::iterator it = qualities.begin (); it != qualities.end (); ++it) {
|
|
if ((*it)->quality == quality) {
|
|
(*it)->set_selected (true);
|
|
} else {
|
|
(*it)->set_selected (false);
|
|
}
|
|
}
|
|
|
|
/* Handle sample formats */
|
|
|
|
ExportFormatBase::SampleFormat format_to_select;
|
|
if (format->sample_format_is_compatible (current_selection->sample_format())) {
|
|
format_to_select = current_selection->sample_format();
|
|
} else {
|
|
format_to_select = format->default_sample_format();
|
|
}
|
|
|
|
boost::shared_ptr<HasSampleFormat> hsf;
|
|
if ((hsf = boost::dynamic_pointer_cast<HasSampleFormat> (format))) {
|
|
SampleFormatList sample_formats = hsf->get_sample_formats();
|
|
for (SampleFormatList::iterator it = sample_formats.begin (); it != sample_formats.end (); ++it) {
|
|
if ((*it)->format == format_to_select) {
|
|
(*it)->set_selected (true);
|
|
} else {
|
|
(*it)->set_selected (false);
|
|
}
|
|
}
|
|
}
|
|
|
|
current_selection->set_sample_format (format_to_select);
|
|
|
|
} else {
|
|
ExportFormatPtr current_format = get_selected_format ();
|
|
if (current_format) {
|
|
current_format->set_selected (false);
|
|
}
|
|
}
|
|
|
|
if (do_selection_changed) {
|
|
selection_changed ();
|
|
}
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_sample_rate (SampleRatePtr const & rate)
|
|
{
|
|
|
|
bool do_selection_changed = !pending_selection_change;
|
|
if (!pending_selection_change) {
|
|
pending_selection_change = true;
|
|
}
|
|
|
|
if (rate) {
|
|
current_selection->set_sample_rate (rate->rate);
|
|
} else {
|
|
current_selection->set_sample_rate (ExportFormatBase::SR_None);
|
|
|
|
SampleRatePtr current_rate = get_selected_sample_rate();
|
|
if (current_rate) {
|
|
current_rate->set_selected (false);
|
|
}
|
|
}
|
|
|
|
if (do_selection_changed) {
|
|
selection_changed ();
|
|
}
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_sample_format (SampleFormatPtr const & format)
|
|
{
|
|
|
|
bool do_selection_changed = !pending_selection_change;
|
|
if (!pending_selection_change) {
|
|
pending_selection_change = true;
|
|
}
|
|
|
|
if (format) {
|
|
current_selection->set_sample_format (format->format);
|
|
} else {
|
|
current_selection->set_sample_format (ExportFormatBase::SF_None);
|
|
|
|
SampleFormatPtr current_format = get_selected_sample_format();
|
|
if (current_format) {
|
|
current_format->set_selected (false);
|
|
}
|
|
}
|
|
|
|
if (do_selection_changed) {
|
|
selection_changed ();
|
|
}
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::select_dither_type (DitherTypePtr const & type)
|
|
{
|
|
|
|
bool do_selection_changed = !pending_selection_change;
|
|
if (!pending_selection_change) {
|
|
pending_selection_change = true;
|
|
}
|
|
|
|
if (type) {
|
|
current_selection->set_dither_type (type->type);
|
|
} else {
|
|
current_selection->set_dither_type (ExportFormatBase::D_None);
|
|
}
|
|
|
|
if (do_selection_changed) {
|
|
selection_changed ();
|
|
}
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::selection_changed ()
|
|
{
|
|
/* Get a list of incompatible compatibility selections */
|
|
|
|
CompatList incompatibles;
|
|
for (CompatList::iterator it = compatibilities.begin(); it != compatibilities.end(); ++it) {
|
|
if (!current_selection->is_compatible_with (**it)) {
|
|
incompatibles.push_back (*it);
|
|
}
|
|
}
|
|
|
|
/* Deselect them */
|
|
|
|
for (CompatList::iterator it = incompatibles.begin(); it != incompatibles.end(); ++it) {
|
|
(*it)->set_selected (false);
|
|
}
|
|
|
|
/* Mark compatibility for everything necessary */
|
|
|
|
std::set<ExportFormatBase::Quality> compatible_qualities;
|
|
ExportFormatBasePtr compat_intersect = get_compatibility_intersection ();
|
|
ExportFormatCompatibility global_compat (*compat_intersect);
|
|
|
|
for (FormatList::iterator it = formats.begin(); it != formats.end(); ++it) {
|
|
if ((*it)->set_compatibility_state (global_compat)) {
|
|
compatible_qualities.insert ((*it)->get_quality());
|
|
}
|
|
}
|
|
|
|
bool any_quality_compatible = true;
|
|
for (QualityList::iterator it = qualities.begin(); it != qualities.end(); ++it) {
|
|
if (compatible_qualities.find((*it)->quality) != compatible_qualities.end()) {
|
|
(*it)->set_compatible (true);
|
|
|
|
} else {
|
|
(*it)->set_compatible (false);
|
|
|
|
if ((*it)->quality != ExportFormatBase::Q_Any) {
|
|
any_quality_compatible = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (any_quality_compatible) {
|
|
for (QualityList::iterator it = qualities.begin(); it != qualities.end(); ++it) {
|
|
if ((*it)->quality == ExportFormatBase::Q_Any) {
|
|
(*it)->set_compatible (true);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (SampleRateList::iterator it = sample_rates.begin(); it != sample_rates.end(); ++it) {
|
|
if (compat_intersect->has_sample_rate ((*it)->rate)) {
|
|
(*it)->set_compatible (true);
|
|
} else {
|
|
(*it)->set_compatible (false);
|
|
}
|
|
}
|
|
|
|
boost::shared_ptr<HasSampleFormat> hsf;
|
|
if ((hsf = boost::dynamic_pointer_cast<HasSampleFormat> (get_selected_format()))) {
|
|
|
|
SampleFormatList sf_list = hsf->get_sample_formats();
|
|
for (SampleFormatList::iterator it = sf_list.begin(); it != sf_list.end(); ++it) {
|
|
if (compat_intersect->has_sample_format ((*it)->format)) {
|
|
(*it)->set_compatible (true);
|
|
} else {
|
|
(*it)->set_compatible (false);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/* Signal completeness and possible description change */
|
|
|
|
CompleteChanged (current_selection->is_complete());
|
|
check_for_description_change ();
|
|
|
|
/* Reset pending state */
|
|
|
|
pending_selection_change = false;
|
|
}
|
|
|
|
void
|
|
ExportFormatManager::check_for_description_change ()
|
|
{
|
|
std::string new_description = current_selection->description();
|
|
if (new_description == prev_description) { return; }
|
|
|
|
prev_description = new_description;
|
|
DescriptionChanged();
|
|
}
|
|
|
|
ExportFormatManager::QualityPtr
|
|
ExportFormatManager::get_selected_quality ()
|
|
{
|
|
for (QualityList::iterator it = qualities.begin(); it != qualities.end(); ++it) {
|
|
if ((*it)->selected()) {
|
|
return *it;
|
|
}
|
|
}
|
|
|
|
return QualityPtr();
|
|
}
|
|
|
|
ExportFormatPtr
|
|
ExportFormatManager::get_selected_format ()
|
|
{
|
|
ExportFormatPtr format;
|
|
|
|
for (FormatList::iterator it = formats.begin(); it != formats.end(); ++it) {
|
|
if ((*it)->selected()) {
|
|
return *it;
|
|
}
|
|
}
|
|
|
|
return format;
|
|
}
|
|
|
|
ExportFormatManager::SampleRatePtr
|
|
ExportFormatManager::get_selected_sample_rate ()
|
|
{
|
|
for (SampleRateList::iterator it = sample_rates.begin(); it != sample_rates.end(); ++it) {
|
|
if ((*it)->selected()) {
|
|
return *it;
|
|
}
|
|
}
|
|
|
|
return SampleRatePtr();
|
|
}
|
|
|
|
ExportFormatManager::SampleFormatPtr
|
|
ExportFormatManager::get_selected_sample_format ()
|
|
{
|
|
boost::shared_ptr<HasSampleFormat> hsf;
|
|
|
|
if ((hsf = boost::dynamic_pointer_cast<HasSampleFormat> (get_selected_format()))) {
|
|
return hsf->get_selected_sample_format ();
|
|
} else {
|
|
return SampleFormatPtr ();
|
|
}
|
|
}
|
|
|
|
|
|
ExportFormatBasePtr
|
|
ExportFormatManager::get_compatibility_intersection ()
|
|
{
|
|
ExportFormatBasePtr compat_intersect = universal_set;
|
|
|
|
for (CompatList::iterator it = compatibilities.begin(); it != compatibilities.end(); ++it) {
|
|
if ((*it)->selected ()) {
|
|
compat_intersect = compat_intersect->get_intersection (**it);
|
|
}
|
|
}
|
|
|
|
return compat_intersect;
|
|
}
|
|
|
|
}; // namespace ARDOUR
|