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"
34 ExportFormatManager::ExportFormatManager (ExportFormatSpecPtr specification) :
35 pending_selection_change (false),
36 universal_set (new ExportFormatBase ())
38 current_selection = specification;
40 init_compatibilities ();
46 ExportFormatManager::~ExportFormatManager ()
52 ExportFormatManager::init_compatibilities ()
54 ExportFormatCompatibilityPtr c_ptr;
56 c_ptr.reset (new ExportFormatCompatibility (_("CD")));
57 c_ptr->add_sample_rate (ExportFormatBase::SR_44_1);
58 c_ptr->add_format_id (ExportFormatBase::F_WAV);
59 c_ptr->add_format_id (ExportFormatBase::F_AIFF);
60 c_ptr->add_quality (ExportFormatBase::Q_LosslessLinear);
61 c_ptr->add_sample_format (ExportFormatBase::SF_16);
62 c_ptr->add_endianness (ExportFormatBase::E_FileDefault);
63 add_compatibility (c_ptr);
65 c_ptr.reset (new ExportFormatCompatibility (_("DVD-A")));
66 c_ptr->add_sample_rate (ExportFormatBase::SR_44_1);
67 c_ptr->add_sample_rate (ExportFormatBase::SR_48);
68 c_ptr->add_sample_rate (ExportFormatBase::SR_88_2);
69 c_ptr->add_sample_rate (ExportFormatBase::SR_96);
70 c_ptr->add_sample_rate (ExportFormatBase::SR_192);
71 c_ptr->add_format_id (ExportFormatBase::F_WAV);
72 c_ptr->add_format_id (ExportFormatBase::F_AIFF);
73 c_ptr->add_quality (ExportFormatBase::Q_LosslessLinear);
74 c_ptr->add_sample_format (ExportFormatBase::SF_16);
75 c_ptr->add_sample_format (ExportFormatBase::SF_24);
76 c_ptr->add_endianness (ExportFormatBase::E_FileDefault);
77 add_compatibility (c_ptr);
79 c_ptr.reset (new ExportFormatCompatibility (_("iPod")));
80 c_ptr->add_sample_rate (ExportFormatBase::SR_44_1);
81 c_ptr->add_sample_rate (ExportFormatBase::SR_48);
82 c_ptr->add_format_id (ExportFormatBase::F_WAV);
83 c_ptr->add_format_id (ExportFormatBase::F_AIFF);
84 c_ptr->add_quality (ExportFormatBase::Q_LosslessLinear);
85 c_ptr->add_sample_format (ExportFormatBase::SF_16);
86 c_ptr->add_sample_format (ExportFormatBase::SF_24);
87 c_ptr->add_endianness (ExportFormatBase::E_FileDefault);
88 add_compatibility (c_ptr);
90 c_ptr.reset (new ExportFormatCompatibility (_("Something else")));
91 c_ptr->add_sample_rate (ExportFormatBase::SR_44_1);
92 c_ptr->add_sample_rate (ExportFormatBase::SR_48);
93 c_ptr->add_format_id (ExportFormatBase::F_WAV);
94 c_ptr->add_format_id (ExportFormatBase::F_AIFF);
95 c_ptr->add_format_id (ExportFormatBase::F_AU);
96 c_ptr->add_format_id (ExportFormatBase::F_FLAC);
97 c_ptr->add_quality (ExportFormatBase::Q_LosslessLinear);
98 c_ptr->add_quality (ExportFormatBase::Q_LosslessCompression);
99 c_ptr->add_sample_format (ExportFormatBase::SF_16);
100 c_ptr->add_sample_format (ExportFormatBase::SF_24);
101 c_ptr->add_sample_format (ExportFormatBase::SF_32);
102 c_ptr->add_endianness (ExportFormatBase::E_FileDefault);
103 add_compatibility (c_ptr);
107 ExportFormatManager::init_qualities ()
109 add_quality (QualityPtr (new QualityState (ExportFormatBase::Q_Any, _("Any"))));
110 add_quality (QualityPtr (new QualityState (ExportFormatBase::Q_LosslessLinear, _("Lossless (linear PCM)"))));
111 add_quality (QualityPtr (new QualityState (ExportFormatBase::Q_LossyCompression, _("Lossy compression"))));
112 add_quality (QualityPtr (new QualityState (ExportFormatBase::Q_LosslessCompression, _("Lossless compression"))));
116 ExportFormatManager::init_formats ()
118 ExportFormatPtr f_ptr;
119 ExportFormatLinear * fl_ptr;
121 f_ptr.reset (fl_ptr = new ExportFormatLinear ("AIFF", ExportFormatBase::F_AIFF));
122 fl_ptr->add_sample_format (ExportFormatBase::SF_U8);
123 fl_ptr->add_sample_format (ExportFormatBase::SF_8);
124 fl_ptr->add_sample_format (ExportFormatBase::SF_16);
125 fl_ptr->add_sample_format (ExportFormatBase::SF_24);
126 fl_ptr->add_sample_format (ExportFormatBase::SF_32);
127 fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
128 fl_ptr->add_sample_format (ExportFormatBase::SF_Double);
129 fl_ptr->add_endianness (ExportFormatBase::E_Big);
130 fl_ptr->set_default_sample_format (ExportFormatBase::SF_16);
131 fl_ptr->set_extension ("aiff");
134 f_ptr.reset (fl_ptr = new ExportFormatLinear ("AU", ExportFormatBase::F_AU));
135 fl_ptr->add_sample_format (ExportFormatBase::SF_8);
136 fl_ptr->add_sample_format (ExportFormatBase::SF_16);
137 fl_ptr->add_sample_format (ExportFormatBase::SF_24);
138 fl_ptr->add_sample_format (ExportFormatBase::SF_32);
139 fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
140 fl_ptr->add_sample_format (ExportFormatBase::SF_Double);
141 fl_ptr->set_default_sample_format (ExportFormatBase::SF_16);
142 fl_ptr->set_extension ("au");
145 f_ptr.reset (new ExportFormatBWF ());
148 f_ptr.reset (fl_ptr = new ExportFormatLinear ("IRCAM", ExportFormatBase::F_IRCAM));
149 fl_ptr->add_sample_format (ExportFormatBase::SF_16);
150 fl_ptr->add_sample_format (ExportFormatBase::SF_24);
151 fl_ptr->add_sample_format (ExportFormatBase::SF_32);
152 fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
153 fl_ptr->set_default_sample_format (ExportFormatBase::SF_24);
154 fl_ptr->set_extension ("sf");
157 f_ptr.reset (fl_ptr = new ExportFormatLinear ("WAV", ExportFormatBase::F_WAV));
158 fl_ptr->add_sample_format (ExportFormatBase::SF_U8);
159 fl_ptr->add_sample_format (ExportFormatBase::SF_16);
160 fl_ptr->add_sample_format (ExportFormatBase::SF_24);
161 fl_ptr->add_sample_format (ExportFormatBase::SF_32);
162 fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
163 fl_ptr->add_sample_format (ExportFormatBase::SF_Double);
164 fl_ptr->add_endianness (ExportFormatBase::E_Little);
165 fl_ptr->set_default_sample_format (ExportFormatBase::SF_16);
166 fl_ptr->set_extension ("wav");
169 f_ptr.reset (fl_ptr = new ExportFormatLinear ("W64", ExportFormatBase::F_W64));
170 fl_ptr->add_sample_format (ExportFormatBase::SF_U8);
171 fl_ptr->add_sample_format (ExportFormatBase::SF_16);
172 fl_ptr->add_sample_format (ExportFormatBase::SF_24);
173 fl_ptr->add_sample_format (ExportFormatBase::SF_32);
174 fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
175 fl_ptr->add_sample_format (ExportFormatBase::SF_Double);
176 fl_ptr->set_default_sample_format (ExportFormatBase::SF_Double);
177 fl_ptr->set_extension ("w64");
180 f_ptr.reset (fl_ptr = new ExportFormatLinear ("RAW", ExportFormatBase::F_RAW));
181 fl_ptr->add_sample_format (ExportFormatBase::SF_U8);
182 fl_ptr->add_sample_format (ExportFormatBase::SF_8);
183 fl_ptr->add_sample_format (ExportFormatBase::SF_16);
184 fl_ptr->add_sample_format (ExportFormatBase::SF_24);
185 fl_ptr->add_sample_format (ExportFormatBase::SF_32);
186 fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
187 fl_ptr->add_sample_format (ExportFormatBase::SF_Double);
188 fl_ptr->set_default_sample_format (ExportFormatBase::SF_Float);
189 fl_ptr->set_extension ("raw");
193 f_ptr.reset (new ExportFormatOggVorbis ());
195 } catch (ExportFormatIncompatible & e) {}
198 f_ptr.reset (new ExportFormatFLAC ());
200 } catch (ExportFormatIncompatible & e) {}
204 ExportFormatManager::init_sample_rates ()
206 add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_Session, _("Session rate"))));
207 add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_22_05, "22,05 kHz")));
208 add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_44_1, "44,1 kHz")));
209 add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_48, "48 kHz")));
210 add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_88_2, "88,2 kHz")));
211 add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_96, "96 kHz")));
212 add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_192, "192 kHz")));
216 ExportFormatManager::add_compatibility (ExportFormatCompatibilityPtr ptr)
218 compatibilities.push_back (ptr);
219 ptr->SelectChanged.connect_same_thread (*this,
220 boost::bind (&ExportFormatManager::change_compatibility_selection,
221 this, _1, WeakExportFormatCompatibilityPtr (ptr)));
225 ExportFormatManager::add_quality (QualityPtr ptr)
227 ptr->SelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_quality_selection, this, _1, WeakQualityPtr (ptr)));
228 qualities.push_back (ptr);
232 ExportFormatManager::add_format (ExportFormatPtr ptr)
234 formats.push_back (ptr);
235 ptr->SelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_format_selection, this, _1, WeakExportFormatPtr (ptr)));
236 universal_set = universal_set->get_union (*ptr);
238 /* Encoding options */
240 boost::shared_ptr<HasSampleFormat> hsf;
242 if (hsf = boost::dynamic_pointer_cast<HasSampleFormat> (ptr)) {
243 hsf->SampleFormatSelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_sample_format_selection, this, _1, _2));
244 hsf->DitherTypeSelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_dither_type_selection, this, _1, _2));
249 ExportFormatManager::add_sample_rate (SampleRatePtr ptr)
251 ptr->SelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_sample_rate_selection, this, _1, WeakSampleRatePtr (ptr)));
252 sample_rates.push_back (ptr);
256 ExportFormatManager::set_name (string name)
258 current_selection->set_name (name);
262 ExportFormatManager::select_src_quality (ExportFormatBase::SRCQuality value)
264 current_selection->set_src_quality (value);
268 ExportFormatManager::select_with_cue (bool value)
270 current_selection->set_with_cue (value);
274 ExportFormatManager::select_with_toc (bool value)
276 current_selection->set_with_toc (value);
280 ExportFormatManager::select_trim_beginning (bool value)
282 current_selection->set_trim_beginning (value);
286 ExportFormatManager::select_silence_beginning (AnyTime const & time)
288 current_selection->set_silence_beginning (time);
292 ExportFormatManager::select_trim_end (bool value)
294 current_selection->set_trim_end (value);
298 ExportFormatManager::select_silence_end (AnyTime const & time)
300 current_selection->set_silence_end (time);
304 ExportFormatManager::select_normalize (bool value)
306 current_selection->set_normalize (value);
310 ExportFormatManager::select_normalize_target (float value)
312 current_selection->set_normalize_target (value);
316 ExportFormatManager::select_tagging (bool tag)
318 current_selection->set_tag (tag);
322 ExportFormatManager::change_compatibility_selection (bool select, WeakExportFormatCompatibilityPtr const & compat)
324 bool do_selection_changed = !pending_selection_change;
325 if (!pending_selection_change) {
326 pending_selection_change = true;
329 ExportFormatCompatibilityPtr ptr = compat.lock();
332 select_compatibility (ptr);
335 if (do_selection_changed) {
336 selection_changed ();
341 ExportFormatManager::change_quality_selection (bool select, WeakQualityPtr const & quality)
343 QualityPtr ptr = quality.lock ();
350 select_quality (ptr);
351 } else if (ptr->quality == current_selection->quality()) {
353 select_quality (ptr);
358 ExportFormatManager::change_format_selection (bool select, WeakExportFormatPtr const & format)
360 ExportFormatPtr ptr = format.lock();
368 } else if (ptr->get_format_id() == current_selection->format_id()) {
375 ExportFormatManager::change_sample_rate_selection (bool select, WeakSampleRatePtr const & rate)
377 SampleRatePtr ptr = rate.lock();
384 select_sample_rate (ptr);
385 } else if (ptr->rate == current_selection->sample_rate()) {
387 select_sample_rate (ptr);
392 ExportFormatManager::change_sample_format_selection (bool select, WeakSampleFormatPtr const & format)
394 SampleFormatPtr ptr = format.lock();
401 select_sample_format (ptr);
402 } else if (ptr->format == current_selection->sample_format()) {
404 select_sample_format (ptr);
409 ExportFormatManager::change_dither_type_selection (bool select, WeakDitherTypePtr const & type)
411 DitherTypePtr ptr = type.lock();
418 select_dither_type (ptr);
419 } else if (ptr->type == current_selection->dither_type()) {
421 select_dither_type (ptr);
426 ExportFormatManager::select_compatibility (WeakExportFormatCompatibilityPtr const & /*compat*/)
428 /* Calculate compatibility intersection for the selection */
430 ExportFormatBasePtr compat_intersect = get_compatibility_intersection ();
432 /* Unselect incompatible items */
434 boost::shared_ptr<ExportFormatBase> select_intersect;
436 select_intersect = compat_intersect->get_intersection (*current_selection);
437 if (select_intersect->qualities_empty()) {
438 select_quality (QualityPtr());
441 select_intersect = compat_intersect->get_intersection (*current_selection);
442 if (select_intersect->formats_empty()) {
443 select_format (ExportFormatPtr());
446 select_intersect = compat_intersect->get_intersection (*current_selection);
447 if (select_intersect->sample_rates_empty()) {
448 select_sample_rate (SampleRatePtr());
451 select_intersect = compat_intersect->get_intersection (*current_selection);
452 if (select_intersect->sample_formats_empty()) {
453 select_sample_format (SampleFormatPtr());
458 ExportFormatManager::select_quality (QualityPtr const & quality)
460 bool do_selection_changed = !pending_selection_change;
461 if (!pending_selection_change) {
462 pending_selection_change = true;
466 current_selection->set_quality (quality->quality);
468 /* Deselect format if it is incompatible */
470 ExportFormatPtr format = get_selected_format();
471 if (format && !format->has_quality (quality->quality)) {
472 format->set_selected (false);
476 current_selection->set_quality (ExportFormatBase::Q_None);
478 QualityPtr current_quality = get_selected_quality();
479 if (current_quality) {
480 current_quality->set_selected (false);
484 * A quality is never explicitly deselected without also deselecting the format
485 * so we don't need to deselect the format here.
486 * doing so causes extra complications
490 if (do_selection_changed) {
491 selection_changed ();
496 ExportFormatManager::select_format (ExportFormatPtr const & format)
498 bool do_selection_changed = !pending_selection_change;
499 if (!pending_selection_change) {
500 pending_selection_change = true;
503 current_selection->set_format (format);
507 /* Slect right quality for format */
509 ExportFormatBase::Quality quality = format->get_quality();
510 for (QualityList::iterator it = qualities.begin (); it != qualities.end (); ++it) {
511 if ((*it)->quality == quality) {
512 (*it)->set_selected (true);
514 (*it)->set_selected (false);
518 /* Handle sample formats */
520 ExportFormatBase::SampleFormat format_to_select;
521 if (format->sample_format_is_compatible (current_selection->sample_format())) {
522 format_to_select = current_selection->sample_format();
524 format_to_select = format->default_sample_format();
527 boost::shared_ptr<HasSampleFormat> hsf;
528 if ((hsf = boost::dynamic_pointer_cast<HasSampleFormat> (format))) {
529 SampleFormatList sample_formats = hsf->get_sample_formats();
530 for (SampleFormatList::iterator it = sample_formats.begin (); it != sample_formats.end (); ++it) {
531 if ((*it)->format == format_to_select) {
532 (*it)->set_selected (true);
534 (*it)->set_selected (false);
539 current_selection->set_sample_format (format_to_select);
542 ExportFormatPtr current_format = get_selected_format ();
543 if (current_format) {
544 current_format->set_selected (false);
548 if (do_selection_changed) {
549 selection_changed ();
554 ExportFormatManager::select_sample_rate (SampleRatePtr const & rate)
557 bool do_selection_changed = !pending_selection_change;
558 if (!pending_selection_change) {
559 pending_selection_change = true;
563 current_selection->set_sample_rate (rate->rate);
565 current_selection->set_sample_rate (ExportFormatBase::SR_None);
567 SampleRatePtr current_rate = get_selected_sample_rate();
569 current_rate->set_selected (false);
573 if (do_selection_changed) {
574 selection_changed ();
579 ExportFormatManager::select_sample_format (SampleFormatPtr const & format)
582 bool do_selection_changed = !pending_selection_change;
583 if (!pending_selection_change) {
584 pending_selection_change = true;
588 current_selection->set_sample_format (format->format);
590 current_selection->set_sample_format (ExportFormatBase::SF_None);
592 SampleFormatPtr current_format = get_selected_sample_format();
593 if (current_format) {
594 current_format->set_selected (false);
598 if (do_selection_changed) {
599 selection_changed ();
604 ExportFormatManager::select_dither_type (DitherTypePtr const & type)
607 bool do_selection_changed = !pending_selection_change;
608 if (!pending_selection_change) {
609 pending_selection_change = true;
613 current_selection->set_dither_type (type->type);
615 current_selection->set_dither_type (ExportFormatBase::D_None);
618 if (do_selection_changed) {
619 selection_changed ();
624 ExportFormatManager::selection_changed ()
626 /* Get a list of incompatible compatibility selections */
628 CompatList incompatibles;
629 for (CompatList::iterator it = compatibilities.begin(); it != compatibilities.end(); ++it) {
630 if (!current_selection->is_compatible_with (**it)) {
631 incompatibles.push_back (*it);
637 for (CompatList::iterator it = incompatibles.begin(); it != incompatibles.end(); ++it) {
638 (*it)->set_selected (false);
641 /* Mark compatibility for everything necessary */
643 std::set<ExportFormatBase::Quality> compatible_qualities;
644 ExportFormatBasePtr compat_intersect = get_compatibility_intersection ();
645 ExportFormatCompatibility global_compat (*compat_intersect);
647 for (FormatList::iterator it = formats.begin(); it != formats.end(); ++it) {
648 if ((*it)->set_compatibility_state (global_compat)) {
649 compatible_qualities.insert ((*it)->get_quality());
653 bool any_quality_compatible = true;
654 for (QualityList::iterator it = qualities.begin(); it != qualities.end(); ++it) {
655 if (compatible_qualities.find((*it)->quality) != compatible_qualities.end()) {
656 (*it)->set_compatible (true);
659 (*it)->set_compatible (false);
661 if ((*it)->quality != ExportFormatBase::Q_Any) {
662 any_quality_compatible = false;
667 if (any_quality_compatible) {
668 for (QualityList::iterator it = qualities.begin(); it != qualities.end(); ++it) {
669 if ((*it)->quality == ExportFormatBase::Q_Any) {
670 (*it)->set_compatible (true);
676 for (SampleRateList::iterator it = sample_rates.begin(); it != sample_rates.end(); ++it) {
677 if (compat_intersect->has_sample_rate ((*it)->rate)) {
678 (*it)->set_compatible (true);
680 (*it)->set_compatible (false);
684 boost::shared_ptr<HasSampleFormat> hsf;
685 if (hsf = boost::dynamic_pointer_cast<HasSampleFormat> (get_selected_format())) {
687 SampleFormatList sf_list = hsf->get_sample_formats();
688 for (SampleFormatList::iterator it = sf_list.begin(); it != sf_list.end(); ++it) {
689 if (compat_intersect->has_sample_format ((*it)->format)) {
690 (*it)->set_compatible (true);
692 (*it)->set_compatible (false);
698 /* Signal completeness */
700 CompleteChanged (current_selection->is_complete());
702 /* Reset pending state */
704 pending_selection_change = false;
707 ExportFormatManager::QualityPtr
708 ExportFormatManager::get_selected_quality ()
710 for (QualityList::iterator it = qualities.begin(); it != qualities.end(); ++it) {
711 if ((*it)->selected()) {
720 ExportFormatManager::get_selected_format ()
722 ExportFormatPtr format;
724 for (FormatList::iterator it = formats.begin(); it != formats.end(); ++it) {
725 if ((*it)->selected()) {
733 ExportFormatManager::SampleRatePtr
734 ExportFormatManager::get_selected_sample_rate ()
736 for (SampleRateList::iterator it = sample_rates.begin(); it != sample_rates.end(); ++it) {
737 if ((*it)->selected()) {
742 return SampleRatePtr();
745 ExportFormatManager::SampleFormatPtr
746 ExportFormatManager::get_selected_sample_format ()
748 boost::shared_ptr<HasSampleFormat> hsf;
750 if (hsf = boost::dynamic_pointer_cast<HasSampleFormat> (get_selected_format())) {
751 return hsf->get_selected_sample_format ();
753 return SampleFormatPtr ();
759 ExportFormatManager::get_compatibility_intersection ()
761 ExportFormatBasePtr compat_intersect = universal_set;
763 for (CompatList::iterator it = compatibilities.begin(); it != compatibilities.end(); ++it) {
764 if ((*it)->selected ()) {
765 compat_intersect = compat_intersect->get_intersection (**it);
769 return compat_intersect;
772 }; // namespace ARDOUR