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