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