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