ardour
export_format_manager.cc
Go to the documentation of this file.
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 
22 
25 
26 #include "i18n.h"
27 
28 using std::string;
29 
30 namespace ARDOUR
31 {
32 
34  pending_selection_change (false),
35  universal_set (new ExportFormatBase ())
36 {
37  current_selection = specification;
38 
40  init_qualities ();
41  init_formats ();
43 
44  prev_description = current_selection->description();
45 }
46 
48 {
49 
50 }
51 
52 void
54 {
56 
57  c_ptr.reset (new ExportFormatCompatibility (_("CD")));
58  c_ptr->add_sample_rate (ExportFormatBase::SR_44_1);
59  c_ptr->add_format_id (ExportFormatBase::F_WAV);
60  c_ptr->add_format_id (ExportFormatBase::F_AIFF);
61  c_ptr->add_quality (ExportFormatBase::Q_LosslessLinear);
62  c_ptr->add_sample_format (ExportFormatBase::SF_16);
63  c_ptr->add_endianness (ExportFormatBase::E_FileDefault);
64  add_compatibility (c_ptr);
65 
66  c_ptr.reset (new ExportFormatCompatibility (_("DVD-A")));
67  c_ptr->add_sample_rate (ExportFormatBase::SR_44_1);
68  c_ptr->add_sample_rate (ExportFormatBase::SR_48);
69  c_ptr->add_sample_rate (ExportFormatBase::SR_88_2);
70  c_ptr->add_sample_rate (ExportFormatBase::SR_96);
71  c_ptr->add_sample_rate (ExportFormatBase::SR_192);
72  c_ptr->add_format_id (ExportFormatBase::F_WAV);
73  c_ptr->add_format_id (ExportFormatBase::F_AIFF);
74  c_ptr->add_quality (ExportFormatBase::Q_LosslessLinear);
75  c_ptr->add_sample_format (ExportFormatBase::SF_16);
76  c_ptr->add_sample_format (ExportFormatBase::SF_24);
77  c_ptr->add_endianness (ExportFormatBase::E_FileDefault);
78  add_compatibility (c_ptr);
79 
80  c_ptr.reset (new ExportFormatCompatibility (_("iPod")));
81  c_ptr->add_sample_rate (ExportFormatBase::SR_44_1);
82  c_ptr->add_sample_rate (ExportFormatBase::SR_48);
83  c_ptr->add_format_id (ExportFormatBase::F_WAV);
84  c_ptr->add_format_id (ExportFormatBase::F_AIFF);
85  c_ptr->add_quality (ExportFormatBase::Q_LosslessLinear);
86  c_ptr->add_sample_format (ExportFormatBase::SF_16);
87  c_ptr->add_sample_format (ExportFormatBase::SF_24);
88  c_ptr->add_endianness (ExportFormatBase::E_FileDefault);
89  add_compatibility (c_ptr);
90 
91  c_ptr.reset (new ExportFormatCompatibility (_("Something else")));
92  c_ptr->add_sample_rate (ExportFormatBase::SR_44_1);
93  c_ptr->add_sample_rate (ExportFormatBase::SR_48);
94  c_ptr->add_format_id (ExportFormatBase::F_WAV);
95  c_ptr->add_format_id (ExportFormatBase::F_AIFF);
96  c_ptr->add_format_id (ExportFormatBase::F_AU);
97  c_ptr->add_format_id (ExportFormatBase::F_FLAC);
98  c_ptr->add_quality (ExportFormatBase::Q_LosslessLinear);
99  c_ptr->add_quality (ExportFormatBase::Q_LosslessCompression);
100  c_ptr->add_sample_format (ExportFormatBase::SF_16);
101  c_ptr->add_sample_format (ExportFormatBase::SF_24);
102  c_ptr->add_sample_format (ExportFormatBase::SF_32);
103  c_ptr->add_endianness (ExportFormatBase::E_FileDefault);
104  add_compatibility (c_ptr);
105 }
106 
107 void
109 {
111  add_quality (QualityPtr (new QualityState (ExportFormatBase::Q_LosslessLinear, _("Lossless (linear PCM)"))));
114 }
115 
116 void
118 {
119  ExportFormatPtr f_ptr;
120  ExportFormatLinear * fl_ptr;
121 
122  f_ptr.reset (fl_ptr = new ExportFormatLinear ("AIFF", ExportFormatBase::F_AIFF));
132  fl_ptr->set_extension ("aiff");
133  add_format (f_ptr);
134 
135  f_ptr.reset (fl_ptr = new ExportFormatLinear ("AU", ExportFormatBase::F_AU));
143  fl_ptr->set_extension ("au");
144  add_format (f_ptr);
145 
146  f_ptr.reset (new ExportFormatBWF ());
147  add_format (f_ptr);
148 
149  f_ptr.reset (fl_ptr = new ExportFormatLinear ("IRCAM", ExportFormatBase::F_IRCAM));
155  fl_ptr->set_extension ("sf");
156  add_format (f_ptr);
157 
158  f_ptr.reset (fl_ptr = new ExportFormatLinear ("WAV", ExportFormatBase::F_WAV));
167  fl_ptr->set_extension ("wav");
168  add_format (f_ptr);
169 
170  f_ptr.reset (fl_ptr = new ExportFormatLinear ("W64", ExportFormatBase::F_W64));
178  fl_ptr->set_extension ("w64");
179  add_format (f_ptr);
180 
181  f_ptr.reset (fl_ptr = new ExportFormatLinear ("CAF", ExportFormatBase::F_CAF));
189  fl_ptr->set_extension ("caf");
190  add_format (f_ptr);
191 
192  f_ptr.reset (fl_ptr = new ExportFormatLinear ("RAW", ExportFormatBase::F_RAW));
201  fl_ptr->set_extension ("raw");
202  add_format (f_ptr);
203 
204  try {
205  f_ptr.reset (new ExportFormatOggVorbis ());
206  add_format (f_ptr);
207  } catch (ExportFormatIncompatible & e) {}
208 
209  try {
210  f_ptr.reset (new ExportFormatFLAC ());
211  add_format (f_ptr);
212  } catch (ExportFormatIncompatible & e) {}
213 }
214 
215 void
217 {
226 }
227 
228 void
230 {
231  compatibilities.push_back (ptr);
232  ptr->SelectChanged.connect_same_thread (*this,
234  this, _1, WeakExportFormatCompatibilityPtr (ptr)));
235 }
236 
237 void
239 {
240  ptr->SelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_quality_selection, this, _1, WeakQualityPtr (ptr)));
241  qualities.push_back (ptr);
242 }
243 
244 void
246 {
247  formats.push_back (ptr);
248  ptr->SelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_format_selection, this, _1, WeakExportFormatPtr (ptr)));
249  universal_set = universal_set->get_union (*ptr);
250 
251  /* Encoding options */
252 
254 
255  if ((hsf = boost::dynamic_pointer_cast<HasSampleFormat> (ptr))) {
256  hsf->SampleFormatSelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_sample_format_selection, this, _1, _2));
257  hsf->DitherTypeSelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_dither_type_selection, this, _1, _2));
258  }
259 }
260 
261 void
263 {
264  ptr->SelectChanged.connect_same_thread (*this, boost::bind (&ExportFormatManager::change_sample_rate_selection, this, _1, WeakSampleRatePtr (ptr)));
265  sample_rates.push_back (ptr);
266 }
267 
268 void
270 {
271  current_selection->set_name (name);
273 }
274 
275 void
277 {
278  current_selection->set_src_quality (value);
280 }
281 
282 void
284 {
285  current_selection->set_with_cue (value);
287 }
288 
289 void
291 {
292  current_selection->set_with_toc (value);
294 }
295 
296 void
298 {
299  current_selection->set_with_mp4chaps (value);
301 }
302 
303 void
304 ExportFormatManager::set_command (std::string command)
305 {
306  current_selection->set_command (command);
308 }
309 
310 void
312 {
313  current_selection->set_trim_beginning (value);
315 }
316 
317 void
319 {
320  current_selection->set_silence_beginning (time);
322 }
323 
324 void
326 {
327  current_selection->set_trim_end (value);
329 }
330 
331 void
333 {
334  current_selection->set_silence_end (time);
336 }
337 
338 void
340 {
341  current_selection->set_normalize (value);
343 }
344 
345 void
347 {
348  current_selection->set_normalize_target (value);
350 }
351 
352 void
354 {
355  current_selection->set_tag (tag);
357 }
358 
359 void
361 {
362  bool do_selection_changed = !pending_selection_change;
365  }
366 
367  ExportFormatCompatibilityPtr ptr = compat.lock();
368 
369  if (ptr && select) {
370  select_compatibility (ptr);
371  }
372 
373  if (do_selection_changed) {
375  }
376 }
377 
378 void
380 {
381  QualityPtr ptr = quality.lock ();
382 
383  if (!ptr) {
384  return;
385  }
386 
387  if (select) {
388  select_quality (ptr);
389  } else if (ptr->quality == current_selection->quality()) {
390  ptr.reset();
391  select_quality (ptr);
392  }
393 }
394 
395 void
397 {
398  ExportFormatPtr ptr = format.lock();
399 
400  if (!ptr) {
401  return;
402  }
403 
404  if (select) {
405  select_format (ptr);
406  } else if (ptr->get_format_id() == current_selection->format_id()) {
407  ptr.reset();
408  select_format (ptr);
409  }
410 }
411 
412 void
414 {
415  SampleRatePtr ptr = rate.lock();
416 
417  if (!ptr) {
418  return;
419  }
420 
421  if (select) {
422  select_sample_rate (ptr);
423  } else if (ptr->rate == current_selection->sample_rate()) {
424  ptr.reset();
425  select_sample_rate (ptr);
426  }
427 }
428 
429 void
431 {
432  SampleFormatPtr ptr = format.lock();
433 
434  if (!ptr) {
435  return;
436  }
437 
438  if (select) {
439  select_sample_format (ptr);
440  } else if (ptr->format == current_selection->sample_format()) {
441  ptr.reset();
442  select_sample_format (ptr);
443  }
444 }
445 
446 void
448 {
449  DitherTypePtr ptr = type.lock();
450 
451  if (!ptr) {
452  return;
453  }
454 
455  if (select) {
456  select_dither_type (ptr);
457  } else if (ptr->type == current_selection->dither_type()) {
458  ptr.reset();
459  select_dither_type (ptr);
460  }
461 }
462 
463 void
465 {
466  /* Calculate compatibility intersection for the selection */
467 
469 
470  /* Unselect incompatible items */
471 
472  boost::shared_ptr<ExportFormatBase> select_intersect;
473 
474  select_intersect = compat_intersect->get_intersection (*current_selection);
475  if (select_intersect->qualities_empty()) {
477  }
478 
479  select_intersect = compat_intersect->get_intersection (*current_selection);
480  if (select_intersect->formats_empty()) {
482  }
483 
484  select_intersect = compat_intersect->get_intersection (*current_selection);
485  if (select_intersect->sample_rates_empty()) {
487  }
488 
489  select_intersect = compat_intersect->get_intersection (*current_selection);
490  if (select_intersect->sample_formats_empty()) {
492  }
493 }
494 
495 void
497 {
498  bool do_selection_changed = !pending_selection_change;
501  }
502 
503  if (quality) {
504  current_selection->set_quality (quality->quality);
505 
506  /* Deselect format if it is incompatible */
507 
509  if (format && !format->has_quality (quality->quality)) {
510  format->set_selected (false);
511  }
512 
513  } else {
515 
516  QualityPtr current_quality = get_selected_quality();
517  if (current_quality) {
518  current_quality->set_selected (false);
519  }
520 
521  /* Note:
522  * A quality is never explicitly deselected without also deselecting the format
523  * so we don't need to deselect the format here.
524  * doing so causes extra complications
525  */
526  }
527 
528  if (do_selection_changed) {
530  }
531 }
532 
533 void
535 {
536  bool do_selection_changed = !pending_selection_change;
539  }
540 
541  current_selection->set_format (format);
542 
543  if (format) {
544 
545  /* Slect right quality for format */
546 
547  ExportFormatBase::Quality quality = format->get_quality();
548  for (QualityList::iterator it = qualities.begin (); it != qualities.end (); ++it) {
549  if ((*it)->quality == quality) {
550  (*it)->set_selected (true);
551  } else {
552  (*it)->set_selected (false);
553  }
554  }
555 
556  /* Handle sample formats */
557 
558  ExportFormatBase::SampleFormat format_to_select;
559  if (format->sample_format_is_compatible (current_selection->sample_format())) {
560  format_to_select = current_selection->sample_format();
561  } else {
562  format_to_select = format->default_sample_format();
563  }
564 
566  if ((hsf = boost::dynamic_pointer_cast<HasSampleFormat> (format))) {
567  SampleFormatList sample_formats = hsf->get_sample_formats();
568  for (SampleFormatList::iterator it = sample_formats.begin (); it != sample_formats.end (); ++it) {
569  if ((*it)->format == format_to_select) {
570  (*it)->set_selected (true);
571  } else {
572  (*it)->set_selected (false);
573  }
574  }
575  }
576 
577  current_selection->set_sample_format (format_to_select);
578 
579  } else {
580  ExportFormatPtr current_format = get_selected_format ();
581  if (current_format) {
582  current_format->set_selected (false);
583  }
584  }
585 
586  if (do_selection_changed) {
588  }
589 }
590 
591 void
593 {
594 
595  bool do_selection_changed = !pending_selection_change;
598  }
599 
600  if (rate) {
601  current_selection->set_sample_rate (rate->rate);
602  } else {
603  current_selection->set_sample_rate (ExportFormatBase::SR_None);
604 
605  SampleRatePtr current_rate = get_selected_sample_rate();
606  if (current_rate) {
607  current_rate->set_selected (false);
608  }
609  }
610 
611  if (do_selection_changed) {
613  }
614 }
615 
616 void
618 {
619 
620  bool do_selection_changed = !pending_selection_change;
623  }
624 
625  if (format) {
626  current_selection->set_sample_format (format->format);
627  } else {
628  current_selection->set_sample_format (ExportFormatBase::SF_None);
629 
630  SampleFormatPtr current_format = get_selected_sample_format();
631  if (current_format) {
632  current_format->set_selected (false);
633  }
634  }
635 
636  if (do_selection_changed) {
638  }
639 }
640 
641 void
643 {
644 
645  bool do_selection_changed = !pending_selection_change;
648  }
649 
650  if (type) {
651  current_selection->set_dither_type (type->type);
652  } else {
653  current_selection->set_dither_type (ExportFormatBase::D_None);
654  }
655 
656  if (do_selection_changed) {
658  }
659 }
660 
661 void
663 {
664  /* Get a list of incompatible compatibility selections */
665 
666  CompatList incompatibles;
667  for (CompatList::iterator it = compatibilities.begin(); it != compatibilities.end(); ++it) {
668  if (!current_selection->is_compatible_with (**it)) {
669  incompatibles.push_back (*it);
670  }
671  }
672 
673  /* Deselect them */
674 
675  for (CompatList::iterator it = incompatibles.begin(); it != incompatibles.end(); ++it) {
676  (*it)->set_selected (false);
677  }
678 
679  /* Mark compatibility for everything necessary */
680 
681  std::set<ExportFormatBase::Quality> compatible_qualities;
683  ExportFormatCompatibility global_compat (*compat_intersect);
684 
685  for (FormatList::iterator it = formats.begin(); it != formats.end(); ++it) {
686  if ((*it)->set_compatibility_state (global_compat)) {
687  compatible_qualities.insert ((*it)->get_quality());
688  }
689  }
690 
691  bool any_quality_compatible = true;
692  for (QualityList::iterator it = qualities.begin(); it != qualities.end(); ++it) {
693  if (compatible_qualities.find((*it)->quality) != compatible_qualities.end()) {
694  (*it)->set_compatible (true);
695 
696  } else {
697  (*it)->set_compatible (false);
698 
699  if ((*it)->quality != ExportFormatBase::Q_Any) {
700  any_quality_compatible = false;
701  }
702  }
703  }
704 
705  if (any_quality_compatible) {
706  for (QualityList::iterator it = qualities.begin(); it != qualities.end(); ++it) {
707  if ((*it)->quality == ExportFormatBase::Q_Any) {
708  (*it)->set_compatible (true);
709  break;
710  }
711  }
712  }
713 
714  for (SampleRateList::iterator it = sample_rates.begin(); it != sample_rates.end(); ++it) {
715  if (compat_intersect->has_sample_rate ((*it)->rate)) {
716  (*it)->set_compatible (true);
717  } else {
718  (*it)->set_compatible (false);
719  }
720  }
721 
723  if ((hsf = boost::dynamic_pointer_cast<HasSampleFormat> (get_selected_format()))) {
724 
725  SampleFormatList sf_list = hsf->get_sample_formats();
726  for (SampleFormatList::iterator it = sf_list.begin(); it != sf_list.end(); ++it) {
727  if (compat_intersect->has_sample_format ((*it)->format)) {
728  (*it)->set_compatible (true);
729  } else {
730  (*it)->set_compatible (false);
731  }
732  }
733 
734  }
735 
736  /* Signal completeness and possible description change */
737 
738  CompleteChanged (current_selection->is_complete());
740 
741  /* Reset pending state */
742 
743  pending_selection_change = false;
744 }
745 
746 void
748 {
749  std::string new_description = current_selection->description();
750  if (new_description == prev_description) { return; }
751 
752  prev_description = new_description;
754 }
755 
758 {
759  for (QualityList::iterator it = qualities.begin(); it != qualities.end(); ++it) {
760  if ((*it)->selected()) {
761  return *it;
762  }
763  }
764 
765  return QualityPtr();
766 }
767 
770 {
771  ExportFormatPtr format;
772 
773  for (FormatList::iterator it = formats.begin(); it != formats.end(); ++it) {
774  if ((*it)->selected()) {
775  return *it;
776  }
777  }
778 
779  return format;
780 }
781 
784 {
785  for (SampleRateList::iterator it = sample_rates.begin(); it != sample_rates.end(); ++it) {
786  if ((*it)->selected()) {
787  return *it;
788  }
789  }
790 
791  return SampleRatePtr();
792 }
793 
796 {
798 
799  if ((hsf = boost::dynamic_pointer_cast<HasSampleFormat> (get_selected_format()))) {
800  return hsf->get_selected_sample_format ();
801  } else {
802  return SampleFormatPtr ();
803  }
804 }
805 
806 
809 {
810  ExportFormatBasePtr compat_intersect = universal_set;
811 
812  for (CompatList::iterator it = compatibilities.begin(); it != compatibilities.end(); ++it) {
813  if ((*it)->selected ()) {
814  compat_intersect = compat_intersect->get_intersection (**it);
815  }
816  }
817 
818  return compat_intersect;
819 }
820 
821 }; // namespace ARDOUR
void set_extension(std::string const &extension)
HasSampleFormat::SampleFormatPtr SampleFormatPtr
void select_format(ExportFormatPtr const &format)
boost::shared_ptr< SampleRateState > SampleRatePtr
void add_compatibility(ExportFormatCompatibilityPtr ptr)
void add_sample_format(ExportFormatBase::SampleFormat format)
boost::shared_ptr< ExportFormat > ExportFormatPtr
void select_sample_rate(SampleRatePtr const &rate)
void select_compatibility(WeakExportFormatCompatibilityPtr const &compat)
std::list< ExportFormatCompatibilityPtr > CompatList
SampleFormatPtr get_selected_sample_format()
void select_quality(QualityPtr const &quality)
#define _(Text)
Definition: i18n.h:11
ExportFormatManager(ExportFormatSpecPtr specification)
HasSampleFormat::SampleFormatList SampleFormatList
void select_silence_beginning(AnyTime const &time)
ExportFormatSpecPtr current_selection
void change_compatibility_selection(bool select, WeakExportFormatCompatibilityPtr const &compat)
void change_sample_format_selection(bool select, WeakSampleFormatPtr const &format)
void change_sample_rate_selection(bool select, WeakSampleRatePtr const &rate)
Definition: amp.h:29
void add_sample_rate(SampleRatePtr ptr)
void add_format(ExportFormatPtr ptr)
ExportFormatBasePtr get_compatibility_intersection()
void change_quality_selection(bool select, WeakQualityPtr const &quality)
void change_dither_type_selection(bool select, WeakDitherTypePtr const &type)
const char * name
PBD::Signal1< void, bool > CompleteChanged
void select_silence_end(AnyTime const &time)
void select_sample_format(SampleFormatPtr const &format)
LIBARDOUR_API PBD::PropertyDescriptor< bool > select
Definition: route_group.cc:48
void select_dither_type(DitherTypePtr const &type)
Allows adding to all sets. A format should be able to test if it is compatible with this...
void change_format_selection(bool select, WeakExportFormatPtr const &format)
void set_default_sample_format(SampleFormat sf)
void add_endianness(Endianness endianness)
boost::shared_ptr< QualityState > QualityPtr
PBD::Signal0< void > DescriptionChanged
void select_src_quality(ExportFormatBase::SRCQuality value)