Remove ambiguous API implementation
[ardour.git] / libs / ardour / export_formats.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_formats.h"
22
23 #include "pbd/i18n.h"
24
25 using namespace std;
26
27 namespace ARDOUR
28 {
29
30 bool
31 ExportFormat::has_sample_format ()
32 {
33         return dynamic_cast<HasSampleFormat *> (this);
34 }
35
36 bool
37 ExportFormat::has_codec_quality ()
38 {
39         return dynamic_cast<HasCodecQuality *> (this);
40 }
41
42
43 bool
44 ExportFormat::sample_format_is_compatible (SampleFormat format) const
45 {
46         return (sample_formats.find (format) != sample_formats.end());
47 }
48
49 /*** HasSampleFormat ***/
50
51 HasSampleFormat::HasSampleFormat (ExportFormatBase::SampleFormatSet & sample_formats) :
52   _sample_formats (sample_formats)
53 {
54         /* Dither Types */
55
56         add_dither_type (ExportFormatBase::D_Shaped, _("Shaped Noise"));
57         add_dither_type (ExportFormatBase::D_Tri, _("Triangular"));
58         add_dither_type (ExportFormatBase::D_Rect, _("Rectangular"));
59         add_dither_type (ExportFormatBase::D_None,  _("None"));
60 }
61
62 void
63 HasSampleFormat::add_sample_format (ExportFormatBase::SampleFormat format)
64 {
65         _sample_formats.insert (format);
66
67         SampleFormatPtr ptr (new SampleFormatState (format, get_sample_format_name (format)));
68         sample_format_states.push_back (ptr);
69         ptr->SelectChanged.connect_same_thread (*this, boost::bind (&HasSampleFormat::update_sample_format_selection, this, _1));
70         // BOOST SIGNALS Could this be made any uglier?
71         ptr->SelectChanged.connect_same_thread (*this,
72                 boost::bind (boost::type<void> (), boost::ref (SampleFormatSelectChanged), _1, WeakSampleFormatPtr (ptr)));
73         ptr->CompatibleChanged.connect_same_thread (*this,
74                 boost::bind (boost::type<void> (), boost::ref (SampleFormatCompatibleChanged), _1, WeakSampleFormatPtr (ptr)));
75 }
76
77 void
78 HasSampleFormat::add_dither_type (ExportFormatBase::DitherType type, string name)
79 {
80         DitherTypePtr ptr (new DitherTypeState (type, name));
81         dither_type_states.push_back (ptr);
82         ptr->SelectChanged.connect_same_thread (*this, boost::bind (&HasSampleFormat::update_dither_type_selection, this, _1));
83         // BOOST SIGNALS Could this be made any uglier?
84         ptr->SelectChanged.connect_same_thread (*this,
85                 boost::bind (boost::type<void> (), boost::ref (DitherTypeSelectChanged), _1, WeakDitherTypePtr (ptr)));
86         ptr->CompatibleChanged.connect_same_thread (*this,
87                 boost::bind (boost::type<void> (),boost::ref ( DitherTypeCompatibleChanged), _1, WeakDitherTypePtr (ptr)));
88 }
89
90 HasSampleFormat::SampleFormatPtr
91 HasSampleFormat::get_selected_sample_format ()
92 {
93         for (SampleFormatList::iterator it = sample_format_states.begin(); it != sample_format_states.end(); ++it) {
94                 if ((*it)->selected()) {
95                         return *it;
96                 }
97         }
98
99         return SampleFormatPtr();
100 }
101
102 HasSampleFormat::DitherTypePtr
103 HasSampleFormat::get_selected_dither_type ()
104 {
105         for (DitherTypeList::iterator it = dither_type_states.begin(); it != dither_type_states.end(); ++it) {
106                 if ((*it)->selected()) {
107                         return *it;
108                 }
109         }
110
111         return DitherTypePtr();
112 }
113
114 void
115 HasSampleFormat::update_sample_format_selection (bool)
116 {
117         SampleFormatPtr format = get_selected_sample_format();
118         if (!format) {
119                 return;
120         }
121
122         if (format->format == ExportFormatBase::SF_24 ||
123             format->format == ExportFormatBase::SF_32 ||
124             format->format == ExportFormatBase::SF_Float ||
125             format->format == ExportFormatBase::SF_Double) {
126                 for (DitherTypeList::iterator it = dither_type_states.begin(); it != dither_type_states.end(); ++it) {
127                         if ((*it)->type == ExportFormatBase::D_None) {
128                                 (*it)->set_selected (true);
129                         } else {
130                                 (*it)->set_compatible (false);
131                         }
132                 }
133
134         } else {
135                 for (DitherTypeList::iterator it = dither_type_states.begin(); it != dither_type_states.end(); ++it) {
136                         (*it)->set_compatible (true);
137                 }
138         }
139 }
140
141 void
142 HasSampleFormat::update_dither_type_selection (bool)
143 {
144         DitherTypePtr type = get_selected_dither_type();
145         if (!type) {
146                 return;
147         }
148
149         if (!type->compatible()) {
150                 SampleFormatPtr format = get_selected_sample_format();
151                 if (format) {
152                         format->set_selected (false);
153                 }
154
155                 for (DitherTypeList::iterator it = dither_type_states.begin(); it != dither_type_states.end(); ++it) {
156                         (*it)->set_compatible (true);
157                 }
158         }
159 }
160
161 string
162 HasSampleFormat::get_sample_format_name (ExportFormatBase::SampleFormat format)
163 {
164         switch (format) {
165           case ExportFormatBase::SF_8:
166                 return _("8-bit");
167           case ExportFormatBase::SF_16:
168                 return _("16-bit");
169           case ExportFormatBase::SF_24:
170                 return _("24-bit");
171           case ExportFormatBase::SF_32:
172                 return _("32-bit");
173           case ExportFormatBase::SF_Float:
174                 return _("float");
175           case ExportFormatBase::SF_Double:
176                 return _("double");
177           case ExportFormatBase::SF_U8:
178                 return _("8-bit unsigned");
179           case ExportFormatBase::SF_Vorbis:
180                 return _("Vorbis sample format");
181           case ExportFormatBase::SF_None:
182                 return _("No sample format");
183         }
184         return "";
185 }
186
187 /*** Linear ***/
188
189 ExportFormatLinear::ExportFormatLinear (string name, FormatId format_id) :
190   HasSampleFormat (sample_formats),
191   _default_sample_format (SF_None)
192 {
193         set_name (name);
194         set_format_id (format_id);
195
196         add_sample_rate (SR_8);
197         add_sample_rate (SR_22_05);
198         add_sample_rate (SR_44_1);
199         add_sample_rate (SR_48);
200         add_sample_rate (SR_88_2);
201         add_sample_rate (SR_96);
202         add_sample_rate (SR_176_4);
203         add_sample_rate (SR_192);
204         add_sample_rate (SR_Session);
205
206         add_endianness (E_FileDefault);
207
208         set_quality (Q_LosslessLinear);
209 }
210
211 bool
212 ExportFormatLinear::set_compatibility_state (ExportFormatCompatibility const & compatibility)
213 {
214         /* Global state */
215
216         bool compatible = true;
217
218         if (!compatibility.has_quality (Q_LosslessLinear)) {
219                 compatible = false;
220         }
221
222         if (!compatibility.has_format (get_format_id())) {
223                 compatible = false;
224         }
225
226         boost::shared_ptr<ExportFormatBase> intersection = get_intersection (compatibility);
227
228         if (intersection->endiannesses_empty()) {
229                 compatible = false;
230         }
231
232         if (intersection->sample_rates_empty()) {
233                 compatible = false;
234         }
235
236         if (intersection->sample_formats_empty()) {
237                 compatible = false;
238         }
239
240         set_compatible (compatible);
241
242         /* Sample Formats */
243
244         for (SampleFormatList::iterator it = sample_format_states.begin(); it != sample_format_states.end(); ++it) {
245                 (*it)->set_compatible (compatibility.has_sample_format ((*it)->format));
246         }
247
248         return compatible;
249 }
250
251 /*** Ogg Vorbis ***/
252
253 ExportFormatOggVorbis::ExportFormatOggVorbis ()
254 {
255         /* Check system compatibility */
256
257         SF_INFO sf_info;
258         sf_info.channels = 2;
259         sf_info.samplerate = SR_44_1;
260         sf_info.format = F_Ogg | SF_Vorbis;
261         if (sf_format_check (&sf_info) != SF_TRUE) {
262                 throw ExportFormatIncompatible();
263         }
264
265         set_name ("Ogg Vorbis");
266         set_format_id (F_Ogg);
267         sample_formats.insert (SF_Vorbis);
268
269         add_sample_rate (SR_22_05);
270         add_sample_rate (SR_44_1);
271         add_sample_rate (SR_48);
272         add_sample_rate (SR_88_2);
273         add_sample_rate (SR_96);
274         add_sample_rate (SR_176_4);
275         add_sample_rate (SR_192);
276         add_sample_rate (SR_Session);
277
278         /* these are 100 vorbis_encode_init_vbr() quality */
279         add_codec_quality ("Low (0)",           0);
280         add_codec_quality ("Default (4)",      40);
281         add_codec_quality ("High (6)",         60);
282         add_codec_quality ("Very High (10)",  100);
283
284         add_endianness (E_FileDefault);
285
286         set_extension ("ogg");
287         set_quality (Q_LossyCompression);
288 }
289
290 bool
291 ExportFormatOggVorbis::set_compatibility_state (ExportFormatCompatibility const & compatibility)
292 {
293         bool compatible = compatibility.has_format (F_Ogg);
294         set_compatible (compatible);
295         return compatible;
296 }
297
298 /*** FLAC ***/
299
300 ExportFormatFLAC::ExportFormatFLAC () :
301   HasSampleFormat (sample_formats)
302 {
303         /* Check system compatibility */
304
305         SF_INFO sf_info;
306         sf_info.channels = 2;
307         sf_info.samplerate = SR_44_1;
308         sf_info.format = F_FLAC | SF_16;
309         if (sf_format_check (&sf_info) != SF_TRUE) {
310                 throw ExportFormatIncompatible();
311         }
312
313         set_name ("FLAC");
314         set_format_id (F_FLAC);
315
316         add_sample_rate (SR_22_05);
317         add_sample_rate (SR_44_1);
318         add_sample_rate (SR_48);
319         add_sample_rate (SR_88_2);
320         add_sample_rate (SR_96);
321         add_sample_rate (SR_176_4);
322         add_sample_rate (SR_192);
323         add_sample_rate (SR_Session);
324
325         add_sample_format (SF_8);
326         add_sample_format (SF_16);
327         add_sample_format (SF_24);
328
329         add_endianness (E_FileDefault);
330
331         set_extension ("flac");
332         set_quality (Q_LosslessCompression);
333 }
334
335 bool
336 ExportFormatFLAC::set_compatibility_state (ExportFormatCompatibility const & compatibility)
337 {
338         bool compatible = compatibility.has_format (F_FLAC);
339         set_compatible (compatible);
340         return compatible;
341 }
342
343 /*** BWF ***/
344
345 ExportFormatBWF::ExportFormatBWF () :
346   HasSampleFormat (sample_formats)
347 {
348         set_name ("BWF");
349         set_format_id (F_WAV);
350
351         add_sample_rate (SR_22_05);
352         add_sample_rate (SR_44_1);
353         add_sample_rate (SR_48);
354         add_sample_rate (SR_88_2);
355         add_sample_rate (SR_96);
356         add_sample_rate (SR_176_4);
357         add_sample_rate (SR_192);
358         add_sample_rate (SR_Session);
359
360         add_sample_format (SF_U8);
361         add_sample_format (SF_16);
362         add_sample_format (SF_24);
363         add_sample_format (SF_32);
364         add_sample_format (SF_Float);
365         add_sample_format (SF_Double);
366
367         add_endianness (E_FileDefault);
368
369         set_extension ("wav");
370         set_quality (Q_LosslessLinear);
371 }
372
373 bool
374 ExportFormatBWF::set_compatibility_state (ExportFormatCompatibility const & compatibility)
375 {
376         bool compatible = compatibility.has_format (F_WAV);
377         set_compatible (compatible);
378         return compatible;
379 }
380
381
382 /*** FFMPEG Pipe ***/
383
384 ExportFormatFFMPEG::ExportFormatFFMPEG (std::string const& name, std::string const& ext)
385 {
386         set_name (name);
387         set_format_id (F_FFMPEG);
388         sample_formats.insert (SF_Float);
389
390         add_sample_rate (SR_8);
391         add_sample_rate (SR_22_05);
392         add_sample_rate (SR_44_1);
393         add_sample_rate (SR_48);
394         add_sample_rate (SR_Session);
395
396         add_endianness (E_Little);
397
398         add_codec_quality ("VBR 220-260 kb/s",  0);
399         add_codec_quality ("VBR 190-250 kb/s", -1);
400         add_codec_quality ("VBR 170-210 kb/s", -2);
401         add_codec_quality ("VBR 150-195 kb/s", -3);
402         add_codec_quality ("VBR 140-185 kb/s", -4);
403         add_codec_quality ("VBR 120-150 kb/s", -5);
404         add_codec_quality ("VBR 100-130 kb/s", -6);
405         add_codec_quality ("VBR 80-120 kb/s",  -7);
406         add_codec_quality ("VBR 70-105 kb/s",  -8);
407         add_codec_quality ("VBR 45-85 kb/s",   -9);
408         /*  Available CBR options are:
409          *  8, 16, 24, 32, 40, 48, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320
410          */
411         add_codec_quality ("CBR  64 kb/s",     64);
412         add_codec_quality ("CBR 128 kb/s",    128);
413         add_codec_quality ("CBR 160 kb/s",    160);
414         add_codec_quality ("CBR 192 kb/s",    192);
415         add_codec_quality ("CBR 256 kb/s",    256);
416
417         set_extension (ext);
418         set_quality (Q_LossyCompression);
419 }
420
421 bool
422 ExportFormatFFMPEG::set_compatibility_state (ExportFormatCompatibility const & compatibility)
423 {
424         bool compatible = compatibility.has_format (F_FFMPEG);
425         set_compatible (compatible);
426         return compatible;
427 }
428
429
430 }; // namespace ARDOUR