use new syntax for connecting to backend signals that enforces explicit connection...
[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 "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::sample_format_is_compatible (SampleFormat format) const
38 {
39         return (sample_formats.find (format) != sample_formats.end());
40 }
41
42 /*** HasSampleFormat ***/
43
44 HasSampleFormat::HasSampleFormat (ExportFormatBase::SampleFormatSet & sample_formats) :
45   _sample_formats (sample_formats)
46 {
47         /* Dither Types */
48
49         add_dither_type (ExportFormatBase::D_Shaped, _("Shaped Noise"));
50         add_dither_type (ExportFormatBase::D_Tri, _("Triangular"));
51         add_dither_type (ExportFormatBase::D_Rect, _("Rectangular"));
52         add_dither_type (ExportFormatBase::D_None,  _("None"));
53 }
54
55 void
56 HasSampleFormat::add_sample_format (ExportFormatBase::SampleFormat format)
57 {
58         _sample_formats.insert (format);
59
60         SampleFormatPtr ptr (new SampleFormatState (format, get_sample_format_name (format)));
61         sample_format_states.push_back (ptr);
62         ptr->SelectChanged.connect (*this, boost::bind (&HasSampleFormat::update_sample_format_selection, this, _1));
63         // BOOST SIGNALS how to connect one signal to another
64         // ptr->SelectChanged.connect (*this, boost::bind (SampleFormatSelectChanged, _1, WeakSampleFormatPtr (ptr));
65         // ptr->CompatibleChanged.connect (*this, boost::bind (SampleFormatCompatibleChanged, _1, WeakSampleFormatPtr (ptr));
66 }
67
68 void
69 HasSampleFormat::add_dither_type (ExportFormatBase::DitherType type, Glib::ustring name)
70 {
71         DitherTypePtr ptr (new DitherTypeState (type, name));
72         dither_type_states.push_back (ptr);
73         ptr->SelectChanged.connect (*this, boost::bind (&HasSampleFormat::update_dither_type_selection, this, _1));
74         // BOOST SIGNALS how to connect one signal to another
75         // ptr->SelectChanged.connect (*this, boost::bind (DitherTypeSelectChanged, _1, WeakDitherTypePtr (ptr));
76         // ptr->CompatibleChanged.connect (*this, boost::bind (DitherTypeCompatibleChanged, _1, WeakDitherTypePtr (ptr));
77 }
78
79 HasSampleFormat::SampleFormatPtr
80 HasSampleFormat::get_selected_sample_format ()
81 {
82         for (SampleFormatList::iterator it = sample_format_states.begin(); it != sample_format_states.end(); ++it) {
83                 if ((*it)->selected()) {
84                         return *it;
85                 }
86         }
87
88         return SampleFormatPtr();
89 }
90
91 HasSampleFormat::DitherTypePtr
92 HasSampleFormat::get_selected_dither_type ()
93 {
94         for (DitherTypeList::iterator it = dither_type_states.begin(); it != dither_type_states.end(); ++it) {
95                 if ((*it)->selected()) {
96                         return *it;
97                 }
98         }
99
100         return DitherTypePtr();
101 }
102
103 void
104 HasSampleFormat::update_sample_format_selection (bool)
105 {
106         SampleFormatPtr format = get_selected_sample_format();
107         if (!format) {
108                 return;
109         }
110
111         if (format->format == ExportFormatBase::SF_24 ||
112             format->format == ExportFormatBase::SF_32 ||
113             format->format == ExportFormatBase::SF_Float ||
114             format->format == ExportFormatBase::SF_Double) {
115                 for (DitherTypeList::iterator it = dither_type_states.begin(); it != dither_type_states.end(); ++it) {
116                         if ((*it)->type == ExportFormatBase::D_None) {
117                                 (*it)->set_selected (true);
118                         } else {
119                                 (*it)->set_compatible (false);
120                         }
121                 }
122
123         } else {
124                 for (DitherTypeList::iterator it = dither_type_states.begin(); it != dither_type_states.end(); ++it) {
125                         (*it)->set_compatible (true);
126                 }
127         }
128 }
129
130 void
131 HasSampleFormat::update_dither_type_selection (bool)
132 {
133         DitherTypePtr type = get_selected_dither_type();
134         if (!type) {
135                 return;
136         }
137
138         if (!type->compatible()) {
139                 SampleFormatPtr format = get_selected_sample_format();
140                 if (format) {
141                         format->set_selected (false);
142                 }
143
144                 for (DitherTypeList::iterator it = dither_type_states.begin(); it != dither_type_states.end(); ++it) {
145                         (*it)->set_compatible (true);
146                 }
147         }
148 }
149
150 string
151 HasSampleFormat::get_sample_format_name (ExportFormatBase::SampleFormat format)
152 {
153         switch (format) {
154           case ExportFormatBase::SF_8:
155                 return _("8bit");
156           case ExportFormatBase::SF_16:
157                 return _("16bit");
158           case ExportFormatBase::SF_24:
159                 return _("24bit");
160           case ExportFormatBase::SF_32:
161                 return _("32bit");
162           case ExportFormatBase::SF_Float:
163                 return _("float");
164           case ExportFormatBase::SF_Double:
165                 return _("double");
166           case ExportFormatBase::SF_U8:
167                 return _("8bit unsigned");
168           case ExportFormatBase::SF_Vorbis:
169                 return _("Vorbis sample format");
170           case ExportFormatBase::SF_None:
171                 return _("No sample format");
172         }
173         return "";
174 }
175
176 /*** Linear ***/
177
178 ExportFormatLinear::ExportFormatLinear (Glib::ustring name, FormatId format_id) :
179   HasSampleFormat (sample_formats),
180   _default_sample_format (SF_None)
181 {
182         set_name (name);
183         set_format_id (format_id);
184
185         add_sample_rate (SR_22_05);
186         add_sample_rate (SR_44_1);
187         add_sample_rate (SR_48);
188         add_sample_rate (SR_88_2);
189         add_sample_rate (SR_96);
190         add_sample_rate (SR_192);
191
192         add_endianness (E_FileDefault);
193
194         set_quality (Q_LosslessLinear);
195 }
196
197 bool
198 ExportFormatLinear::set_compatibility_state (ExportFormatCompatibility const & compatibility)
199 {
200         /* Global state */
201
202         bool compatible = true;
203
204         if (!compatibility.has_quality (Q_LosslessLinear)) {
205                 compatible = false;
206         }
207
208         if (!compatibility.has_format (get_format_id())) {
209                 compatible = false;
210         }
211
212         boost::shared_ptr<ExportFormatBase> intersection = get_intersection (compatibility);
213
214         if (intersection->endiannesses_empty()) {
215                 compatible = false;
216         }
217
218         if (intersection->sample_rates_empty()) {
219                 compatible = false;
220         }
221
222         if (intersection->sample_formats_empty()) {
223                 compatible = false;
224         }
225
226         set_compatible (compatible);
227
228         /* Sample Formats */
229
230         for (SampleFormatList::iterator it = sample_format_states.begin(); it != sample_format_states.end(); ++it) {
231                 (*it)->set_compatible (compatibility.has_sample_format ((*it)->format));
232         }
233
234         return compatible;
235 }
236
237 /*** Ogg Vorbis ***/
238
239 ExportFormatOggVorbis::ExportFormatOggVorbis ()
240 {
241         /* Check system compatibility */
242
243         SF_INFO sf_info;
244         sf_info.channels = 2;
245         sf_info.samplerate = SR_44_1;
246         sf_info.format = F_Ogg | SF_Vorbis;
247         if (sf_format_check (&sf_info) != SF_TRUE) {
248                 throw ExportFormatIncompatible();
249         }
250
251         set_name ("Ogg Vorbis");
252         set_format_id (F_Ogg);
253         sample_formats.insert (SF_Vorbis);
254
255         add_sample_rate (SR_22_05);
256         add_sample_rate (SR_44_1);
257         add_sample_rate (SR_48);
258         add_sample_rate (SR_88_2);
259         add_sample_rate (SR_96);
260         add_sample_rate (SR_192);
261
262         add_endianness (E_FileDefault);
263
264         set_extension ("ogg");
265         set_quality (Q_LossyCompression);
266 }
267
268 bool
269 ExportFormatOggVorbis::set_compatibility_state (ExportFormatCompatibility const & compatibility)
270 {
271         bool compatible = compatibility.has_format (F_Ogg);
272         set_compatible (compatible);
273         return compatible;
274 }
275
276 /*** FLAC ***/
277
278 ExportFormatFLAC::ExportFormatFLAC () :
279   HasSampleFormat (sample_formats)
280 {
281         /* Check system compatibility */
282
283         SF_INFO sf_info;
284         sf_info.channels = 2;
285         sf_info.samplerate = SR_44_1;
286         sf_info.format = F_FLAC | SF_16;
287         if (sf_format_check (&sf_info) != SF_TRUE) {
288                 throw ExportFormatIncompatible();
289         }
290
291         set_name ("FLAC");
292         set_format_id (F_FLAC);
293
294         add_sample_rate (SR_22_05);
295         add_sample_rate (SR_44_1);
296         add_sample_rate (SR_48);
297         add_sample_rate (SR_88_2);
298         add_sample_rate (SR_96);
299         add_sample_rate (SR_192);
300
301         add_sample_format (SF_8);
302         add_sample_format (SF_16);
303         add_sample_format (SF_24);
304
305         add_endianness (E_FileDefault);
306
307         set_extension ("flac");
308         set_quality (Q_LosslessCompression);
309 }
310
311 bool
312 ExportFormatFLAC::set_compatibility_state (ExportFormatCompatibility const & compatibility)
313 {
314         bool compatible = compatibility.has_format (F_FLAC);
315         set_compatible (compatible);
316         return compatible;
317 }
318
319 /*** BWF ***/
320
321 ExportFormatBWF::ExportFormatBWF () :
322   HasSampleFormat (sample_formats)
323 {
324         set_name ("BWF");
325         set_format_id (F_WAV);
326
327         add_sample_rate (SR_22_05);
328         add_sample_rate (SR_44_1);
329         add_sample_rate (SR_48);
330         add_sample_rate (SR_88_2);
331         add_sample_rate (SR_96);
332         add_sample_rate (SR_192);
333
334         add_sample_format (SF_U8);
335         add_sample_format (SF_16);
336         add_sample_format (SF_24);
337         add_sample_format (SF_32);
338         add_sample_format (SF_Float);
339         add_sample_format (SF_Double);
340
341         add_endianness (E_FileDefault);
342
343         set_extension ("wav");
344         set_quality (Q_LosslessLinear);
345 }
346
347 bool
348 ExportFormatBWF::set_compatibility_state (ExportFormatCompatibility const & compatibility)
349 {
350         bool compatible = compatibility.has_format (F_WAV);
351         set_compatible (compatible);
352         return compatible;
353 }
354
355 }; // namespace ARDOUR