2 Copyright (C) 2008 Paul Davis
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "ardour/export_format_manager.h"
23 #include "ardour/types.h"
24 #include "ardour/export_format_specification.h"
25 #include "ardour/export_format_compatibility.h"
32 ExportFormatManager::ExportFormatManager (SpecPtr specification) :
33 pending_selection_change (false),
34 universal_set (new ExportFormatBase ())
36 current_selection = specification;
38 init_compatibilities ();
44 ExportFormatManager::~ExportFormatManager ()
50 ExportFormatManager::init_compatibilities ()
54 c_ptr.reset (new ExportFormatCompatibility (_("CD")));
55 c_ptr->add_sample_rate (ExportFormatBase::SR_44_1);
56 c_ptr->add_format_id (ExportFormatBase::F_WAV);
57 c_ptr->add_format_id (ExportFormatBase::F_AIFF);
58 c_ptr->add_quality (ExportFormatBase::Q_LosslessLinear);
59 c_ptr->add_sample_format (ExportFormatBase::SF_16);
60 c_ptr->add_endianness (ExportFormatBase::E_FileDefault);
61 add_compatibility (c_ptr);
63 c_ptr.reset (new ExportFormatCompatibility (_("DVD-A")));
64 c_ptr->add_sample_rate (ExportFormatBase::SR_44_1);
65 c_ptr->add_sample_rate (ExportFormatBase::SR_48);
66 c_ptr->add_sample_rate (ExportFormatBase::SR_88_2);
67 c_ptr->add_sample_rate (ExportFormatBase::SR_96);
68 c_ptr->add_sample_rate (ExportFormatBase::SR_192);
69 c_ptr->add_format_id (ExportFormatBase::F_WAV);
70 c_ptr->add_format_id (ExportFormatBase::F_AIFF);
71 c_ptr->add_quality (ExportFormatBase::Q_LosslessLinear);
72 c_ptr->add_sample_format (ExportFormatBase::SF_16);
73 c_ptr->add_sample_format (ExportFormatBase::SF_24);
74 c_ptr->add_endianness (ExportFormatBase::E_FileDefault);
75 add_compatibility (c_ptr);
77 c_ptr.reset (new ExportFormatCompatibility (_("iPod")));
78 c_ptr->add_sample_rate (ExportFormatBase::SR_44_1);
79 c_ptr->add_sample_rate (ExportFormatBase::SR_48);
80 c_ptr->add_format_id (ExportFormatBase::F_WAV);
81 c_ptr->add_format_id (ExportFormatBase::F_AIFF);
82 c_ptr->add_quality (ExportFormatBase::Q_LosslessLinear);
83 c_ptr->add_sample_format (ExportFormatBase::SF_16);
84 c_ptr->add_sample_format (ExportFormatBase::SF_24);
85 c_ptr->add_endianness (ExportFormatBase::E_FileDefault);
86 add_compatibility (c_ptr);
88 c_ptr.reset (new ExportFormatCompatibility (_("Something else")));
89 c_ptr->add_sample_rate (ExportFormatBase::SR_44_1);
90 c_ptr->add_sample_rate (ExportFormatBase::SR_48);
91 c_ptr->add_format_id (ExportFormatBase::F_WAV);
92 c_ptr->add_format_id (ExportFormatBase::F_AIFF);
93 c_ptr->add_format_id (ExportFormatBase::F_AU);
94 c_ptr->add_format_id (ExportFormatBase::F_FLAC);
95 c_ptr->add_quality (ExportFormatBase::Q_LosslessLinear);
96 c_ptr->add_quality (ExportFormatBase::Q_LosslessCompression);
97 c_ptr->add_sample_format (ExportFormatBase::SF_16);
98 c_ptr->add_sample_format (ExportFormatBase::SF_24);
99 c_ptr->add_sample_format (ExportFormatBase::SF_32);
100 c_ptr->add_endianness (ExportFormatBase::E_FileDefault);
101 add_compatibility (c_ptr);
105 ExportFormatManager::init_qualities ()
107 add_quality (QualityPtr (new QualityState (ExportFormatBase::Q_Any, _("Any"))));
108 add_quality (QualityPtr (new QualityState (ExportFormatBase::Q_LosslessLinear, _("Lossless (linear PCM)"))));
109 add_quality (QualityPtr (new QualityState (ExportFormatBase::Q_LossyCompression, _("Lossy compression"))));
110 add_quality (QualityPtr (new QualityState (ExportFormatBase::Q_LosslessCompression, _("Lossless compression"))));
114 ExportFormatManager::init_formats ()
117 ExportFormatLinear * fl_ptr;
119 f_ptr.reset (fl_ptr = new ExportFormatLinear ("AIFF", ExportFormatBase::F_AIFF));
120 fl_ptr->add_sample_format (ExportFormatBase::SF_U8);
121 fl_ptr->add_sample_format (ExportFormatBase::SF_8);
122 fl_ptr->add_sample_format (ExportFormatBase::SF_16);
123 fl_ptr->add_sample_format (ExportFormatBase::SF_24);
124 fl_ptr->add_sample_format (ExportFormatBase::SF_32);
125 fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
126 fl_ptr->add_sample_format (ExportFormatBase::SF_Double);
127 fl_ptr->add_endianness (ExportFormatBase::E_Big);
128 fl_ptr->set_default_sample_format (ExportFormatBase::SF_16);
129 fl_ptr->set_extension ("aiff");
132 f_ptr.reset (fl_ptr = new ExportFormatLinear ("AU", ExportFormatBase::F_AU));
133 fl_ptr->add_sample_format (ExportFormatBase::SF_8);
134 fl_ptr->add_sample_format (ExportFormatBase::SF_16);
135 fl_ptr->add_sample_format (ExportFormatBase::SF_24);
136 fl_ptr->add_sample_format (ExportFormatBase::SF_32);
137 fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
138 fl_ptr->add_sample_format (ExportFormatBase::SF_Double);
139 fl_ptr->set_default_sample_format (ExportFormatBase::SF_16);
140 fl_ptr->set_extension ("au");
143 f_ptr.reset (new ExportFormatBWF ());
146 f_ptr.reset (fl_ptr = new ExportFormatLinear ("IRCAM", ExportFormatBase::F_IRCAM));
147 fl_ptr->add_sample_format (ExportFormatBase::SF_16);
148 fl_ptr->add_sample_format (ExportFormatBase::SF_24);
149 fl_ptr->add_sample_format (ExportFormatBase::SF_32);
150 fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
151 fl_ptr->set_default_sample_format (ExportFormatBase::SF_24);
152 fl_ptr->set_extension ("sf");
155 f_ptr.reset (fl_ptr = new ExportFormatLinear ("WAV", ExportFormatBase::F_WAV));
156 fl_ptr->add_sample_format (ExportFormatBase::SF_U8);
157 fl_ptr->add_sample_format (ExportFormatBase::SF_16);
158 fl_ptr->add_sample_format (ExportFormatBase::SF_24);
159 fl_ptr->add_sample_format (ExportFormatBase::SF_32);
160 fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
161 fl_ptr->add_sample_format (ExportFormatBase::SF_Double);
162 fl_ptr->add_endianness (ExportFormatBase::E_Little);
163 fl_ptr->set_default_sample_format (ExportFormatBase::SF_16);
164 fl_ptr->set_extension ("wav");
167 f_ptr.reset (fl_ptr = new ExportFormatLinear ("W64", ExportFormatBase::F_W64));
168 fl_ptr->add_sample_format (ExportFormatBase::SF_U8);
169 fl_ptr->add_sample_format (ExportFormatBase::SF_16);
170 fl_ptr->add_sample_format (ExportFormatBase::SF_24);
171 fl_ptr->add_sample_format (ExportFormatBase::SF_32);
172 fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
173 fl_ptr->add_sample_format (ExportFormatBase::SF_Double);
174 fl_ptr->set_default_sample_format (ExportFormatBase::SF_Double);
175 fl_ptr->set_extension ("w64");
178 f_ptr.reset (fl_ptr = new ExportFormatLinear ("RAW", ExportFormatBase::F_RAW));
179 fl_ptr->add_sample_format (ExportFormatBase::SF_U8);
180 fl_ptr->add_sample_format (ExportFormatBase::SF_8);
181 fl_ptr->add_sample_format (ExportFormatBase::SF_16);
182 fl_ptr->add_sample_format (ExportFormatBase::SF_24);
183 fl_ptr->add_sample_format (ExportFormatBase::SF_32);
184 fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
185 fl_ptr->add_sample_format (ExportFormatBase::SF_Double);
186 fl_ptr->set_default_sample_format (ExportFormatBase::SF_Float);
187 fl_ptr->set_extension ("raw");
191 f_ptr.reset (new ExportFormatOggVorbis ());
193 } catch (ExportFormatIncompatible & e) {}
196 f_ptr.reset (new ExportFormatFLAC ());
198 } catch (ExportFormatIncompatible & e) {}
202 ExportFormatManager::init_sample_rates ()
204 add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_22_05, "22,05 kHz")));
205 add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_44_1, "44,1 kHz")));
206 add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_48, "48 kHz")));
207 add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_88_2, "88,2 kHz")));
208 add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_96, "96 kHz")));
209 add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_192, "192 kHz")));
213 ExportFormatManager::add_compatibility (CompatPtr ptr)
215 compatibilities.push_back (ptr);
216 ptr->SelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_compatibility_selection, this, _1, WeakCompatPtr (ptr)));
220 ExportFormatManager::add_quality (QualityPtr ptr)
222 ptr->SelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_quality_selection, this, _1, WeakQualityPtr (ptr)));
223 qualities.push_back (ptr);
227 ExportFormatManager::add_format (FormatPtr ptr)
229 formats.push_back (ptr);
230 ptr->SelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_format_selection, this, _1, WeakFormatPtr (ptr)));
231 universal_set = universal_set->get_union (*ptr);
233 /* Encoding options */
235 boost::shared_ptr<HasSampleFormat> hsf;
237 if (hsf = boost::dynamic_pointer_cast<HasSampleFormat> (ptr)) {
238 hsf->SampleFormatSelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_sample_format_selection, this, _1, _2));
239 hsf->DitherTypeSelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_dither_type_selection, this, _1, _2));
244 ExportFormatManager::add_sample_rate (SampleRatePtr ptr)
246 ptr->SelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_sample_rate_selection, this, _1, WeakSampleRatePtr (ptr)));
247 sample_rates.push_back (ptr);
251 ExportFormatManager::set_name (Glib::ustring name)
253 current_selection->set_name (name);
257 ExportFormatManager::select_src_quality (ExportFormatBase::SRCQuality value)
259 current_selection->set_src_quality (value);
263 ExportFormatManager::select_trim_beginning (bool value)
265 current_selection->set_trim_beginning (value);
269 ExportFormatManager::select_silence_beginning (AnyTime const & time)
271 current_selection->set_silence_beginning (time);
275 ExportFormatManager::select_trim_end (bool value)
277 current_selection->set_trim_end (value);
281 ExportFormatManager::select_silence_end (AnyTime const & time)
283 current_selection->set_silence_end (time);
287 ExportFormatManager::select_normalize (bool value)
289 current_selection->set_normalize (value);
293 ExportFormatManager::select_normalize_target (float value)
295 current_selection->set_normalize_target (value);
299 ExportFormatManager::select_tagging (bool tag)
301 current_selection->set_tag (tag);
305 ExportFormatManager::change_compatibility_selection (bool select, WeakCompatPtr const & compat)
307 bool do_selection_changed = !pending_selection_change;
308 if (!pending_selection_change) {
309 pending_selection_change = true;
312 CompatPtr ptr = compat.lock();
315 select_compatibility (ptr);
318 if (do_selection_changed) {
319 selection_changed ();
324 ExportFormatManager::change_quality_selection (bool select, WeakQualityPtr const & quality)
326 QualityPtr ptr = quality.lock ();
333 select_quality (ptr);
334 } else if (ptr->quality == current_selection->quality()) {
336 select_quality (ptr);
341 ExportFormatManager::change_format_selection (bool select, WeakFormatPtr const & format)
343 FormatPtr ptr = format.lock();
351 } else if (ptr->get_format_id() == current_selection->format_id()) {
358 ExportFormatManager::change_sample_rate_selection (bool select, WeakSampleRatePtr const & rate)
360 SampleRatePtr ptr = rate.lock();
367 select_sample_rate (ptr);
368 } else if (ptr->rate == current_selection->sample_rate()) {
370 select_sample_rate (ptr);
375 ExportFormatManager::change_sample_format_selection (bool select, WeakSampleFormatPtr const & format)
377 SampleFormatPtr ptr = format.lock();
384 select_sample_format (ptr);
385 } else if (ptr->format == current_selection->sample_format()) {
387 select_sample_format (ptr);
392 ExportFormatManager::change_dither_type_selection (bool select, WeakDitherTypePtr const & type)
394 DitherTypePtr ptr = type.lock();
401 select_dither_type (ptr);
402 } else if (ptr->type == current_selection->dither_type()) {
404 select_dither_type (ptr);
409 ExportFormatManager::select_compatibility (WeakCompatPtr const & /*compat*/)
411 /* Calculate compatibility intersection for the selection */
413 FormatBasePtr compat_intersect = get_compatibility_intersection ();
415 /* Unselect incompatible items */
417 boost::shared_ptr<ExportFormatBase> select_intersect;
419 select_intersect = compat_intersect->get_intersection (*current_selection);
420 if (select_intersect->qualities_empty()) {
421 select_quality (QualityPtr());
424 select_intersect = compat_intersect->get_intersection (*current_selection);
425 if (select_intersect->formats_empty()) {
426 select_format (FormatPtr());
429 select_intersect = compat_intersect->get_intersection (*current_selection);
430 if (select_intersect->sample_rates_empty()) {
431 select_sample_rate (SampleRatePtr());
434 select_intersect = compat_intersect->get_intersection (*current_selection);
435 if (select_intersect->sample_formats_empty()) {
436 select_sample_format (SampleFormatPtr());
441 ExportFormatManager::select_quality (QualityPtr const & quality)
443 bool do_selection_changed = !pending_selection_change;
444 if (!pending_selection_change) {
445 pending_selection_change = true;
449 current_selection->set_quality (quality->quality);
451 /* Deselect format if it is incompatible */
453 FormatPtr format = get_selected_format();
454 if (format && !format->has_quality (quality->quality)) {
455 format->set_selected (false);
459 current_selection->set_quality (ExportFormatBase::Q_None);
461 QualityPtr current_quality = get_selected_quality();
462 if (current_quality) {
463 current_quality->set_selected (false);
467 * A quality is never explicitly deselected without also deselecting the format
468 * so we don't need to deselect the format here.
469 * doing so causes extra complications
473 if (do_selection_changed) {
474 selection_changed ();
479 ExportFormatManager::select_format (FormatPtr const & format)
481 bool do_selection_changed = !pending_selection_change;
482 if (!pending_selection_change) {
483 pending_selection_change = true;
486 current_selection->set_format (format);
490 /* Slect right quality for format */
492 ExportFormatBase::Quality quality = format->get_quality();
493 for (QualityList::iterator it = qualities.begin (); it != qualities.end (); ++it) {
494 if ((*it)->quality == quality) {
495 (*it)->set_selected (true);
497 (*it)->set_selected (false);
501 /* Handle sample formats */
503 ExportFormatBase::SampleFormat format_to_select;
504 if (format->sample_format_is_compatible (current_selection->sample_format())) {
505 format_to_select = current_selection->sample_format();
507 format_to_select = format->default_sample_format();
510 boost::shared_ptr<HasSampleFormat> hsf;
511 if ((hsf = boost::dynamic_pointer_cast<HasSampleFormat> (format))) {
512 SampleFormatList sample_formats = hsf->get_sample_formats();
513 for (SampleFormatList::iterator it = sample_formats.begin (); it != sample_formats.end (); ++it) {
514 if ((*it)->format == format_to_select) {
515 (*it)->set_selected (true);
517 (*it)->set_selected (false);
522 current_selection->set_sample_format (format_to_select);
525 FormatPtr current_format = get_selected_format ();
526 if (current_format) {
527 current_format->set_selected (false);
531 if (do_selection_changed) {
532 selection_changed ();
537 ExportFormatManager::select_sample_rate (SampleRatePtr const & rate)
540 bool do_selection_changed = !pending_selection_change;
541 if (!pending_selection_change) {
542 pending_selection_change = true;
546 current_selection->set_sample_rate (rate->rate);
548 current_selection->set_sample_rate (ExportFormatBase::SR_None);
550 SampleRatePtr current_rate = get_selected_sample_rate();
552 current_rate->set_selected (false);
556 if (do_selection_changed) {
557 selection_changed ();
562 ExportFormatManager::select_sample_format (SampleFormatPtr const & format)
565 bool do_selection_changed = !pending_selection_change;
566 if (!pending_selection_change) {
567 pending_selection_change = true;
571 current_selection->set_sample_format (format->format);
573 current_selection->set_sample_format (ExportFormatBase::SF_None);
575 SampleFormatPtr current_format = get_selected_sample_format();
576 if (current_format) {
577 current_format->set_selected (false);
581 if (do_selection_changed) {
582 selection_changed ();
587 ExportFormatManager::select_dither_type (DitherTypePtr const & type)
590 bool do_selection_changed = !pending_selection_change;
591 if (!pending_selection_change) {
592 pending_selection_change = true;
596 current_selection->set_dither_type (type->type);
598 current_selection->set_dither_type (ExportFormatBase::D_None);
601 if (do_selection_changed) {
602 selection_changed ();
607 ExportFormatManager::selection_changed ()
609 /* Get a list of incompatible compatibility selections */
611 CompatList incompatibles;
612 for (CompatList::iterator it = compatibilities.begin(); it != compatibilities.end(); ++it) {
613 if (!current_selection->is_compatible_with (**it)) {
614 incompatibles.push_back (*it);
620 for (CompatList::iterator it = incompatibles.begin(); it != incompatibles.end(); ++it) {
621 (*it)->set_selected (false);
624 /* Mark compatibility for everything necessary */
626 std::set<ExportFormatBase::Quality> compatible_qualities;
627 FormatBasePtr compat_intersect = get_compatibility_intersection ();
628 ExportFormatCompatibility global_compat (*compat_intersect);
630 for (FormatList::iterator it = formats.begin(); it != formats.end(); ++it) {
631 if ((*it)->set_compatibility_state (global_compat)) {
632 compatible_qualities.insert ((*it)->get_quality());
636 bool any_quality_compatible = true;
637 for (QualityList::iterator it = qualities.begin(); it != qualities.end(); ++it) {
638 if (compatible_qualities.find((*it)->quality) != compatible_qualities.end()) {
639 (*it)->set_compatible (true);
642 (*it)->set_compatible (false);
644 if ((*it)->quality != ExportFormatBase::Q_Any) {
645 any_quality_compatible = false;
650 if (any_quality_compatible) {
651 for (QualityList::iterator it = qualities.begin(); it != qualities.end(); ++it) {
652 if ((*it)->quality == ExportFormatBase::Q_Any) {
653 (*it)->set_compatible (true);
659 for (SampleRateList::iterator it = sample_rates.begin(); it != sample_rates.end(); ++it) {
660 if (compat_intersect->has_sample_rate ((*it)->rate)) {
661 (*it)->set_compatible (true);
663 (*it)->set_compatible (false);
667 boost::shared_ptr<HasSampleFormat> hsf;
668 if (hsf = boost::dynamic_pointer_cast<HasSampleFormat> (get_selected_format())) {
670 SampleFormatList sf_list = hsf->get_sample_formats();
671 for (SampleFormatList::iterator it = sf_list.begin(); it != sf_list.end(); ++it) {
672 if (compat_intersect->has_sample_format ((*it)->format)) {
673 (*it)->set_compatible (true);
675 (*it)->set_compatible (false);
681 /* Signal completeness */
683 CompleteChanged (current_selection->is_complete());
685 /* Reset pending state */
687 pending_selection_change = false;
690 ExportFormatManager::QualityPtr
691 ExportFormatManager::get_selected_quality ()
693 for (QualityList::iterator it = qualities.begin(); it != qualities.end(); ++it) {
694 if ((*it)->selected()) {
702 ExportFormatManager::FormatPtr
703 ExportFormatManager::get_selected_format ()
707 for (FormatList::iterator it = formats.begin(); it != formats.end(); ++it) {
708 if ((*it)->selected()) {
716 ExportFormatManager::SampleRatePtr
717 ExportFormatManager::get_selected_sample_rate ()
719 for (SampleRateList::iterator it = sample_rates.begin(); it != sample_rates.end(); ++it) {
720 if ((*it)->selected()) {
725 return SampleRatePtr();
728 ExportFormatManager::SampleFormatPtr
729 ExportFormatManager::get_selected_sample_format ()
731 boost::shared_ptr<HasSampleFormat> hsf;
733 if (hsf = boost::dynamic_pointer_cast<HasSampleFormat> (get_selected_format())) {
734 return hsf->get_selected_sample_format ();
736 return SampleFormatPtr ();
741 ExportFormatManager::FormatBasePtr
742 ExportFormatManager::get_compatibility_intersection ()
744 FormatBasePtr compat_intersect = universal_set;
746 for (CompatList::iterator it = compatibilities.begin(); it != compatibilities.end(); ++it) {
747 if ((*it)->selected ()) {
748 compat_intersect = compat_intersect->get_intersection (**it);
752 return compat_intersect;
755 }; // namespace ARDOUR