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 
ExportFormatManager(ExportFormatSpecPtr specification)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 
~ExportFormatManager()50 ExportFormatManager::~ExportFormatManager ()
51 {
52 
53 }
54 
55 void
init_compatibilities()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
init_qualities()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
init_formats()120 ExportFormatManager::init_formats ()
121 {
122 	ExportFormatPtr f_ptr;
123 	ExportFormatLinear * fl_ptr;
124 
125 	f_ptr.reset (fl_ptr = new ExportFormatTaggedLinear ("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 ExportFormatTaggedLinear ("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 ExportFormatTaggedLinear ("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
init_sample_rates()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
add_compatibility(ExportFormatCompatibilityPtr ptr)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
add_quality(QualityPtr ptr)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
add_format(ExportFormatPtr ptr)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
add_sample_rate(SampleRatePtr ptr)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
set_name(string name)279 ExportFormatManager::set_name (string name)
280 {
281 	current_selection->set_name (name);
282 	check_for_description_change ();
283 }
284 
285 void
select_src_quality(ExportFormatBase::SRCQuality value)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
select_codec_quality(int value)293 ExportFormatManager::select_codec_quality (int value)
294 {
295 	current_selection->set_codec_quality (value);
296 	check_for_description_change ();
297 }
298 
299 void
select_with_cue(bool value)300 ExportFormatManager::select_with_cue (bool value)
301 {
302 	current_selection->set_with_cue (value);
303 	check_for_description_change ();
304 }
305 
306 void
select_with_toc(bool value)307 ExportFormatManager::select_with_toc (bool value)
308 {
309 	current_selection->set_with_toc (value);
310 	check_for_description_change ();
311 }
312 
313 void
select_with_mp4chaps(bool value)314 ExportFormatManager::select_with_mp4chaps (bool value)
315 {
316 	current_selection->set_with_mp4chaps (value);
317 	check_for_description_change ();
318 }
319 
320 void
set_command(std::string command)321 ExportFormatManager::set_command (std::string command)
322 {
323 	current_selection->set_command (command);
324 	check_for_description_change ();
325 }
326 
327 void
select_trim_beginning(bool value)328 ExportFormatManager::select_trim_beginning (bool value)
329 {
330 	current_selection->set_trim_beginning (value);
331 	check_for_description_change ();
332 }
333 
334 void
select_silence_beginning(AnyTime const & time)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
select_trim_end(bool value)342 ExportFormatManager::select_trim_end (bool value)
343 {
344 	current_selection->set_trim_end (value);
345 	check_for_description_change ();
346 }
347 
348 void
select_silence_end(AnyTime const & time)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
select_normalize(bool value)356 ExportFormatManager::select_normalize (bool value)
357 {
358 	current_selection->set_normalize (value);
359 	check_for_description_change ();
360 }
361 
362 void
select_normalize_loudness(bool value)363 ExportFormatManager::select_normalize_loudness (bool value)
364 {
365 	current_selection->set_normalize_loudness (value);
366 	check_for_description_change ();
367 }
368 
369 void
select_tp_limiter(bool value)370 ExportFormatManager::select_tp_limiter (bool value)
371 {
372 	current_selection->set_use_tp_limiter (value);
373 	check_for_description_change ();
374 }
375 
376 void
select_normalize_dbfs(float value)377 ExportFormatManager::select_normalize_dbfs (float value)
378 {
379 	current_selection->set_normalize_dbfs (value);
380 	check_for_description_change ();
381 }
382 
383 void
select_normalize_lufs(float value)384 ExportFormatManager::select_normalize_lufs (float value)
385 {
386 	current_selection->set_normalize_lufs (value);
387 	check_for_description_change ();
388 }
389 
390 void
select_normalize_dbtp(float value)391 ExportFormatManager::select_normalize_dbtp (float value)
392 {
393 	current_selection->set_normalize_dbtp (value);
394 	check_for_description_change ();
395 }
396 
397 void
select_demo_noise_level(float value)398 ExportFormatManager::select_demo_noise_level (float value)
399 {
400 	current_selection->set_demo_noise_level (value);
401 	check_for_description_change ();
402 }
403 
404 void
select_demo_noise_duration(int value)405 ExportFormatManager::select_demo_noise_duration (int value)
406 {
407 	current_selection->set_demo_noise_duration (value);
408 	check_for_description_change ();
409 }
410 
411 void
select_demo_noise_interval(int value)412 ExportFormatManager::select_demo_noise_interval (int value)
413 {
414 	current_selection->set_demo_noise_interval (value);
415 	check_for_description_change ();
416 }
417 
418 void
select_tagging(bool tag)419 ExportFormatManager::select_tagging (bool tag)
420 {
421 	current_selection->set_tag (tag);
422 	check_for_description_change ();
423 }
424 
425 void
change_compatibility_selection(bool select,WeakExportFormatCompatibilityPtr const & compat)426 ExportFormatManager::change_compatibility_selection (bool select, WeakExportFormatCompatibilityPtr const & compat)
427 {
428 	bool do_selection_changed = !pending_selection_change;
429 	if (!pending_selection_change) {
430 		pending_selection_change = true;
431 	}
432 
433 	ExportFormatCompatibilityPtr ptr = compat.lock();
434 
435 	if (ptr && select) {
436 		select_compatibility (ptr);
437 	}
438 
439 	if (do_selection_changed) {
440 		selection_changed ();
441 	}
442 }
443 
444 void
change_quality_selection(bool select,WeakQualityPtr const & quality)445 ExportFormatManager::change_quality_selection (bool select, WeakQualityPtr const & quality)
446 {
447 	QualityPtr ptr = quality.lock ();
448 
449 	if (!ptr) {
450 		return;
451 	}
452 
453 	if (select) {
454 		select_quality (ptr);
455 	} else if (ptr->quality == current_selection->quality()) {
456 		ptr.reset();
457 		select_quality (ptr);
458 	}
459 }
460 
461 void
change_format_selection(bool select,WeakExportFormatPtr const & format)462 ExportFormatManager::change_format_selection (bool select, WeakExportFormatPtr const & format)
463 {
464 	ExportFormatPtr ptr = format.lock();
465 
466 	if (!ptr) {
467 		return;
468 	}
469 
470 	if (select) {
471 		select_format (ptr);
472 	} else if (ptr->get_format_id() == current_selection->format_id()) {
473 		ptr.reset();
474 		select_format (ptr);
475 	}
476 }
477 
478 void
change_sample_rate_selection(bool select,WeakSampleRatePtr const & rate)479 ExportFormatManager::change_sample_rate_selection (bool select, WeakSampleRatePtr const & rate)
480 {
481 	SampleRatePtr ptr = rate.lock();
482 
483 	if (!ptr) {
484 		return;
485 	}
486 
487 	if (select) {
488 		select_sample_rate (ptr);
489 	} else if (ptr->rate == current_selection->sample_rate()) {
490 		ptr.reset();
491 		select_sample_rate (ptr);
492 	}
493 }
494 
495 void
change_sample_format_selection(bool select,WeakSampleFormatPtr const & format)496 ExportFormatManager::change_sample_format_selection (bool select, WeakSampleFormatPtr const & format)
497 {
498 	SampleFormatPtr ptr = format.lock();
499 
500 	if (!ptr) {
501 		return;
502 	}
503 
504 	if (select) {
505 		select_sample_format (ptr);
506 	} else if (ptr->format == current_selection->sample_format()) {
507 		ptr.reset();
508 		select_sample_format (ptr);
509 	}
510 }
511 
512 void
change_dither_type_selection(bool select,WeakDitherTypePtr const & type)513 ExportFormatManager::change_dither_type_selection (bool select, WeakDitherTypePtr const & type)
514 {
515 	DitherTypePtr ptr = type.lock();
516 
517 	if (!ptr) {
518 		return;
519 	}
520 
521 	if (select) {
522 		select_dither_type (ptr);
523 	} else if (ptr->type == current_selection->dither_type()) {
524 		ptr.reset();
525 		select_dither_type (ptr);
526 	}
527 }
528 
529 void
select_compatibility(WeakExportFormatCompatibilityPtr const &)530 ExportFormatManager::select_compatibility (WeakExportFormatCompatibilityPtr const & /*compat*/)
531 {
532 	/* Calculate compatibility intersection for the selection */
533 
534 	ExportFormatBasePtr compat_intersect = get_compatibility_intersection ();
535 
536 	/* Unselect incompatible items */
537 
538 	boost::shared_ptr<ExportFormatBase> select_intersect;
539 
540 	select_intersect = compat_intersect->get_intersection (*current_selection);
541 	if (select_intersect->qualities_empty()) {
542 		select_quality (QualityPtr());
543 	}
544 
545 	select_intersect = compat_intersect->get_intersection (*current_selection);
546 	if (select_intersect->formats_empty()) {
547 		select_format (ExportFormatPtr());
548 	}
549 
550 	select_intersect = compat_intersect->get_intersection (*current_selection);
551 	if (select_intersect->sample_rates_empty()) {
552 		select_sample_rate (SampleRatePtr());
553 	}
554 
555 	select_intersect = compat_intersect->get_intersection (*current_selection);
556 	if (select_intersect->sample_formats_empty()) {
557 		select_sample_format (SampleFormatPtr());
558 	}
559 }
560 
561 void
select_quality(QualityPtr const & quality)562 ExportFormatManager::select_quality (QualityPtr const & quality)
563 {
564 	bool do_selection_changed = !pending_selection_change;
565 	if (!pending_selection_change) {
566 		pending_selection_change = true;
567 	}
568 
569 	if (quality) {
570 		current_selection->set_quality (quality->quality);
571 
572 		/* Deselect format if it is incompatible */
573 
574 		ExportFormatPtr format = get_selected_format();
575 		if (format && !format->has_quality (quality->quality)) {
576 			format->set_selected (false);
577 		}
578 
579 	} else {
580 		current_selection->set_quality (ExportFormatBase::Q_None);
581 
582 		QualityPtr current_quality = get_selected_quality();
583 		if (current_quality) {
584 			current_quality->set_selected (false);
585 		}
586 
587 		/* Note:
588 		 * A quality is never explicitly deselected without also deselecting the format
589 		 * so we don't need to deselect the format here.
590 		 * doing so causes extra complications
591 		 */
592 	}
593 
594 	if (do_selection_changed) {
595 		selection_changed ();
596 	}
597 }
598 
599 void
select_format(ExportFormatPtr const & format)600 ExportFormatManager::select_format (ExportFormatPtr const & format)
601 {
602 	bool do_selection_changed = !pending_selection_change;
603 	if (!pending_selection_change) {
604 		pending_selection_change = true;
605 	}
606 
607 	current_selection->set_format (format);
608 
609 	if (format) {
610 
611 		/* Slect right quality for format */
612 
613 		ExportFormatBase::Quality quality = format->get_quality();
614 		for (QualityList::iterator it = qualities.begin (); it != qualities.end (); ++it) {
615 			if ((*it)->quality == quality) {
616 				(*it)->set_selected (true);
617 			} else {
618 				(*it)->set_selected (false);
619 			}
620 		}
621 
622 		/* Handle sample formats */
623 
624 		ExportFormatBase::SampleFormat format_to_select;
625 		if (format->sample_format_is_compatible (current_selection->sample_format())) {
626 			format_to_select = current_selection->sample_format();
627 		} else {
628 			format_to_select = format->default_sample_format();
629 		}
630 
631 		boost::shared_ptr<HasSampleFormat> hsf;
632 		if ((hsf = boost::dynamic_pointer_cast<HasSampleFormat> (format))) {
633 			SampleFormatList sample_formats = hsf->get_sample_formats();
634 			for (SampleFormatList::iterator it = sample_formats.begin (); it != sample_formats.end (); ++it) {
635 				if ((*it)->format == format_to_select) {
636 					(*it)->set_selected (true);
637 				} else {
638 					(*it)->set_selected (false);
639 				}
640 			}
641 		}
642 
643 		current_selection->set_sample_format (format_to_select);
644 
645 	} else {
646 		ExportFormatPtr current_format = get_selected_format ();
647 		if (current_format) {
648 			current_format->set_selected (false);
649 		}
650 	}
651 
652 	if (do_selection_changed) {
653 		selection_changed ();
654 	}
655 }
656 
657 void
select_sample_rate(SampleRatePtr const & rate)658 ExportFormatManager::select_sample_rate (SampleRatePtr const & rate)
659 {
660 
661 	bool do_selection_changed = !pending_selection_change;
662 	if (!pending_selection_change) {
663 		pending_selection_change = true;
664 	}
665 
666 	if (rate) {
667 		current_selection->set_sample_rate (rate->rate);
668 	} else {
669 		current_selection->set_sample_rate (ExportFormatBase::SR_None);
670 
671 		SampleRatePtr current_rate = get_selected_sample_rate();
672 		if (current_rate) {
673 			current_rate->set_selected (false);
674 		}
675 	}
676 
677 	if (do_selection_changed) {
678 		selection_changed ();
679 	}
680 }
681 
682 void
select_sample_format(SampleFormatPtr const & format)683 ExportFormatManager::select_sample_format (SampleFormatPtr const & format)
684 {
685 
686 	bool do_selection_changed = !pending_selection_change;
687 	if (!pending_selection_change) {
688 		pending_selection_change = true;
689 	}
690 
691 	if (format) {
692 		current_selection->set_sample_format (format->format);
693 	} else {
694 		current_selection->set_sample_format (ExportFormatBase::SF_None);
695 
696 		SampleFormatPtr current_format = get_selected_sample_format();
697 		if (current_format) {
698 			current_format->set_selected (false);
699 		}
700 	}
701 
702 	if (do_selection_changed) {
703 		selection_changed ();
704 	}
705 }
706 
707 void
select_dither_type(DitherTypePtr const & type)708 ExportFormatManager::select_dither_type (DitherTypePtr const & type)
709 {
710 
711 	bool do_selection_changed = !pending_selection_change;
712 	if (!pending_selection_change) {
713 		pending_selection_change = true;
714 	}
715 
716 	if (type) {
717 		current_selection->set_dither_type (type->type);
718 	} else {
719 		current_selection->set_dither_type (ExportFormatBase::D_None);
720 	}
721 
722 	if (do_selection_changed) {
723 		selection_changed ();
724 	}
725 }
726 
727 void
selection_changed()728 ExportFormatManager::selection_changed ()
729 {
730 	/* Get a list of incompatible compatibility selections */
731 
732 	CompatList incompatibles;
733 	for (CompatList::iterator it = compatibilities.begin(); it != compatibilities.end(); ++it) {
734 		if (!current_selection->is_compatible_with (**it)) {
735 			incompatibles.push_back (*it);
736 		}
737 	}
738 
739 	/* Deselect them */
740 
741 	for (CompatList::iterator it = incompatibles.begin(); it != incompatibles.end(); ++it) {
742 		(*it)->set_selected (false);
743 	}
744 
745 	/* Mark compatibility for everything necessary */
746 
747 	std::set<ExportFormatBase::Quality> compatible_qualities;
748 	ExportFormatBasePtr compat_intersect = get_compatibility_intersection ();
749 	ExportFormatCompatibility global_compat (*compat_intersect);
750 
751 	for (FormatList::iterator it = formats.begin(); it != formats.end(); ++it) {
752 		if ((*it)->set_compatibility_state (global_compat)) {
753 			compatible_qualities.insert ((*it)->get_quality());
754 		}
755 	}
756 
757 	bool any_quality_compatible = true;
758 	for (QualityList::iterator it = qualities.begin(); it != qualities.end(); ++it) {
759 		if (compatible_qualities.find((*it)->quality) != compatible_qualities.end()) {
760 			(*it)->set_compatible (true);
761 
762 		} else {
763 			(*it)->set_compatible (false);
764 
765 			if ((*it)->quality != ExportFormatBase::Q_Any) {
766 				any_quality_compatible = false;
767 			}
768 		}
769 	}
770 
771 	if (any_quality_compatible) {
772 		for (QualityList::iterator it = qualities.begin(); it != qualities.end(); ++it) {
773 			if ((*it)->quality == ExportFormatBase::Q_Any) {
774 				(*it)->set_compatible (true);
775 				break;
776 			}
777 		}
778 	}
779 
780 	for (SampleRateList::iterator it = sample_rates.begin(); it != sample_rates.end(); ++it) {
781 		if (compat_intersect->has_sample_rate ((*it)->rate)) {
782 			(*it)->set_compatible (true);
783 		} else {
784 			(*it)->set_compatible (false);
785 		}
786 	}
787 
788 	boost::shared_ptr<HasSampleFormat> hsf;
789 	if ((hsf = boost::dynamic_pointer_cast<HasSampleFormat> (get_selected_format()))) {
790 
791 		SampleFormatList sf_list = hsf->get_sample_formats();
792 		for (SampleFormatList::iterator it = sf_list.begin(); it != sf_list.end(); ++it) {
793 			if (compat_intersect->has_sample_format ((*it)->format)) {
794 				(*it)->set_compatible (true);
795 			} else {
796 				(*it)->set_compatible (false);
797 			}
798 		}
799 
800 	}
801 
802 	/* Signal completeness and possible description change */
803 
804 	CompleteChanged (current_selection->is_complete());
805 	check_for_description_change ();
806 
807 	/* Reset pending state */
808 
809 	pending_selection_change = false;
810 }
811 
812 void
check_for_description_change()813 ExportFormatManager::check_for_description_change ()
814 {
815 	std::string new_description = current_selection->description();
816 	if (new_description == prev_description) { return; }
817 
818 	prev_description = new_description;
819 	DescriptionChanged();
820 }
821 
822 ExportFormatManager::QualityPtr
get_selected_quality()823 ExportFormatManager::get_selected_quality ()
824 {
825 	for (QualityList::iterator it = qualities.begin(); it != qualities.end(); ++it) {
826 		if ((*it)->selected()) {
827 			return *it;
828 		}
829 	}
830 
831 	return QualityPtr();
832 }
833 
834 ExportFormatPtr
get_selected_format()835 ExportFormatManager::get_selected_format ()
836 {
837 	ExportFormatPtr format;
838 
839 	for (FormatList::iterator it = formats.begin(); it != formats.end(); ++it) {
840 		if ((*it)->selected()) {
841 			return *it;
842 		}
843 	}
844 
845 	return format;
846 }
847 
848 ExportFormatManager::SampleRatePtr
get_selected_sample_rate()849 ExportFormatManager::get_selected_sample_rate ()
850 {
851 	for (SampleRateList::iterator it = sample_rates.begin(); it != sample_rates.end(); ++it) {
852 		if ((*it)->selected()) {
853 			return *it;
854 		}
855 	}
856 
857 	return SampleRatePtr();
858 }
859 
860 ExportFormatManager::SampleFormatPtr
get_selected_sample_format()861 ExportFormatManager::get_selected_sample_format ()
862 {
863 	boost::shared_ptr<HasSampleFormat> hsf;
864 
865 	if ((hsf = boost::dynamic_pointer_cast<HasSampleFormat> (get_selected_format()))) {
866 		return hsf->get_selected_sample_format ();
867 	} else {
868 		return SampleFormatPtr ();
869 	}
870 }
871 
872 
873 ExportFormatBasePtr
get_compatibility_intersection()874 ExportFormatManager::get_compatibility_intersection ()
875 {
876 	ExportFormatBasePtr compat_intersect = universal_set;
877 
878 	for (CompatList::iterator it = compatibilities.begin(); it != compatibilities.end(); ++it) {
879 		if ((*it)->selected ()) {
880 			compat_intersect = compat_intersect->get_intersection (**it);
881 		}
882 	}
883 
884 	return compat_intersect;
885 }
886 
887 }; // namespace ARDOUR
888