force AIFF and WAV exports to Big and Little endianness respectively
[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/types.h"
24 #include "ardour/export_format_specification.h"
25 #include "ardour/export_format_compatibility.h"
26
27 #include "i18n.h"
28
29 namespace ARDOUR
30 {
31
32 ExportFormatManager::ExportFormatManager (SpecPtr specification) :
33   pending_selection_change (false),
34   universal_set (new ExportFormatBase ())
35 {
36         current_selection = specification;
37
38         init_compatibilities ();
39         init_qualities ();
40         init_formats ();
41         init_sample_rates ();
42 }
43
44 ExportFormatManager::~ExportFormatManager ()
45 {
46
47 }
48
49 void
50 ExportFormatManager::init_compatibilities ()
51 {
52         CompatPtr c_ptr;
53
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);
62
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);
76
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);
87
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);
102 }
103
104 void
105 ExportFormatManager::init_qualities ()
106 {
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"))));
111 }
112
113 void
114 ExportFormatManager::init_formats ()
115 {
116         FormatPtr f_ptr;
117         ExportFormatLinear * fl_ptr;
118
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");
130         add_format (f_ptr);
131
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");
141         add_format (f_ptr);
142
143         f_ptr.reset (new ExportFormatBWF ());
144         add_format (f_ptr);
145
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");
153         add_format (f_ptr);
154
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");
165         add_format (f_ptr);
166
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");
176         add_format (f_ptr);
177
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");
188         add_format (f_ptr);
189
190         try {
191                 f_ptr.reset (new ExportFormatOggVorbis ());
192                 add_format (f_ptr);
193         } catch (ExportFormatIncompatible & e) {}
194
195         try {
196                 f_ptr.reset (new ExportFormatFLAC ());
197                 add_format (f_ptr);
198         } catch (ExportFormatIncompatible & e) {}
199 }
200
201 void
202 ExportFormatManager::init_sample_rates ()
203 {
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")));
210 }
211
212 void
213 ExportFormatManager::add_compatibility (CompatPtr ptr)
214 {
215         compatibilities.push_back (ptr);
216         ptr->SelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_compatibility_selection, this, _1, WeakCompatPtr (ptr)));
217 }
218
219 void
220 ExportFormatManager::add_quality (QualityPtr ptr)
221 {
222         ptr->SelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_quality_selection, this, _1, WeakQualityPtr (ptr)));
223         qualities.push_back (ptr);
224 }
225
226 void
227 ExportFormatManager::add_format (FormatPtr ptr)
228 {
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);
232
233         /* Encoding options */
234
235         boost::shared_ptr<HasSampleFormat> hsf;
236
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));
240         }
241 }
242
243 void
244 ExportFormatManager::add_sample_rate (SampleRatePtr ptr)
245 {
246         ptr->SelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_sample_rate_selection, this, _1, WeakSampleRatePtr (ptr)));
247         sample_rates.push_back (ptr);
248 }
249
250 void
251 ExportFormatManager::set_name (Glib::ustring name)
252 {
253         current_selection->set_name (name);
254 }
255
256 void
257 ExportFormatManager::select_src_quality (ExportFormatBase::SRCQuality value)
258 {
259         current_selection->set_src_quality (value);
260 }
261
262 void
263 ExportFormatManager::select_trim_beginning (bool value)
264 {
265         current_selection->set_trim_beginning (value);
266 }
267
268 void
269 ExportFormatManager::select_silence_beginning (AnyTime const & time)
270 {
271         current_selection->set_silence_beginning (time);
272 }
273
274 void
275 ExportFormatManager::select_trim_end (bool value)
276 {
277         current_selection->set_trim_end (value);
278 }
279
280 void
281 ExportFormatManager::select_silence_end (AnyTime const & time)
282 {
283         current_selection->set_silence_end (time);
284 }
285
286 void
287 ExportFormatManager::select_normalize (bool value)
288 {
289         current_selection->set_normalize (value);
290 }
291
292 void
293 ExportFormatManager::select_normalize_target (float value)
294 {
295         current_selection->set_normalize_target (value);
296 }
297
298 void
299 ExportFormatManager::select_tagging (bool tag)
300 {
301         current_selection->set_tag (tag);
302 }
303
304 void
305 ExportFormatManager::change_compatibility_selection (bool select, WeakCompatPtr const & compat)
306 {
307         bool do_selection_changed = !pending_selection_change;
308         if (!pending_selection_change) {
309                 pending_selection_change = true;
310         }
311
312         CompatPtr ptr = compat.lock();
313
314         if (ptr && select) {
315                 select_compatibility (ptr);
316         }
317
318         if (do_selection_changed) {
319                 selection_changed ();
320         }
321 }
322
323 void
324 ExportFormatManager::change_quality_selection (bool select, WeakQualityPtr const & quality)
325 {
326         QualityPtr ptr = quality.lock ();
327
328         if (!ptr) {
329                 return;
330         }
331
332         if (select) {
333                 select_quality (ptr);
334         } else if (ptr->quality == current_selection->quality()) {
335                 ptr.reset();
336                 select_quality (ptr);
337         }
338 }
339
340 void
341 ExportFormatManager::change_format_selection (bool select, WeakFormatPtr const & format)
342 {
343         FormatPtr ptr = format.lock();
344
345         if (!ptr) {
346                 return;
347         }
348
349         if (select) {
350                 select_format (ptr);
351         } else if (ptr->get_format_id() == current_selection->format_id()) {
352                 ptr.reset();
353                 select_format (ptr);
354         }
355 }
356
357 void
358 ExportFormatManager::change_sample_rate_selection (bool select, WeakSampleRatePtr const & rate)
359 {
360         SampleRatePtr ptr = rate.lock();
361
362         if (!ptr) {
363                 return;
364         }
365
366         if (select) {
367                 select_sample_rate (ptr);
368         } else if (ptr->rate == current_selection->sample_rate()) {
369                 ptr.reset();
370                 select_sample_rate (ptr);
371         }
372 }
373
374 void
375 ExportFormatManager::change_sample_format_selection (bool select, WeakSampleFormatPtr const & format)
376 {
377         SampleFormatPtr ptr = format.lock();
378
379         if (!ptr) {
380                 return;
381         }
382
383         if (select) {
384                 select_sample_format (ptr);
385         } else if (ptr->format == current_selection->sample_format()) {
386                 ptr.reset();
387                 select_sample_format (ptr);
388         }
389 }
390
391 void
392 ExportFormatManager::change_dither_type_selection (bool select, WeakDitherTypePtr const & type)
393 {
394         DitherTypePtr ptr = type.lock();
395
396         if (!ptr) {
397                 return;
398         }
399
400         if (select) {
401                 select_dither_type (ptr);
402         } else if (ptr->type == current_selection->dither_type()) {
403                 ptr.reset();
404                 select_dither_type (ptr);
405         }
406 }
407
408 void
409 ExportFormatManager::select_compatibility (WeakCompatPtr const & /*compat*/)
410 {
411         /* Calculate compatibility intersection for the selection */
412
413         FormatBasePtr compat_intersect = get_compatibility_intersection ();
414
415         /* Unselect incompatible items */
416
417         boost::shared_ptr<ExportFormatBase> select_intersect;
418
419         select_intersect = compat_intersect->get_intersection (*current_selection);
420         if (select_intersect->qualities_empty()) {
421                 select_quality (QualityPtr());
422         }
423
424         select_intersect = compat_intersect->get_intersection (*current_selection);
425         if (select_intersect->formats_empty()) {
426                 select_format (FormatPtr());
427         }
428
429         select_intersect = compat_intersect->get_intersection (*current_selection);
430         if (select_intersect->sample_rates_empty()) {
431                 select_sample_rate (SampleRatePtr());
432         }
433
434         select_intersect = compat_intersect->get_intersection (*current_selection);
435         if (select_intersect->sample_formats_empty()) {
436                 select_sample_format (SampleFormatPtr());
437         }
438 }
439
440 void
441 ExportFormatManager::select_quality (QualityPtr const & quality)
442 {
443         bool do_selection_changed = !pending_selection_change;
444         if (!pending_selection_change) {
445                 pending_selection_change = true;
446         }
447
448         if (quality) {
449                 current_selection->set_quality (quality->quality);
450
451                 /* Deselect format if it is incompatible */
452
453                 FormatPtr format = get_selected_format();
454                 if (format && !format->has_quality (quality->quality)) {
455                         format->set_selected (false);
456                 }
457
458         } else {
459                 current_selection->set_quality (ExportFormatBase::Q_None);
460
461                 QualityPtr current_quality = get_selected_quality();
462                 if (current_quality) {
463                         current_quality->set_selected (false);
464                 }
465
466                 /* Note:
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
470                  */
471         }
472
473         if (do_selection_changed) {
474                 selection_changed ();
475         }
476 }
477
478 void
479 ExportFormatManager::select_format (FormatPtr const & format)
480 {
481         bool do_selection_changed = !pending_selection_change;
482         if (!pending_selection_change) {
483                 pending_selection_change = true;
484         }
485
486         current_selection->set_format (format);
487
488         if (format) {
489
490                 /* Slect right quality for format */
491
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);
496                         } else {
497                                 (*it)->set_selected (false);
498                         }
499                 }
500
501                 /* Handle sample formats */
502
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();
506                 } else {
507                         format_to_select = format->default_sample_format();
508                 }
509
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);
516                                 } else {
517                                         (*it)->set_selected (false);
518                                 }
519                         }
520                 }
521
522                 current_selection->set_sample_format (format_to_select);
523
524         } else {
525                 FormatPtr current_format = get_selected_format ();
526                 if (current_format) {
527                         current_format->set_selected (false);
528                 }
529         }
530
531         if (do_selection_changed) {
532                 selection_changed ();
533         }
534 }
535
536 void
537 ExportFormatManager::select_sample_rate (SampleRatePtr const & rate)
538 {
539
540         bool do_selection_changed = !pending_selection_change;
541         if (!pending_selection_change) {
542                 pending_selection_change = true;
543         }
544
545         if (rate) {
546                 current_selection->set_sample_rate (rate->rate);
547         } else {
548                 current_selection->set_sample_rate (ExportFormatBase::SR_None);
549
550                 SampleRatePtr current_rate = get_selected_sample_rate();
551                 if (current_rate) {
552                         current_rate->set_selected (false);
553                 }
554         }
555
556         if (do_selection_changed) {
557                 selection_changed ();
558         }
559 }
560
561 void
562 ExportFormatManager::select_sample_format (SampleFormatPtr const & format)
563 {
564
565         bool do_selection_changed = !pending_selection_change;
566         if (!pending_selection_change) {
567                 pending_selection_change = true;
568         }
569
570         if (format) {
571                 current_selection->set_sample_format (format->format);
572         } else {
573                 current_selection->set_sample_format (ExportFormatBase::SF_None);
574
575                 SampleFormatPtr current_format = get_selected_sample_format();
576                 if (current_format) {
577                         current_format->set_selected (false);
578                 }
579         }
580
581         if (do_selection_changed) {
582                 selection_changed ();
583         }
584 }
585
586 void
587 ExportFormatManager::select_dither_type (DitherTypePtr const & type)
588 {
589
590         bool do_selection_changed = !pending_selection_change;
591         if (!pending_selection_change) {
592                 pending_selection_change = true;
593         }
594
595         if (type) {
596                 current_selection->set_dither_type (type->type);
597         } else {
598                 current_selection->set_dither_type (ExportFormatBase::D_None);
599         }
600
601         if (do_selection_changed) {
602                 selection_changed ();
603         }
604 }
605
606 void
607 ExportFormatManager::selection_changed ()
608 {
609         /* Get a list of incompatible compatibility selections */
610
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);
615                 }
616         }
617
618         /* Deselect them */
619
620         for (CompatList::iterator it = incompatibles.begin(); it != incompatibles.end(); ++it) {
621                 (*it)->set_selected (false);
622         }
623
624         /* Mark compatibility for everything necessary */
625
626         std::set<ExportFormatBase::Quality> compatible_qualities;
627         FormatBasePtr compat_intersect = get_compatibility_intersection ();
628         ExportFormatCompatibility global_compat (*compat_intersect);
629
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());
633                 }
634         }
635
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);
640
641                 } else {
642                         (*it)->set_compatible (false);
643
644                         if ((*it)->quality != ExportFormatBase::Q_Any) {
645                                 any_quality_compatible = false;
646                         }
647                 }
648         }
649
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);
654                                 break;
655                         }
656                 }
657         }
658
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);
662                 } else {
663                         (*it)->set_compatible (false);
664                 }
665         }
666
667         boost::shared_ptr<HasSampleFormat> hsf;
668         if (hsf = boost::dynamic_pointer_cast<HasSampleFormat> (get_selected_format())) {
669
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);
674                         } else {
675                                 (*it)->set_compatible (false);
676                         }
677                 }
678
679         }
680
681         /* Signal completeness */
682
683         CompleteChanged (current_selection->is_complete());
684
685         /* Reset pending state */
686
687         pending_selection_change = false;
688 }
689
690 ExportFormatManager::QualityPtr
691 ExportFormatManager::get_selected_quality ()
692 {
693         for (QualityList::iterator it = qualities.begin(); it != qualities.end(); ++it) {
694                 if ((*it)->selected()) {
695                         return *it;
696                 }
697         }
698
699         return QualityPtr();
700 }
701
702 ExportFormatManager::FormatPtr
703 ExportFormatManager::get_selected_format ()
704 {
705         FormatPtr format;
706
707         for (FormatList::iterator it = formats.begin(); it != formats.end(); ++it) {
708                 if ((*it)->selected()) {
709                         return *it;
710                 }
711         }
712
713         return format;
714 }
715
716 ExportFormatManager::SampleRatePtr
717 ExportFormatManager::get_selected_sample_rate ()
718 {
719         for (SampleRateList::iterator it = sample_rates.begin(); it != sample_rates.end(); ++it) {
720                 if ((*it)->selected()) {
721                         return *it;
722                 }
723         }
724
725         return SampleRatePtr();
726 }
727
728 ExportFormatManager::SampleFormatPtr
729 ExportFormatManager::get_selected_sample_format ()
730 {
731         boost::shared_ptr<HasSampleFormat> hsf;
732
733         if (hsf = boost::dynamic_pointer_cast<HasSampleFormat> (get_selected_format())) {
734                 return hsf->get_selected_sample_format ();
735         } else {
736                 return SampleFormatPtr ();
737         }
738 }
739
740
741 ExportFormatManager::FormatBasePtr
742 ExportFormatManager::get_compatibility_intersection ()
743 {
744         FormatBasePtr compat_intersect = universal_set;
745
746         for (CompatList::iterator it = compatibilities.begin(); it != compatibilities.end(); ++it) {
747                 if ((*it)->selected ()) {
748                         compat_intersect = compat_intersect->get_intersection (**it);
749                 }
750         }
751
752         return compat_intersect;
753 }
754
755 }; // namespace ARDOUR