Inrease the export "chunk size" to speed it up over 10% at least in some situations
[ardour.git] / libs / ardour / export_format_manager.cc
1 /*
2     Copyright (C) 2008 Paul Davis
3     Author: Sakari Bergen
4
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.
9
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.
14
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.
18
19 */
20
21 #include "ardour/export_format_manager.h"
22
23 #include "ardour/export_format_specification.h"
24 #include "ardour/export_format_compatibility.h"
25
26 #include "i18n.h"
27
28 using std::string;
29
30 namespace ARDOUR
31 {
32
33 ExportFormatManager::ExportFormatManager (ExportFormatSpecPtr specification) :
34   pending_selection_change (false),
35   universal_set (new ExportFormatBase ())
36 {
37         current_selection = specification;
38
39         init_compatibilities ();
40         init_qualities ();
41         init_formats ();
42         init_sample_rates ();
43
44         prev_description = current_selection->description();
45 }
46
47 ExportFormatManager::~ExportFormatManager ()
48 {
49
50 }
51
52 void
53 ExportFormatManager::init_compatibilities ()
54 {
55         ExportFormatCompatibilityPtr c_ptr;
56
57         c_ptr.reset (new ExportFormatCompatibility (_("CD")));
58         c_ptr->add_sample_rate (ExportFormatBase::SR_44_1);
59         c_ptr->add_format_id (ExportFormatBase::F_WAV);
60         c_ptr->add_format_id (ExportFormatBase::F_AIFF);
61         c_ptr->add_quality (ExportFormatBase::Q_LosslessLinear);
62         c_ptr->add_sample_format (ExportFormatBase::SF_16);
63         c_ptr->add_endianness (ExportFormatBase::E_FileDefault);
64         add_compatibility (c_ptr);
65
66         c_ptr.reset (new ExportFormatCompatibility (_("DVD-A")));
67         c_ptr->add_sample_rate (ExportFormatBase::SR_44_1);
68         c_ptr->add_sample_rate (ExportFormatBase::SR_48);
69         c_ptr->add_sample_rate (ExportFormatBase::SR_88_2);
70         c_ptr->add_sample_rate (ExportFormatBase::SR_96);
71         c_ptr->add_sample_rate (ExportFormatBase::SR_192);
72         c_ptr->add_format_id (ExportFormatBase::F_WAV);
73         c_ptr->add_format_id (ExportFormatBase::F_AIFF);
74         c_ptr->add_quality (ExportFormatBase::Q_LosslessLinear);
75         c_ptr->add_sample_format (ExportFormatBase::SF_16);
76         c_ptr->add_sample_format (ExportFormatBase::SF_24);
77         c_ptr->add_endianness (ExportFormatBase::E_FileDefault);
78         add_compatibility (c_ptr);
79
80         c_ptr.reset (new ExportFormatCompatibility (_("iPod")));
81         c_ptr->add_sample_rate (ExportFormatBase::SR_44_1);
82         c_ptr->add_sample_rate (ExportFormatBase::SR_48);
83         c_ptr->add_format_id (ExportFormatBase::F_WAV);
84         c_ptr->add_format_id (ExportFormatBase::F_AIFF);
85         c_ptr->add_quality (ExportFormatBase::Q_LosslessLinear);
86         c_ptr->add_sample_format (ExportFormatBase::SF_16);
87         c_ptr->add_sample_format (ExportFormatBase::SF_24);
88         c_ptr->add_endianness (ExportFormatBase::E_FileDefault);
89         add_compatibility (c_ptr);
90
91         c_ptr.reset (new ExportFormatCompatibility (_("Something else")));
92         c_ptr->add_sample_rate (ExportFormatBase::SR_44_1);
93         c_ptr->add_sample_rate (ExportFormatBase::SR_48);
94         c_ptr->add_format_id (ExportFormatBase::F_WAV);
95         c_ptr->add_format_id (ExportFormatBase::F_AIFF);
96         c_ptr->add_format_id (ExportFormatBase::F_AU);
97         c_ptr->add_format_id (ExportFormatBase::F_FLAC);
98         c_ptr->add_quality (ExportFormatBase::Q_LosslessLinear);
99         c_ptr->add_quality (ExportFormatBase::Q_LosslessCompression);
100         c_ptr->add_sample_format (ExportFormatBase::SF_16);
101         c_ptr->add_sample_format (ExportFormatBase::SF_24);
102         c_ptr->add_sample_format (ExportFormatBase::SF_32);
103         c_ptr->add_endianness (ExportFormatBase::E_FileDefault);
104         add_compatibility (c_ptr);
105 }
106
107 void
108 ExportFormatManager::init_qualities ()
109 {
110         add_quality (QualityPtr (new QualityState (ExportFormatBase::Q_Any, _("Any"))));
111         add_quality (QualityPtr (new QualityState (ExportFormatBase::Q_LosslessLinear, _("Lossless (linear PCM)"))));
112         add_quality (QualityPtr (new QualityState (ExportFormatBase::Q_LossyCompression, _("Lossy compression"))));
113         add_quality (QualityPtr (new QualityState (ExportFormatBase::Q_LosslessCompression, _("Lossless compression"))));
114 }
115
116 void
117 ExportFormatManager::init_formats ()
118 {
119         ExportFormatPtr f_ptr;
120         ExportFormatLinear * fl_ptr;
121
122         f_ptr.reset (fl_ptr = new ExportFormatLinear ("AIFF", ExportFormatBase::F_AIFF));
123         fl_ptr->add_sample_format (ExportFormatBase::SF_U8);
124         fl_ptr->add_sample_format (ExportFormatBase::SF_8);
125         fl_ptr->add_sample_format (ExportFormatBase::SF_16);
126         fl_ptr->add_sample_format (ExportFormatBase::SF_24);
127         fl_ptr->add_sample_format (ExportFormatBase::SF_32);
128         fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
129         fl_ptr->add_sample_format (ExportFormatBase::SF_Double);
130         fl_ptr->add_endianness (ExportFormatBase::E_Big);
131         fl_ptr->set_default_sample_format (ExportFormatBase::SF_16);
132         fl_ptr->set_extension ("aiff");
133         add_format (f_ptr);
134
135         f_ptr.reset (fl_ptr = new ExportFormatLinear ("AU", ExportFormatBase::F_AU));
136         fl_ptr->add_sample_format (ExportFormatBase::SF_8);
137         fl_ptr->add_sample_format (ExportFormatBase::SF_16);
138         fl_ptr->add_sample_format (ExportFormatBase::SF_24);
139         fl_ptr->add_sample_format (ExportFormatBase::SF_32);
140         fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
141         fl_ptr->add_sample_format (ExportFormatBase::SF_Double);
142         fl_ptr->set_default_sample_format (ExportFormatBase::SF_16);
143         fl_ptr->set_extension ("au");
144         add_format (f_ptr);
145
146         f_ptr.reset (new ExportFormatBWF ());
147         add_format (f_ptr);
148
149         f_ptr.reset (fl_ptr = new ExportFormatLinear ("IRCAM", ExportFormatBase::F_IRCAM));
150         fl_ptr->add_sample_format (ExportFormatBase::SF_16);
151         fl_ptr->add_sample_format (ExportFormatBase::SF_24);
152         fl_ptr->add_sample_format (ExportFormatBase::SF_32);
153         fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
154         fl_ptr->set_default_sample_format (ExportFormatBase::SF_24);
155         fl_ptr->set_extension ("sf");
156         add_format (f_ptr);
157
158         f_ptr.reset (fl_ptr = new ExportFormatLinear ("WAV", ExportFormatBase::F_WAV));
159         fl_ptr->add_sample_format (ExportFormatBase::SF_U8);
160         fl_ptr->add_sample_format (ExportFormatBase::SF_16);
161         fl_ptr->add_sample_format (ExportFormatBase::SF_24);
162         fl_ptr->add_sample_format (ExportFormatBase::SF_32);
163         fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
164         fl_ptr->add_sample_format (ExportFormatBase::SF_Double);
165         fl_ptr->add_endianness (ExportFormatBase::E_Little);
166         fl_ptr->set_default_sample_format (ExportFormatBase::SF_16);
167         fl_ptr->set_extension ("wav");
168         add_format (f_ptr);
169
170         f_ptr.reset (fl_ptr = new ExportFormatLinear ("W64", ExportFormatBase::F_W64));
171         fl_ptr->add_sample_format (ExportFormatBase::SF_U8);
172         fl_ptr->add_sample_format (ExportFormatBase::SF_16);
173         fl_ptr->add_sample_format (ExportFormatBase::SF_24);
174         fl_ptr->add_sample_format (ExportFormatBase::SF_32);
175         fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
176         fl_ptr->add_sample_format (ExportFormatBase::SF_Double);
177         fl_ptr->set_default_sample_format (ExportFormatBase::SF_Double);
178         fl_ptr->set_extension ("w64");
179         add_format (f_ptr);
180
181         f_ptr.reset (fl_ptr = new ExportFormatLinear ("RAW", ExportFormatBase::F_RAW));
182         fl_ptr->add_sample_format (ExportFormatBase::SF_U8);
183         fl_ptr->add_sample_format (ExportFormatBase::SF_8);
184         fl_ptr->add_sample_format (ExportFormatBase::SF_16);
185         fl_ptr->add_sample_format (ExportFormatBase::SF_24);
186         fl_ptr->add_sample_format (ExportFormatBase::SF_32);
187         fl_ptr->add_sample_format (ExportFormatBase::SF_Float);
188         fl_ptr->add_sample_format (ExportFormatBase::SF_Double);
189         fl_ptr->set_default_sample_format (ExportFormatBase::SF_Float);
190         fl_ptr->set_extension ("raw");
191         add_format (f_ptr);
192
193         try {
194                 f_ptr.reset (new ExportFormatOggVorbis ());
195                 add_format (f_ptr);
196         } catch (ExportFormatIncompatible & e) {}
197
198         try {
199                 f_ptr.reset (new ExportFormatFLAC ());
200                 add_format (f_ptr);
201         } catch (ExportFormatIncompatible & e) {}
202 }
203
204 void
205 ExportFormatManager::init_sample_rates ()
206 {
207         add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_Session, _("Session rate"))));
208         add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_22_05, "22,05 kHz")));
209         add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_44_1, "44,1 kHz")));
210         add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_48, "48 kHz")));
211         add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_88_2, "88,2 kHz")));
212         add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_96, "96 kHz")));
213         add_sample_rate (SampleRatePtr (new SampleRateState (ExportFormatBase::SR_192, "192 kHz")));
214 }
215
216 void
217 ExportFormatManager::add_compatibility (ExportFormatCompatibilityPtr ptr)
218 {
219         compatibilities.push_back (ptr);
220         ptr->SelectChanged.connect_same_thread (*this,
221                                                 boost::bind (&ExportFormatManager::change_compatibility_selection,
222                                                              this, _1, WeakExportFormatCompatibilityPtr (ptr)));
223 }
224
225 void
226 ExportFormatManager::add_quality (QualityPtr ptr)
227 {
228         ptr->SelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_quality_selection, this, _1, WeakQualityPtr (ptr)));
229         qualities.push_back (ptr);
230 }
231
232 void
233 ExportFormatManager::add_format (ExportFormatPtr ptr)
234 {
235         formats.push_back (ptr);
236         ptr->SelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_format_selection, this, _1, WeakExportFormatPtr (ptr)));
237         universal_set = universal_set->get_union (*ptr);
238
239         /* Encoding options */
240
241         boost::shared_ptr<HasSampleFormat> hsf;
242
243         if ((hsf = boost::dynamic_pointer_cast<HasSampleFormat> (ptr))) {
244                 hsf->SampleFormatSelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_sample_format_selection, this, _1, _2));
245                 hsf->DitherTypeSelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_dither_type_selection, this, _1, _2));
246         }
247 }
248
249 void
250 ExportFormatManager::add_sample_rate (SampleRatePtr ptr)
251 {
252         ptr->SelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_sample_rate_selection, this, _1, WeakSampleRatePtr (ptr)));
253         sample_rates.push_back (ptr);
254 }
255
256 void
257 ExportFormatManager::set_name (string name)
258 {
259         current_selection->set_name (name);
260         check_for_description_change ();
261 }
262
263 void
264 ExportFormatManager::select_src_quality (ExportFormatBase::SRCQuality value)
265 {
266         current_selection->set_src_quality (value);
267         check_for_description_change ();
268 }
269
270 void
271 ExportFormatManager::select_with_cue (bool value)
272 {
273         current_selection->set_with_cue (value);
274         check_for_description_change ();
275 }
276
277 void
278 ExportFormatManager::select_with_toc (bool value)
279 {
280         current_selection->set_with_toc (value);
281         check_for_description_change ();
282 }
283
284 void
285 ExportFormatManager::select_trim_beginning (bool value)
286 {
287         current_selection->set_trim_beginning (value);
288         check_for_description_change ();
289 }
290
291 void
292 ExportFormatManager::select_silence_beginning (AnyTime const & time)
293 {
294         current_selection->set_silence_beginning (time);
295         check_for_description_change ();
296 }
297
298 void
299 ExportFormatManager::select_trim_end (bool value)
300 {
301         current_selection->set_trim_end (value);
302         check_for_description_change ();
303 }
304
305 void
306 ExportFormatManager::select_silence_end (AnyTime const & time)
307 {
308         current_selection->set_silence_end (time);
309         check_for_description_change ();
310 }
311
312 void
313 ExportFormatManager::select_normalize (bool value)
314 {
315         current_selection->set_normalize (value);
316         check_for_description_change ();
317 }
318
319 void
320 ExportFormatManager::select_normalize_target (float value)
321 {
322         current_selection->set_normalize_target (value);
323         check_for_description_change ();
324 }
325
326 void
327 ExportFormatManager::select_tagging (bool tag)
328 {
329         current_selection->set_tag (tag);
330         check_for_description_change ();
331 }
332
333 void
334 ExportFormatManager::change_compatibility_selection (bool select, WeakExportFormatCompatibilityPtr const & compat)
335 {
336         bool do_selection_changed = !pending_selection_change;
337         if (!pending_selection_change) {
338                 pending_selection_change = true;
339         }
340
341         ExportFormatCompatibilityPtr ptr = compat.lock();
342
343         if (ptr && select) {
344                 select_compatibility (ptr);
345         }
346
347         if (do_selection_changed) {
348                 selection_changed ();
349         }
350 }
351
352 void
353 ExportFormatManager::change_quality_selection (bool select, WeakQualityPtr const & quality)
354 {
355         QualityPtr ptr = quality.lock ();
356
357         if (!ptr) {
358                 return;
359         }
360
361         if (select) {
362                 select_quality (ptr);
363         } else if (ptr->quality == current_selection->quality()) {
364                 ptr.reset();
365                 select_quality (ptr);
366         }
367 }
368
369 void
370 ExportFormatManager::change_format_selection (bool select, WeakExportFormatPtr const & format)
371 {
372         ExportFormatPtr ptr = format.lock();
373
374         if (!ptr) {
375                 return;
376         }
377
378         if (select) {
379                 select_format (ptr);
380         } else if (ptr->get_format_id() == current_selection->format_id()) {
381                 ptr.reset();
382                 select_format (ptr);
383         }
384 }
385
386 void
387 ExportFormatManager::change_sample_rate_selection (bool select, WeakSampleRatePtr const & rate)
388 {
389         SampleRatePtr ptr = rate.lock();
390
391         if (!ptr) {
392                 return;
393         }
394
395         if (select) {
396                 select_sample_rate (ptr);
397         } else if (ptr->rate == current_selection->sample_rate()) {
398                 ptr.reset();
399                 select_sample_rate (ptr);
400         }
401 }
402
403 void
404 ExportFormatManager::change_sample_format_selection (bool select, WeakSampleFormatPtr const & format)
405 {
406         SampleFormatPtr ptr = format.lock();
407
408         if (!ptr) {
409                 return;
410         }
411
412         if (select) {
413                 select_sample_format (ptr);
414         } else if (ptr->format == current_selection->sample_format()) {
415                 ptr.reset();
416                 select_sample_format (ptr);
417         }
418 }
419
420 void
421 ExportFormatManager::change_dither_type_selection (bool select, WeakDitherTypePtr const & type)
422 {
423         DitherTypePtr ptr = type.lock();
424
425         if (!ptr) {
426                 return;
427         }
428
429         if (select) {
430                 select_dither_type (ptr);
431         } else if (ptr->type == current_selection->dither_type()) {
432                 ptr.reset();
433                 select_dither_type (ptr);
434         }
435 }
436
437 void
438 ExportFormatManager::select_compatibility (WeakExportFormatCompatibilityPtr const & /*compat*/)
439 {
440         /* Calculate compatibility intersection for the selection */
441
442         ExportFormatBasePtr compat_intersect = get_compatibility_intersection ();
443
444         /* Unselect incompatible items */
445
446         boost::shared_ptr<ExportFormatBase> select_intersect;
447
448         select_intersect = compat_intersect->get_intersection (*current_selection);
449         if (select_intersect->qualities_empty()) {
450                 select_quality (QualityPtr());
451         }
452
453         select_intersect = compat_intersect->get_intersection (*current_selection);
454         if (select_intersect->formats_empty()) {
455                 select_format (ExportFormatPtr());
456         }
457
458         select_intersect = compat_intersect->get_intersection (*current_selection);
459         if (select_intersect->sample_rates_empty()) {
460                 select_sample_rate (SampleRatePtr());
461         }
462
463         select_intersect = compat_intersect->get_intersection (*current_selection);
464         if (select_intersect->sample_formats_empty()) {
465                 select_sample_format (SampleFormatPtr());
466         }
467 }
468
469 void
470 ExportFormatManager::select_quality (QualityPtr const & quality)
471 {
472         bool do_selection_changed = !pending_selection_change;
473         if (!pending_selection_change) {
474                 pending_selection_change = true;
475         }
476
477         if (quality) {
478                 current_selection->set_quality (quality->quality);
479
480                 /* Deselect format if it is incompatible */
481
482                 ExportFormatPtr format = get_selected_format();
483                 if (format && !format->has_quality (quality->quality)) {
484                         format->set_selected (false);
485                 }
486
487         } else {
488                 current_selection->set_quality (ExportFormatBase::Q_None);
489
490                 QualityPtr current_quality = get_selected_quality();
491                 if (current_quality) {
492                         current_quality->set_selected (false);
493                 }
494
495                 /* Note:
496                  * A quality is never explicitly deselected without also deselecting the format
497                  * so we don't need to deselect the format here.
498                  * doing so causes extra complications
499                  */
500         }
501
502         if (do_selection_changed) {
503                 selection_changed ();
504         }
505 }
506
507 void
508 ExportFormatManager::select_format (ExportFormatPtr const & format)
509 {
510         bool do_selection_changed = !pending_selection_change;
511         if (!pending_selection_change) {
512                 pending_selection_change = true;
513         }
514
515         current_selection->set_format (format);
516
517         if (format) {
518
519                 /* Slect right quality for format */
520
521                 ExportFormatBase::Quality quality = format->get_quality();
522                 for (QualityList::iterator it = qualities.begin (); it != qualities.end (); ++it) {
523                         if ((*it)->quality == quality) {
524                                 (*it)->set_selected (true);
525                         } else {
526                                 (*it)->set_selected (false);
527                         }
528                 }
529
530                 /* Handle sample formats */
531
532                 ExportFormatBase::SampleFormat format_to_select;
533                 if (format->sample_format_is_compatible (current_selection->sample_format())) {
534                         format_to_select = current_selection->sample_format();
535                 } else {
536                         format_to_select = format->default_sample_format();
537                 }
538
539                 boost::shared_ptr<HasSampleFormat> hsf;
540                 if ((hsf = boost::dynamic_pointer_cast<HasSampleFormat> (format))) {
541                         SampleFormatList sample_formats = hsf->get_sample_formats();
542                         for (SampleFormatList::iterator it = sample_formats.begin (); it != sample_formats.end (); ++it) {
543                                 if ((*it)->format == format_to_select) {
544                                         (*it)->set_selected (true);
545                                 } else {
546                                         (*it)->set_selected (false);
547                                 }
548                         }
549                 }
550
551                 current_selection->set_sample_format (format_to_select);
552
553         } else {
554                 ExportFormatPtr current_format = get_selected_format ();
555                 if (current_format) {
556                         current_format->set_selected (false);
557                 }
558         }
559
560         if (do_selection_changed) {
561                 selection_changed ();
562         }
563 }
564
565 void
566 ExportFormatManager::select_sample_rate (SampleRatePtr const & rate)
567 {
568
569         bool do_selection_changed = !pending_selection_change;
570         if (!pending_selection_change) {
571                 pending_selection_change = true;
572         }
573
574         if (rate) {
575                 current_selection->set_sample_rate (rate->rate);
576         } else {
577                 current_selection->set_sample_rate (ExportFormatBase::SR_None);
578
579                 SampleRatePtr current_rate = get_selected_sample_rate();
580                 if (current_rate) {
581                         current_rate->set_selected (false);
582                 }
583         }
584
585         if (do_selection_changed) {
586                 selection_changed ();
587         }
588 }
589
590 void
591 ExportFormatManager::select_sample_format (SampleFormatPtr const & format)
592 {
593
594         bool do_selection_changed = !pending_selection_change;
595         if (!pending_selection_change) {
596                 pending_selection_change = true;
597         }
598
599         if (format) {
600                 current_selection->set_sample_format (format->format);
601         } else {
602                 current_selection->set_sample_format (ExportFormatBase::SF_None);
603
604                 SampleFormatPtr current_format = get_selected_sample_format();
605                 if (current_format) {
606                         current_format->set_selected (false);
607                 }
608         }
609
610         if (do_selection_changed) {
611                 selection_changed ();
612         }
613 }
614
615 void
616 ExportFormatManager::select_dither_type (DitherTypePtr const & type)
617 {
618
619         bool do_selection_changed = !pending_selection_change;
620         if (!pending_selection_change) {
621                 pending_selection_change = true;
622         }
623
624         if (type) {
625                 current_selection->set_dither_type (type->type);
626         } else {
627                 current_selection->set_dither_type (ExportFormatBase::D_None);
628         }
629
630         if (do_selection_changed) {
631                 selection_changed ();
632         }
633 }
634
635 void
636 ExportFormatManager::selection_changed ()
637 {
638         /* Get a list of incompatible compatibility selections */
639
640         CompatList incompatibles;
641         for (CompatList::iterator it = compatibilities.begin(); it != compatibilities.end(); ++it) {
642                 if (!current_selection->is_compatible_with (**it)) {
643                         incompatibles.push_back (*it);
644                 }
645         }
646
647         /* Deselect them */
648
649         for (CompatList::iterator it = incompatibles.begin(); it != incompatibles.end(); ++it) {
650                 (*it)->set_selected (false);
651         }
652
653         /* Mark compatibility for everything necessary */
654
655         std::set<ExportFormatBase::Quality> compatible_qualities;
656         ExportFormatBasePtr compat_intersect = get_compatibility_intersection ();
657         ExportFormatCompatibility global_compat (*compat_intersect);
658
659         for (FormatList::iterator it = formats.begin(); it != formats.end(); ++it) {
660                 if ((*it)->set_compatibility_state (global_compat)) {
661                         compatible_qualities.insert ((*it)->get_quality());
662                 }
663         }
664
665         bool any_quality_compatible = true;
666         for (QualityList::iterator it = qualities.begin(); it != qualities.end(); ++it) {
667                 if (compatible_qualities.find((*it)->quality) != compatible_qualities.end()) {
668                         (*it)->set_compatible (true);
669
670                 } else {
671                         (*it)->set_compatible (false);
672
673                         if ((*it)->quality != ExportFormatBase::Q_Any) {
674                                 any_quality_compatible = false;
675                         }
676                 }
677         }
678
679         if (any_quality_compatible) {
680                 for (QualityList::iterator it = qualities.begin(); it != qualities.end(); ++it) {
681                         if ((*it)->quality == ExportFormatBase::Q_Any) {
682                                 (*it)->set_compatible (true);
683                                 break;
684                         }
685                 }
686         }
687
688         for (SampleRateList::iterator it = sample_rates.begin(); it != sample_rates.end(); ++it) {
689                 if (compat_intersect->has_sample_rate ((*it)->rate)) {
690                         (*it)->set_compatible (true);
691                 } else {
692                         (*it)->set_compatible (false);
693                 }
694         }
695
696         boost::shared_ptr<HasSampleFormat> hsf;
697         if ((hsf = boost::dynamic_pointer_cast<HasSampleFormat> (get_selected_format()))) {
698
699                 SampleFormatList sf_list = hsf->get_sample_formats();
700                 for (SampleFormatList::iterator it = sf_list.begin(); it != sf_list.end(); ++it) {
701                         if (compat_intersect->has_sample_format ((*it)->format)) {
702                                 (*it)->set_compatible (true);
703                         } else {
704                                 (*it)->set_compatible (false);
705                         }
706                 }
707
708         }
709
710         /* Signal completeness and possible description change */
711
712         CompleteChanged (current_selection->is_complete());
713         check_for_description_change ();
714
715         /* Reset pending state */
716
717         pending_selection_change = false;
718 }
719
720 void
721 ExportFormatManager::check_for_description_change ()
722 {
723         std::string new_description = current_selection->description();
724         if (new_description == prev_description) { return; }
725
726         prev_description = new_description;
727         DescriptionChanged();
728 }
729
730 ExportFormatManager::QualityPtr
731 ExportFormatManager::get_selected_quality ()
732 {
733         for (QualityList::iterator it = qualities.begin(); it != qualities.end(); ++it) {
734                 if ((*it)->selected()) {
735                         return *it;
736                 }
737         }
738
739         return QualityPtr();
740 }
741
742 ExportFormatPtr
743 ExportFormatManager::get_selected_format ()
744 {
745         ExportFormatPtr format;
746
747         for (FormatList::iterator it = formats.begin(); it != formats.end(); ++it) {
748                 if ((*it)->selected()) {
749                         return *it;
750                 }
751         }
752
753         return format;
754 }
755
756 ExportFormatManager::SampleRatePtr
757 ExportFormatManager::get_selected_sample_rate ()
758 {
759         for (SampleRateList::iterator it = sample_rates.begin(); it != sample_rates.end(); ++it) {
760                 if ((*it)->selected()) {
761                         return *it;
762                 }
763         }
764
765         return SampleRatePtr();
766 }
767
768 ExportFormatManager::SampleFormatPtr
769 ExportFormatManager::get_selected_sample_format ()
770 {
771         boost::shared_ptr<HasSampleFormat> hsf;
772
773         if ((hsf = boost::dynamic_pointer_cast<HasSampleFormat> (get_selected_format()))) {
774                 return hsf->get_selected_sample_format ();
775         } else {
776                 return SampleFormatPtr ();
777         }
778 }
779
780
781 ExportFormatBasePtr
782 ExportFormatManager::get_compatibility_intersection ()
783 {
784         ExportFormatBasePtr compat_intersect = universal_set;
785
786         for (CompatList::iterator it = compatibilities.begin(); it != compatibilities.end(); ++it) {
787                 if ((*it)->selected ()) {
788                         compat_intersect = compat_intersect->get_intersection (**it);
789                 }
790         }
791
792         return compat_intersect;
793 }
794
795 }; // namespace ARDOUR